wineoss: Use dedicated macros to call interface functions.
[wine.git] / libs / xml2 / xmlschemas.c
blobf31d3d1f618f7f8419f2d38fb5270000f3fe53a3
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 /* #define DEBUG 1 */
81 /* #define DEBUG_CONTENT 1 */
83 /* #define DEBUG_TYPE 1 */
85 /* #define DEBUG_CONTENT_REGEXP 1 */
87 /* #define DEBUG_AUTOMATA 1 */
89 /* #define DEBUG_IDC */
91 /* #define DEBUG_IDC_NODE_TABLE */
93 /* #define WXS_ELEM_DECL_CONS_ENABLED */
95 #ifdef DEBUG_IDC
96 #ifndef DEBUG_IDC_NODE_TABLE
97 #define DEBUG_IDC_NODE_TABLE
98 #endif
99 #endif
101 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
103 #define ENABLE_REDEFINE
105 /* #define ENABLE_NAMED_LOCALS */
107 /* #define ENABLE_IDC_NODE_TABLES_TEST */
109 #define DUMP_CONTENT_MODEL
111 #ifdef LIBXML_READER_ENABLED
112 /* #define XML_SCHEMA_READER_ENABLED */
113 #endif
115 #define UNBOUNDED (1 << 30)
116 #define TODO \
117 xmlGenericError(xmlGenericErrorContext, \
118 "Unimplemented block at %s:%d\n", \
119 __FILE__, __LINE__);
121 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
124 * The XML Schemas namespaces
126 static const xmlChar *xmlSchemaNs = (const xmlChar *)
127 "http://www.w3.org/2001/XMLSchema";
129 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
130 "http://www.w3.org/2001/XMLSchema-instance";
132 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
133 "http://www.w3.org/2000/xmlns/";
136 * Come casting macros.
138 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
139 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
140 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
141 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
142 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
143 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
144 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
145 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
146 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
147 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
148 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
149 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
150 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
151 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
152 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
153 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
154 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
157 * Macros to query common properties of components.
159 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
161 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
163 * Macros for element declarations.
165 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
167 #define WXS_SUBST_HEAD(item) (item)->refDecl
169 * Macros for attribute declarations.
171 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
173 * Macros for attribute uses.
175 #define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
177 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
179 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
181 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
183 * Macros for attribute groups.
185 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
186 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
188 * Macros for particles.
190 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
192 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
194 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
196 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
198 * Macros for model groups definitions.
200 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
202 * Macros for model groups.
204 #define WXS_IS_MODEL_GROUP(i) \
205 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
206 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
207 ((i)->type == XML_SCHEMA_TYPE_ALL))
209 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
211 * Macros for schema buckets.
213 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
214 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
216 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
217 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
219 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
221 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
223 * Macros for complex/simple types.
225 #define WXS_IS_ANYTYPE(i) \
226 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
227 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
229 #define WXS_IS_COMPLEX(i) \
230 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
231 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
233 #define WXS_IS_SIMPLE(item) \
234 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
235 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
236 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
238 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
239 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
240 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
242 #define WXS_IS_RESTRICTION(t) \
243 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
245 #define WXS_IS_EXTENSION(t) \
246 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
248 #define WXS_IS_TYPE_NOT_FIXED(i) \
249 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
250 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
252 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
253 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
254 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
256 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
258 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
260 * Macros for exclusively for complex types.
262 #define WXS_HAS_COMPLEX_CONTENT(item) \
263 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
264 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
265 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
267 #define WXS_HAS_SIMPLE_CONTENT(item) \
268 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
269 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
271 #define WXS_HAS_MIXED_CONTENT(item) \
272 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
274 #define WXS_EMPTIABLE(t) \
275 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
277 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
279 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
281 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
283 * Macros for exclusively for simple types.
285 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
287 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
289 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
291 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
293 * Misc parser context macros.
295 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
297 #define WXS_HAS_BUCKETS(ctx) \
298 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
299 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
301 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
303 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
305 #define WXS_SCHEMA(ctx) (ctx)->schema
307 #define WXS_ADD_LOCAL(ctx, item) \
308 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
310 #define WXS_ADD_GLOBAL(ctx, item) \
311 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
313 #define WXS_ADD_PENDING(ctx, item) \
314 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
316 * xmlSchemaItemList macros.
318 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
320 * Misc macros.
322 #define IS_SCHEMA(node, type) \
323 ((node != NULL) && (node->ns != NULL) && \
324 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
325 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
327 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
330 * Since we put the default/fixed values into the dict, we can
331 * use pointer comparison for those values.
332 * REMOVED: (xmlStrEqual((v1), (v2)))
334 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
336 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
338 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
340 #define HFAILURE if (res == -1) goto exit_failure;
342 #define HERROR if (res != 0) goto exit_error;
344 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
346 * Some flags used for various schema constraints.
348 #define SUBSET_RESTRICTION 1<<0
349 #define SUBSET_EXTENSION 1<<1
350 #define SUBSET_SUBSTITUTION 1<<2
351 #define SUBSET_LIST 1<<3
352 #define SUBSET_UNION 1<<4
354 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
355 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
357 typedef struct _xmlSchemaItemList xmlSchemaItemList;
358 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
359 struct _xmlSchemaItemList {
360 void **items; /* used for dynamic addition of schemata */
361 int nbItems; /* used for dynamic addition of schemata */
362 int sizeItems; /* used for dynamic addition of schemata */
365 #define XML_SCHEMA_CTXT_PARSER 1
366 #define XML_SCHEMA_CTXT_VALIDATOR 2
368 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
369 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
370 struct _xmlSchemaAbstractCtxt {
371 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
372 void *dummy; /* Fix alignment issues */
375 typedef struct _xmlSchemaBucket xmlSchemaBucket;
376 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
378 #define XML_SCHEMA_SCHEMA_MAIN 0
379 #define XML_SCHEMA_SCHEMA_IMPORT 1
380 #define XML_SCHEMA_SCHEMA_INCLUDE 2
381 #define XML_SCHEMA_SCHEMA_REDEFINE 3
384 * xmlSchemaSchemaRelation:
386 * Used to create a graph of schema relationships.
388 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
389 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
390 struct _xmlSchemaSchemaRelation {
391 xmlSchemaSchemaRelationPtr next;
392 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
393 const xmlChar *importNamespace;
394 xmlSchemaBucketPtr bucket;
397 #define XML_SCHEMA_BUCKET_MARKED 1<<0
398 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
400 struct _xmlSchemaBucket {
401 int type;
402 int flags;
403 const xmlChar *schemaLocation;
404 const xmlChar *origTargetNamespace;
405 const xmlChar *targetNamespace;
406 xmlDocPtr doc;
407 xmlSchemaSchemaRelationPtr relations;
408 int located;
409 int parsed;
410 int imported;
411 int preserveDoc;
412 xmlSchemaItemListPtr globals; /* Global components. */
413 xmlSchemaItemListPtr locals; /* Local components. */
417 * xmlSchemaImport:
418 * (extends xmlSchemaBucket)
420 * Reflects a schema. Holds some information
421 * about the schema and its toplevel components. Duplicate
422 * toplevel components are not checked at this level.
424 typedef struct _xmlSchemaImport xmlSchemaImport;
425 typedef xmlSchemaImport *xmlSchemaImportPtr;
426 struct _xmlSchemaImport {
427 int type; /* Main OR import OR include. */
428 int flags;
429 const xmlChar *schemaLocation; /* The URI of the schema document. */
430 /* For chameleon includes, @origTargetNamespace will be NULL */
431 const xmlChar *origTargetNamespace;
433 * For chameleon includes, @targetNamespace will be the
434 * targetNamespace of the including schema.
436 const xmlChar *targetNamespace;
437 xmlDocPtr doc; /* The schema node-tree. */
438 /* @relations will hold any included/imported/redefined schemas. */
439 xmlSchemaSchemaRelationPtr relations;
440 int located;
441 int parsed;
442 int imported;
443 int preserveDoc;
444 xmlSchemaItemListPtr globals;
445 xmlSchemaItemListPtr locals;
446 /* The imported schema. */
447 xmlSchemaPtr schema;
451 * (extends xmlSchemaBucket)
453 typedef struct _xmlSchemaInclude xmlSchemaInclude;
454 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
455 struct _xmlSchemaInclude {
456 int type;
457 int flags;
458 const xmlChar *schemaLocation;
459 const xmlChar *origTargetNamespace;
460 const xmlChar *targetNamespace;
461 xmlDocPtr doc;
462 xmlSchemaSchemaRelationPtr relations;
463 int located;
464 int parsed;
465 int imported;
466 int preserveDoc;
467 xmlSchemaItemListPtr globals; /* Global components. */
468 xmlSchemaItemListPtr locals; /* Local components. */
470 /* The owning main or import schema bucket. */
471 xmlSchemaImportPtr ownerImport;
475 * xmlSchemaBasicItem:
477 * The abstract base type for schema components.
479 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
480 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
481 struct _xmlSchemaBasicItem {
482 xmlSchemaTypeType type;
483 void *dummy; /* Fix alignment issues */
487 * xmlSchemaAnnotItem:
489 * The abstract base type for annotated schema components.
490 * (Extends xmlSchemaBasicItem)
492 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
493 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
494 struct _xmlSchemaAnnotItem {
495 xmlSchemaTypeType type;
496 xmlSchemaAnnotPtr annot;
500 * xmlSchemaTreeItem:
502 * The abstract base type for tree-like structured schema components.
503 * (Extends xmlSchemaAnnotItem)
505 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
506 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
507 struct _xmlSchemaTreeItem {
508 xmlSchemaTypeType type;
509 xmlSchemaAnnotPtr annot;
510 xmlSchemaTreeItemPtr next;
511 xmlSchemaTreeItemPtr children;
515 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
517 * xmlSchemaAttributeUsePtr:
519 * The abstract base type for tree-like structured schema components.
520 * (Extends xmlSchemaTreeItem)
522 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
523 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
524 struct _xmlSchemaAttributeUse {
525 xmlSchemaTypeType type;
526 xmlSchemaAnnotPtr annot;
527 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
529 * The attr. decl. OR a QName-ref. to an attr. decl. OR
530 * a QName-ref. to an attribute group definition.
532 xmlSchemaAttributePtr attrDecl;
534 int flags;
535 xmlNodePtr node;
536 int occurs; /* required, optional */
537 const xmlChar * defValue;
538 xmlSchemaValPtr defVal;
542 * xmlSchemaAttributeUseProhibPtr:
544 * A helper component to reflect attribute prohibitions.
545 * (Extends xmlSchemaBasicItem)
547 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
548 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
549 struct _xmlSchemaAttributeUseProhib {
550 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
551 xmlNodePtr node;
552 const xmlChar *name;
553 const xmlChar *targetNamespace;
554 int isRef;
558 * xmlSchemaRedef:
560 typedef struct _xmlSchemaRedef xmlSchemaRedef;
561 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
562 struct _xmlSchemaRedef {
563 xmlSchemaRedefPtr next;
564 xmlSchemaBasicItemPtr item; /* The redefining component. */
565 xmlSchemaBasicItemPtr reference; /* The referencing component. */
566 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
567 const xmlChar *refName; /* The name of the to-be-redefined component. */
568 const xmlChar *refTargetNs; /* The target namespace of the
569 to-be-redefined comp. */
570 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
574 * xmlSchemaConstructionCtxt:
576 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
577 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
578 struct _xmlSchemaConstructionCtxt {
579 xmlSchemaPtr mainSchema; /* The main schema. */
580 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
581 xmlDictPtr dict;
582 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
583 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
584 xmlSchemaBucketPtr bucket; /* The current schema bucket */
585 xmlSchemaItemListPtr pending; /* All Components of all schemas that
586 need to be fixed. */
587 xmlHashTablePtr substGroups;
588 xmlSchemaRedefPtr redefs;
589 xmlSchemaRedefPtr lastRedef;
592 #define XML_SCHEMAS_PARSE_ERROR 1
593 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
595 struct _xmlSchemaParserCtxt {
596 int type;
597 void *errCtxt; /* user specific error context */
598 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
599 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
600 int err;
601 int nberrors;
602 xmlStructuredErrorFunc serror;
604 xmlSchemaConstructionCtxtPtr constructor;
605 int ownsConstructor; /* TODO: Move this to parser *flags*. */
607 /* xmlSchemaPtr topschema; */
608 /* xmlHashTablePtr namespaces; */
610 xmlSchemaPtr schema; /* The main schema in use */
611 int counter;
613 const xmlChar *URL;
614 xmlDocPtr doc;
615 int preserve; /* Whether the doc should be freed */
617 const char *buffer;
618 int size;
621 * Used to build complex element content models
623 xmlAutomataPtr am;
624 xmlAutomataStatePtr start;
625 xmlAutomataStatePtr end;
626 xmlAutomataStatePtr state;
628 xmlDictPtr dict; /* dictionary for interned string names */
629 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
630 int options;
631 xmlSchemaValidCtxtPtr vctxt;
632 int isS4S;
633 int isRedefine;
634 int xsiAssemble;
635 int stop; /* If the parser should stop; i.e. a critical error. */
636 const xmlChar *targetNamespace;
637 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
639 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
640 int redefCounter; /* Used for redefinitions. */
641 xmlSchemaItemListPtr attrProhibs;
645 * xmlSchemaQNameRef:
647 * A component reference item (not a schema component)
648 * (Extends xmlSchemaBasicItem)
650 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
651 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
652 struct _xmlSchemaQNameRef {
653 xmlSchemaTypeType type;
654 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
655 xmlSchemaTypeType itemType;
656 const xmlChar *name;
657 const xmlChar *targetNamespace;
658 xmlNodePtr node;
662 * xmlSchemaParticle:
664 * A particle component.
665 * (Extends xmlSchemaTreeItem)
667 typedef struct _xmlSchemaParticle xmlSchemaParticle;
668 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
669 struct _xmlSchemaParticle {
670 xmlSchemaTypeType type;
671 xmlSchemaAnnotPtr annot;
672 xmlSchemaTreeItemPtr next; /* next particle */
673 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
674 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
675 etc.) */
676 int minOccurs;
677 int maxOccurs;
678 xmlNodePtr node;
682 * xmlSchemaModelGroup:
684 * A model group component.
685 * (Extends xmlSchemaTreeItem)
687 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
688 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
689 struct _xmlSchemaModelGroup {
690 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
691 xmlSchemaAnnotPtr annot;
692 xmlSchemaTreeItemPtr next; /* not used */
693 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
694 xmlNodePtr node;
697 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
698 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
700 * xmlSchemaModelGroupDef:
702 * A model group definition component.
703 * (Extends xmlSchemaTreeItem)
705 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
706 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
707 struct _xmlSchemaModelGroupDef {
708 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
709 xmlSchemaAnnotPtr annot;
710 xmlSchemaTreeItemPtr next; /* not used */
711 xmlSchemaTreeItemPtr children; /* the "model group" */
712 const xmlChar *name;
713 const xmlChar *targetNamespace;
714 xmlNodePtr node;
715 int flags;
718 typedef struct _xmlSchemaIDC xmlSchemaIDC;
719 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
722 * xmlSchemaIDCSelect:
724 * The identity-constraint "field" and "selector" item, holding the
725 * XPath expression.
727 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
728 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
729 struct _xmlSchemaIDCSelect {
730 xmlSchemaIDCSelectPtr next;
731 xmlSchemaIDCPtr idc;
732 int index; /* an index position if significant for IDC key-sequences */
733 const xmlChar *xpath; /* the XPath expression */
734 void *xpathComp; /* the compiled XPath expression */
738 * xmlSchemaIDC:
740 * The identity-constraint definition component.
741 * (Extends xmlSchemaAnnotItem)
744 struct _xmlSchemaIDC {
745 xmlSchemaTypeType type;
746 xmlSchemaAnnotPtr annot;
747 xmlSchemaIDCPtr next;
748 xmlNodePtr node;
749 const xmlChar *name;
750 const xmlChar *targetNamespace;
751 xmlSchemaIDCSelectPtr selector;
752 xmlSchemaIDCSelectPtr fields;
753 int nbFields;
754 xmlSchemaQNameRefPtr ref;
758 * xmlSchemaIDCAug:
760 * The augmented IDC information used for validation.
762 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
763 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
764 struct _xmlSchemaIDCAug {
765 xmlSchemaIDCAugPtr next; /* next in a list */
766 xmlSchemaIDCPtr def; /* the IDC definition */
767 int keyrefDepth; /* the lowest tree level to which IDC
768 tables need to be bubbled upwards */
772 * xmlSchemaPSVIIDCKeySequence:
774 * The key sequence of a node table item.
776 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
777 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
778 struct _xmlSchemaPSVIIDCKey {
779 xmlSchemaTypePtr type;
780 xmlSchemaValPtr val;
784 * xmlSchemaPSVIIDCNode:
786 * The node table item of a node table.
788 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
789 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
790 struct _xmlSchemaPSVIIDCNode {
791 xmlNodePtr node;
792 xmlSchemaPSVIIDCKeyPtr *keys;
793 int nodeLine;
794 int nodeQNameID;
799 * xmlSchemaPSVIIDCBinding:
801 * The identity-constraint binding item of the [identity-constraint table].
803 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
804 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
805 struct _xmlSchemaPSVIIDCBinding {
806 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
807 xmlSchemaIDCPtr definition; /* the IDC definition */
808 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
809 int nbNodes; /* number of entries in the node table */
810 int sizeNodes; /* size of the node table */
811 xmlSchemaItemListPtr dupls;
815 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
816 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
818 #define XPATH_STATE_OBJ_MATCHES -2
819 #define XPATH_STATE_OBJ_BLOCKED -3
821 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
822 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
825 * xmlSchemaIDCStateObj:
827 * The state object used to evaluate XPath expressions.
829 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
830 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
831 struct _xmlSchemaIDCStateObj {
832 int type;
833 xmlSchemaIDCStateObjPtr next; /* next if in a list */
834 int depth; /* depth of creation */
835 int *history; /* list of (depth, state-id) tuples */
836 int nbHistory;
837 int sizeHistory;
838 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
839 matcher */
840 xmlSchemaIDCSelectPtr sel;
841 void *xpathCtxt;
844 #define IDC_MATCHER 0
847 * xmlSchemaIDCMatcher:
849 * Used to evaluate IDC selectors (and fields).
851 struct _xmlSchemaIDCMatcher {
852 int type;
853 int depth; /* the tree depth at creation time */
854 xmlSchemaIDCMatcherPtr next; /* next in the list */
855 xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
856 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
857 int idcType;
858 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
859 elements */
860 int sizeKeySeqs;
861 xmlSchemaItemListPtr targets; /* list of target-node
862 (xmlSchemaPSVIIDCNodePtr) entries */
863 xmlHashTablePtr htab;
867 * Element info flags.
869 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
870 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
871 #define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
872 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
874 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
875 #define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
876 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
878 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
879 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
880 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
881 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
884 * xmlSchemaNodeInfo:
886 * Holds information of an element node.
888 struct _xmlSchemaNodeInfo {
889 int nodeType;
890 xmlNodePtr node;
891 int nodeLine;
892 const xmlChar *localName;
893 const xmlChar *nsName;
894 const xmlChar *value;
895 xmlSchemaValPtr val; /* the pre-computed value if any */
896 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
898 int flags; /* combination of node info flags */
900 int valNeeded;
901 int normVal;
903 xmlSchemaElementPtr decl; /* the element/attribute declaration */
904 int depth;
905 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
906 for the scope element*/
907 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
908 element */
909 xmlRegExecCtxtPtr regexCtxt;
911 const xmlChar **nsBindings; /* Namespace bindings on this element */
912 int nbNsBindings;
913 int sizeNsBindings;
915 int hasKeyrefs;
916 int appliedXPath; /* Indicates that an XPath has been applied. */
919 #define XML_SCHEMAS_ATTR_UNKNOWN 1
920 #define XML_SCHEMAS_ATTR_ASSESSED 2
921 #define XML_SCHEMAS_ATTR_PROHIBITED 3
922 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
923 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
924 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
925 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
926 #define XML_SCHEMAS_ATTR_DEFAULT 8
927 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
928 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
929 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
930 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
931 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
932 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
933 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
934 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
935 #define XML_SCHEMAS_ATTR_META 17
937 * @metaType values of xmlSchemaAttrInfo.
939 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
940 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
941 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
942 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
943 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
945 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
946 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
947 struct _xmlSchemaAttrInfo {
948 int nodeType;
949 xmlNodePtr node;
950 int nodeLine;
951 const xmlChar *localName;
952 const xmlChar *nsName;
953 const xmlChar *value;
954 xmlSchemaValPtr val; /* the pre-computed value if any */
955 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
956 int flags; /* combination of node info flags */
958 xmlSchemaAttributePtr decl; /* the attribute declaration */
959 xmlSchemaAttributeUsePtr use; /* the attribute use */
960 int state;
961 int metaType;
962 const xmlChar *vcValue; /* the value constraint value */
963 xmlSchemaNodeInfoPtr parent;
967 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
969 * xmlSchemaValidCtxt:
971 * A Schemas validation context
973 struct _xmlSchemaValidCtxt {
974 int type;
975 void *errCtxt; /* user specific data block */
976 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
977 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
978 xmlStructuredErrorFunc serror;
980 xmlSchemaPtr schema; /* The schema in use */
981 xmlDocPtr doc;
982 xmlParserInputBufferPtr input;
983 xmlCharEncoding enc;
984 xmlSAXHandlerPtr sax;
985 xmlParserCtxtPtr parserCtxt;
986 void *user_data; /* TODO: What is this for? */
987 char *filename;
989 int err;
990 int nberrors;
992 xmlNodePtr node;
993 xmlNodePtr cur;
994 /* xmlSchemaTypePtr type; */
996 xmlRegExecCtxtPtr regexp;
997 xmlSchemaValPtr value;
999 int valueWS;
1000 int options;
1001 xmlNodePtr validationRoot;
1002 xmlSchemaParserCtxtPtr pctxt;
1003 int xsiAssemble;
1005 int depth;
1006 xmlSchemaNodeInfoPtr *elemInfos; /* array of element information */
1007 int sizeElemInfos;
1008 xmlSchemaNodeInfoPtr inode; /* the current element information */
1010 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC information */
1012 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1013 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1014 xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1016 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1017 int nbIdcNodes;
1018 int sizeIdcNodes;
1020 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1021 int nbIdcKeys;
1022 int sizeIdcKeys;
1024 int flags;
1026 xmlDictPtr dict;
1028 #ifdef LIBXML_READER_ENABLED
1029 xmlTextReaderPtr reader;
1030 #endif
1032 xmlSchemaAttrInfoPtr *attrInfos;
1033 int nbAttrInfos;
1034 int sizeAttrInfos;
1036 int skipDepth;
1037 xmlSchemaItemListPtr nodeQNames;
1038 int hasKeyrefs;
1039 int createIDCNodeTables;
1040 int psviExposeIDCNodeTables;
1042 /* Locator for error reporting in streaming mode */
1043 xmlSchemaValidityLocatorFunc locFunc;
1044 void *locCtxt;
1048 * xmlSchemaSubstGroup:
1052 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1053 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1054 struct _xmlSchemaSubstGroup {
1055 xmlSchemaElementPtr head;
1056 xmlSchemaItemListPtr members;
1060 * xmlIDCHashEntry:
1062 * an entry in hash tables to quickly look up keys/uniques
1064 typedef struct _xmlIDCHashEntry xmlIDCHashEntry;
1065 typedef xmlIDCHashEntry *xmlIDCHashEntryPtr;
1066 struct _xmlIDCHashEntry {
1067 xmlIDCHashEntryPtr next; /* next item with same hash */
1068 int index; /* index into associated item list */
1071 /************************************************************************
1073 * Some predeclarations *
1075 ************************************************************************/
1077 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1078 xmlSchemaPtr schema,
1079 xmlNodePtr node);
1080 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1081 xmlSchemaPtr schema,
1082 xmlNodePtr node);
1083 static int
1084 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1085 xmlSchemaAbstractCtxtPtr ctxt);
1086 static const xmlChar *
1087 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1088 static int
1089 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1090 xmlNodePtr node);
1091 static int
1092 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1093 xmlSchemaParserCtxtPtr ctxt);
1094 static void
1095 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1096 static xmlSchemaWhitespaceValueType
1097 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1098 static xmlSchemaTreeItemPtr
1099 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1100 xmlNodePtr node, xmlSchemaTypeType type,
1101 int withParticle);
1102 static const xmlChar *
1103 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1104 static xmlSchemaTypeLinkPtr
1105 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1106 static void
1107 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1108 const char *funcName,
1109 const char *message) LIBXML_ATTR_FORMAT(3,0);
1110 static int
1111 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1112 xmlSchemaTypePtr type,
1113 xmlSchemaTypePtr baseType,
1114 int subset);
1115 static void
1116 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1117 xmlSchemaParserCtxtPtr ctxt);
1118 static void
1119 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1120 static xmlSchemaQNameRefPtr
1121 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1122 xmlSchemaPtr schema,
1123 xmlNodePtr node);
1125 /************************************************************************
1127 * Helper functions *
1129 ************************************************************************/
1132 * xmlSchemaItemTypeToStr:
1133 * @type: the type of the schema item
1135 * Returns the component name of a schema item.
1137 static const xmlChar *
1138 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1140 switch (type) {
1141 case XML_SCHEMA_TYPE_BASIC:
1142 return(BAD_CAST "simple type definition");
1143 case XML_SCHEMA_TYPE_SIMPLE:
1144 return(BAD_CAST "simple type definition");
1145 case XML_SCHEMA_TYPE_COMPLEX:
1146 return(BAD_CAST "complex type definition");
1147 case XML_SCHEMA_TYPE_ELEMENT:
1148 return(BAD_CAST "element declaration");
1149 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1150 return(BAD_CAST "attribute use");
1151 case XML_SCHEMA_TYPE_ATTRIBUTE:
1152 return(BAD_CAST "attribute declaration");
1153 case XML_SCHEMA_TYPE_GROUP:
1154 return(BAD_CAST "model group definition");
1155 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1156 return(BAD_CAST "attribute group definition");
1157 case XML_SCHEMA_TYPE_NOTATION:
1158 return(BAD_CAST "notation declaration");
1159 case XML_SCHEMA_TYPE_SEQUENCE:
1160 return(BAD_CAST "model group (sequence)");
1161 case XML_SCHEMA_TYPE_CHOICE:
1162 return(BAD_CAST "model group (choice)");
1163 case XML_SCHEMA_TYPE_ALL:
1164 return(BAD_CAST "model group (all)");
1165 case XML_SCHEMA_TYPE_PARTICLE:
1166 return(BAD_CAST "particle");
1167 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1168 return(BAD_CAST "unique identity-constraint");
1169 /* return(BAD_CAST "IDC (unique)"); */
1170 case XML_SCHEMA_TYPE_IDC_KEY:
1171 return(BAD_CAST "key identity-constraint");
1172 /* return(BAD_CAST "IDC (key)"); */
1173 case XML_SCHEMA_TYPE_IDC_KEYREF:
1174 return(BAD_CAST "keyref identity-constraint");
1175 /* return(BAD_CAST "IDC (keyref)"); */
1176 case XML_SCHEMA_TYPE_ANY:
1177 return(BAD_CAST "wildcard (any)");
1178 case XML_SCHEMA_EXTRA_QNAMEREF:
1179 return(BAD_CAST "[helper component] QName reference");
1180 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1181 return(BAD_CAST "[helper component] attribute use prohibition");
1182 default:
1183 return(BAD_CAST "Not a schema component");
1188 * xmlSchemaGetComponentTypeStr:
1189 * @type: the type of the schema item
1191 * Returns the component name of a schema item.
1193 static const xmlChar *
1194 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1196 switch (item->type) {
1197 case XML_SCHEMA_TYPE_BASIC:
1198 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1199 return(BAD_CAST "complex type definition");
1200 else
1201 return(BAD_CAST "simple type definition");
1202 default:
1203 return(xmlSchemaItemTypeToStr(item->type));
1208 * xmlSchemaGetComponentNode:
1209 * @item: a schema component
1211 * Returns node associated with the schema component.
1212 * NOTE that such a node need not be available; plus, a component's
1213 * node need not to reflect the component directly, since there is no
1214 * one-to-one relationship between the XML Schema representation and
1215 * the component representation.
1217 static xmlNodePtr
1218 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1220 switch (item->type) {
1221 case XML_SCHEMA_TYPE_ELEMENT:
1222 return (((xmlSchemaElementPtr) item)->node);
1223 case XML_SCHEMA_TYPE_ATTRIBUTE:
1224 return (((xmlSchemaAttributePtr) item)->node);
1225 case XML_SCHEMA_TYPE_COMPLEX:
1226 case XML_SCHEMA_TYPE_SIMPLE:
1227 return (((xmlSchemaTypePtr) item)->node);
1228 case XML_SCHEMA_TYPE_ANY:
1229 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1230 return (((xmlSchemaWildcardPtr) item)->node);
1231 case XML_SCHEMA_TYPE_PARTICLE:
1232 return (((xmlSchemaParticlePtr) item)->node);
1233 case XML_SCHEMA_TYPE_SEQUENCE:
1234 case XML_SCHEMA_TYPE_CHOICE:
1235 case XML_SCHEMA_TYPE_ALL:
1236 return (((xmlSchemaModelGroupPtr) item)->node);
1237 case XML_SCHEMA_TYPE_GROUP:
1238 return (((xmlSchemaModelGroupDefPtr) item)->node);
1239 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1240 return (((xmlSchemaAttributeGroupPtr) item)->node);
1241 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1242 case XML_SCHEMA_TYPE_IDC_KEY:
1243 case XML_SCHEMA_TYPE_IDC_KEYREF:
1244 return (((xmlSchemaIDCPtr) item)->node);
1245 case XML_SCHEMA_EXTRA_QNAMEREF:
1246 return(((xmlSchemaQNameRefPtr) item)->node);
1247 /* TODO: What to do with NOTATIONs?
1248 case XML_SCHEMA_TYPE_NOTATION:
1249 return (((xmlSchemaNotationPtr) item)->node);
1251 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1252 return (((xmlSchemaAttributeUsePtr) item)->node);
1253 default:
1254 return (NULL);
1258 #if 0
1260 * xmlSchemaGetNextComponent:
1261 * @item: a schema component
1263 * Returns the next sibling of the schema component.
1265 static xmlSchemaBasicItemPtr
1266 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1268 switch (item->type) {
1269 case XML_SCHEMA_TYPE_ELEMENT:
1270 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1271 case XML_SCHEMA_TYPE_ATTRIBUTE:
1272 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1273 case XML_SCHEMA_TYPE_COMPLEX:
1274 case XML_SCHEMA_TYPE_SIMPLE:
1275 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1276 case XML_SCHEMA_TYPE_ANY:
1277 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1278 return (NULL);
1279 case XML_SCHEMA_TYPE_PARTICLE:
1280 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1281 case XML_SCHEMA_TYPE_SEQUENCE:
1282 case XML_SCHEMA_TYPE_CHOICE:
1283 case XML_SCHEMA_TYPE_ALL:
1284 return (NULL);
1285 case XML_SCHEMA_TYPE_GROUP:
1286 return (NULL);
1287 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1288 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1289 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1290 case XML_SCHEMA_TYPE_IDC_KEY:
1291 case XML_SCHEMA_TYPE_IDC_KEYREF:
1292 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1293 default:
1294 return (NULL);
1297 #endif
1301 * xmlSchemaFormatQName:
1302 * @buf: the string buffer
1303 * @namespaceName: the namespace name
1304 * @localName: the local name
1306 * Returns the given QName in the format "{namespaceName}localName" or
1307 * just "localName" if @namespaceName is NULL.
1309 * Returns the localName if @namespaceName is NULL, a formatted
1310 * string otherwise.
1312 static const xmlChar*
1313 xmlSchemaFormatQName(xmlChar **buf,
1314 const xmlChar *namespaceName,
1315 const xmlChar *localName)
1317 FREE_AND_NULL(*buf)
1318 if (namespaceName != NULL) {
1319 *buf = xmlStrdup(BAD_CAST "{");
1320 *buf = xmlStrcat(*buf, namespaceName);
1321 *buf = xmlStrcat(*buf, BAD_CAST "}");
1323 if (localName != NULL) {
1324 if (namespaceName == NULL)
1325 return(localName);
1326 *buf = xmlStrcat(*buf, localName);
1327 } else {
1328 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1330 return ((const xmlChar *) *buf);
1333 static const xmlChar*
1334 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1336 if (ns != NULL)
1337 return (xmlSchemaFormatQName(buf, ns->href, localName));
1338 else
1339 return (xmlSchemaFormatQName(buf, NULL, localName));
1342 static const xmlChar *
1343 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1345 if (item == NULL) {
1346 return (NULL);
1348 switch (item->type) {
1349 case XML_SCHEMA_TYPE_ELEMENT:
1350 return (((xmlSchemaElementPtr) item)->name);
1351 case XML_SCHEMA_TYPE_ATTRIBUTE:
1352 return (((xmlSchemaAttributePtr) item)->name);
1353 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1354 return (((xmlSchemaAttributeGroupPtr) item)->name);
1355 case XML_SCHEMA_TYPE_BASIC:
1356 case XML_SCHEMA_TYPE_SIMPLE:
1357 case XML_SCHEMA_TYPE_COMPLEX:
1358 return (((xmlSchemaTypePtr) item)->name);
1359 case XML_SCHEMA_TYPE_GROUP:
1360 return (((xmlSchemaModelGroupDefPtr) item)->name);
1361 case XML_SCHEMA_TYPE_IDC_KEY:
1362 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1363 case XML_SCHEMA_TYPE_IDC_KEYREF:
1364 return (((xmlSchemaIDCPtr) item)->name);
1365 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1366 if (WXS_ATTRUSE_DECL(item) != NULL) {
1367 return(xmlSchemaGetComponentName(
1368 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1369 } else
1370 return(NULL);
1371 case XML_SCHEMA_EXTRA_QNAMEREF:
1372 return (((xmlSchemaQNameRefPtr) item)->name);
1373 case XML_SCHEMA_TYPE_NOTATION:
1374 return (((xmlSchemaNotationPtr) item)->name);
1375 default:
1377 * Other components cannot have names.
1379 break;
1381 return (NULL);
1384 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1385 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1387 static const xmlChar *
1388 xmlSchemaGetQNameRefName(void *ref)
1390 return(((xmlSchemaQNameRefPtr) ref)->name);
1393 static const xmlChar *
1394 xmlSchemaGetQNameRefTargetNs(void *ref)
1396 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1400 static const xmlChar *
1401 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1403 if (item == NULL) {
1404 return (NULL);
1406 switch (item->type) {
1407 case XML_SCHEMA_TYPE_ELEMENT:
1408 return (((xmlSchemaElementPtr) item)->targetNamespace);
1409 case XML_SCHEMA_TYPE_ATTRIBUTE:
1410 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1411 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1412 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1413 case XML_SCHEMA_TYPE_BASIC:
1414 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1415 case XML_SCHEMA_TYPE_SIMPLE:
1416 case XML_SCHEMA_TYPE_COMPLEX:
1417 return (((xmlSchemaTypePtr) item)->targetNamespace);
1418 case XML_SCHEMA_TYPE_GROUP:
1419 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1420 case XML_SCHEMA_TYPE_IDC_KEY:
1421 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1422 case XML_SCHEMA_TYPE_IDC_KEYREF:
1423 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1424 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1425 if (WXS_ATTRUSE_DECL(item) != NULL) {
1426 return(xmlSchemaGetComponentTargetNs(
1427 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1429 /* TODO: Will returning NULL break something? */
1430 break;
1431 case XML_SCHEMA_EXTRA_QNAMEREF:
1432 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1433 case XML_SCHEMA_TYPE_NOTATION:
1434 return (((xmlSchemaNotationPtr) item)->targetNamespace);
1435 default:
1437 * Other components cannot have names.
1439 break;
1441 return (NULL);
1444 static const xmlChar*
1445 xmlSchemaGetComponentQName(xmlChar **buf,
1446 void *item)
1448 return (xmlSchemaFormatQName(buf,
1449 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1450 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1453 static const xmlChar*
1454 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1456 xmlChar *str = NULL;
1458 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1459 *buf = xmlStrcat(*buf, BAD_CAST " '");
1460 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1461 (xmlSchemaBasicItemPtr) item));
1462 *buf = xmlStrcat(*buf, BAD_CAST "'");
1463 FREE_AND_NULL(str);
1464 return(*buf);
1467 static const xmlChar*
1468 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1470 return(xmlSchemaGetComponentDesignation(buf, idc));
1474 * xmlSchemaWildcardPCToString:
1475 * @pc: the type of processContents
1477 * Returns a string representation of the type of
1478 * processContents.
1480 static const xmlChar *
1481 xmlSchemaWildcardPCToString(int pc)
1483 switch (pc) {
1484 case XML_SCHEMAS_ANY_SKIP:
1485 return (BAD_CAST "skip");
1486 case XML_SCHEMAS_ANY_LAX:
1487 return (BAD_CAST "lax");
1488 case XML_SCHEMAS_ANY_STRICT:
1489 return (BAD_CAST "strict");
1490 default:
1491 return (BAD_CAST "invalid process contents");
1496 * xmlSchemaGetCanonValueWhtspExt:
1497 * @val: the precomputed value
1498 * @retValue: the returned value
1499 * @ws: the whitespace type of the value
1500 * @for_hash: non-zero if this is supposed to generate a string for hashing
1502 * Get a the canonical representation of the value.
1503 * The caller has to free the returned retValue.
1505 * Returns 0 if the value could be built and -1 in case of
1506 * API errors or if the value type is not supported yet.
1508 static int
1509 xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
1510 xmlSchemaWhitespaceValueType ws,
1511 xmlChar **retValue,
1512 int for_hash)
1514 int list;
1515 xmlSchemaValType valType;
1516 const xmlChar *value, *value2 = NULL;
1519 if ((retValue == NULL) || (val == NULL))
1520 return (-1);
1521 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1522 *retValue = NULL;
1523 do {
1524 value = NULL;
1525 valType = xmlSchemaGetValType(val);
1526 switch (valType) {
1527 case XML_SCHEMAS_STRING:
1528 case XML_SCHEMAS_NORMSTRING:
1529 case XML_SCHEMAS_ANYSIMPLETYPE:
1530 value = xmlSchemaValueGetAsString(val);
1531 if (value != NULL) {
1532 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1533 value2 = xmlSchemaCollapseString(value);
1534 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1535 value2 = xmlSchemaWhiteSpaceReplace(value);
1536 if (value2 != NULL)
1537 value = value2;
1539 break;
1540 default:
1541 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1542 if (value2 != NULL)
1543 xmlFree((xmlChar *) value2);
1544 goto internal_error;
1546 if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
1547 /* We can mostly use the canonical value for hashing,
1548 except in the case of decimal. There the canonical
1549 representation requires a trailing '.0' even for
1550 non-fractional numbers, but for the derived integer
1551 types it forbids any decimal point. Nevertheless they
1552 compare equal if the value is equal. We need to generate
1553 the same hash value for this to work, and it's easiest
1554 to just cut off the useless '.0' suffix for the
1555 decimal type. */
1556 int len = xmlStrlen(value2);
1557 if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
1558 ((xmlChar*)value2)[len-2] = 0;
1560 value = value2;
1562 if (*retValue == NULL)
1563 if (value == NULL) {
1564 if (! list)
1565 *retValue = xmlStrdup(BAD_CAST "");
1566 } else
1567 *retValue = xmlStrdup(value);
1568 else if (value != NULL) {
1569 /* List. */
1570 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1571 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1573 FREE_AND_NULL(value2)
1574 val = xmlSchemaValueGetNext(val);
1575 } while (val != NULL);
1577 return (0);
1578 internal_error:
1579 if (*retValue != NULL)
1580 xmlFree((xmlChar *) (*retValue));
1581 if (value2 != NULL)
1582 xmlFree((xmlChar *) value2);
1583 return (-1);
1586 static int
1587 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1588 xmlSchemaWhitespaceValueType ws,
1589 xmlChar **retValue)
1591 return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
1594 static int
1595 xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
1596 xmlChar **retValue)
1598 return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
1599 retValue, 1);
1603 * xmlSchemaFormatItemForReport:
1604 * @buf: the string buffer
1605 * @itemDes: the designation of the item
1606 * @itemName: the name of the item
1607 * @item: the item as an object
1608 * @itemNode: the node of the item
1609 * @local: the local name
1610 * @parsing: if the function is used during the parse
1612 * Returns a representation of the given item used
1613 * for error reports.
1615 * The following order is used to build the resulting
1616 * designation if the arguments are not NULL:
1617 * 1a. If itemDes not NULL -> itemDes
1618 * 1b. If (itemDes not NULL) and (itemName not NULL)
1619 * -> itemDes + itemName
1620 * 2. If the preceding was NULL and (item not NULL) -> item
1621 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1623 * If the itemNode is an attribute node, the name of the attribute
1624 * will be appended to the result.
1626 * Returns the formatted string and sets @buf to the resulting value.
1628 static xmlChar*
1629 xmlSchemaFormatItemForReport(xmlChar **buf,
1630 const xmlChar *itemDes,
1631 xmlSchemaBasicItemPtr item,
1632 xmlNodePtr itemNode)
1634 xmlChar *str = NULL;
1635 int named = 1;
1637 if (*buf != NULL) {
1638 xmlFree(*buf);
1639 *buf = NULL;
1642 if (itemDes != NULL) {
1643 *buf = xmlStrdup(itemDes);
1644 } else if (item != NULL) {
1645 switch (item->type) {
1646 case XML_SCHEMA_TYPE_BASIC: {
1647 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1649 if (WXS_IS_ATOMIC(type))
1650 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1651 else if (WXS_IS_LIST(type))
1652 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1653 else if (WXS_IS_UNION(type))
1654 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1655 else
1656 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1657 *buf = xmlStrcat(*buf, type->name);
1658 *buf = xmlStrcat(*buf, BAD_CAST "'");
1660 break;
1661 case XML_SCHEMA_TYPE_SIMPLE: {
1662 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1664 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1665 *buf = xmlStrdup(BAD_CAST"");
1666 } else {
1667 *buf = xmlStrdup(BAD_CAST "local ");
1669 if (WXS_IS_ATOMIC(type))
1670 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1671 else if (WXS_IS_LIST(type))
1672 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1673 else if (WXS_IS_UNION(type))
1674 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1675 else
1676 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1677 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1678 *buf = xmlStrcat(*buf, BAD_CAST " '");
1679 *buf = xmlStrcat(*buf, type->name);
1680 *buf = xmlStrcat(*buf, BAD_CAST "'");
1683 break;
1684 case XML_SCHEMA_TYPE_COMPLEX: {
1685 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1687 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1688 *buf = xmlStrdup(BAD_CAST "");
1689 else
1690 *buf = xmlStrdup(BAD_CAST "local ");
1691 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1692 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1693 *buf = xmlStrcat(*buf, BAD_CAST " '");
1694 *buf = xmlStrcat(*buf, type->name);
1695 *buf = xmlStrcat(*buf, BAD_CAST "'");
1698 break;
1699 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1700 xmlSchemaAttributeUsePtr ause;
1702 ause = WXS_ATTR_USE_CAST item;
1703 *buf = xmlStrdup(BAD_CAST "attribute use ");
1704 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1705 *buf = xmlStrcat(*buf, BAD_CAST "'");
1706 *buf = xmlStrcat(*buf,
1707 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1708 FREE_AND_NULL(str)
1709 *buf = xmlStrcat(*buf, BAD_CAST "'");
1710 } else {
1711 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1714 break;
1715 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1716 xmlSchemaAttributePtr attr;
1718 attr = (xmlSchemaAttributePtr) item;
1719 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1720 *buf = xmlStrcat(*buf, BAD_CAST " '");
1721 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1722 attr->targetNamespace, attr->name));
1723 FREE_AND_NULL(str)
1724 *buf = xmlStrcat(*buf, BAD_CAST "'");
1726 break;
1727 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1728 xmlSchemaGetComponentDesignation(buf, item);
1729 break;
1730 case XML_SCHEMA_TYPE_ELEMENT: {
1731 xmlSchemaElementPtr elem;
1733 elem = (xmlSchemaElementPtr) item;
1734 *buf = xmlStrdup(BAD_CAST "element decl.");
1735 *buf = xmlStrcat(*buf, BAD_CAST " '");
1736 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1737 elem->targetNamespace, elem->name));
1738 *buf = xmlStrcat(*buf, BAD_CAST "'");
1740 break;
1741 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1742 case XML_SCHEMA_TYPE_IDC_KEY:
1743 case XML_SCHEMA_TYPE_IDC_KEYREF:
1744 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1745 *buf = xmlStrdup(BAD_CAST "unique '");
1746 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1747 *buf = xmlStrdup(BAD_CAST "key '");
1748 else
1749 *buf = xmlStrdup(BAD_CAST "keyRef '");
1750 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1751 *buf = xmlStrcat(*buf, BAD_CAST "'");
1752 break;
1753 case XML_SCHEMA_TYPE_ANY:
1754 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1755 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1756 ((xmlSchemaWildcardPtr) item)->processContents));
1757 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1758 break;
1759 case XML_SCHEMA_FACET_MININCLUSIVE:
1760 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1761 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1762 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1763 case XML_SCHEMA_FACET_TOTALDIGITS:
1764 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1765 case XML_SCHEMA_FACET_PATTERN:
1766 case XML_SCHEMA_FACET_ENUMERATION:
1767 case XML_SCHEMA_FACET_WHITESPACE:
1768 case XML_SCHEMA_FACET_LENGTH:
1769 case XML_SCHEMA_FACET_MAXLENGTH:
1770 case XML_SCHEMA_FACET_MINLENGTH:
1771 *buf = xmlStrdup(BAD_CAST "facet '");
1772 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1773 *buf = xmlStrcat(*buf, BAD_CAST "'");
1774 break;
1775 case XML_SCHEMA_TYPE_GROUP: {
1776 *buf = xmlStrdup(BAD_CAST "model group def.");
1777 *buf = xmlStrcat(*buf, BAD_CAST " '");
1778 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1779 *buf = xmlStrcat(*buf, BAD_CAST "'");
1780 FREE_AND_NULL(str)
1782 break;
1783 case XML_SCHEMA_TYPE_SEQUENCE:
1784 case XML_SCHEMA_TYPE_CHOICE:
1785 case XML_SCHEMA_TYPE_ALL:
1786 case XML_SCHEMA_TYPE_PARTICLE:
1787 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1788 break;
1789 case XML_SCHEMA_TYPE_NOTATION: {
1790 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1791 *buf = xmlStrcat(*buf, BAD_CAST " '");
1792 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1793 *buf = xmlStrcat(*buf, BAD_CAST "'");
1794 FREE_AND_NULL(str);
1796 /* Falls through. */
1797 default:
1798 named = 0;
1800 } else
1801 named = 0;
1803 if ((named == 0) && (itemNode != NULL)) {
1804 xmlNodePtr elem;
1806 if (itemNode->type == XML_ATTRIBUTE_NODE)
1807 elem = itemNode->parent;
1808 else
1809 elem = itemNode;
1810 *buf = xmlStrdup(BAD_CAST "Element '");
1811 if (elem->ns != NULL) {
1812 *buf = xmlStrcat(*buf,
1813 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1814 FREE_AND_NULL(str)
1815 } else
1816 *buf = xmlStrcat(*buf, elem->name);
1817 *buf = xmlStrcat(*buf, BAD_CAST "'");
1820 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1821 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1822 if (itemNode->ns != NULL) {
1823 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1824 itemNode->ns->href, itemNode->name));
1825 FREE_AND_NULL(str)
1826 } else
1827 *buf = xmlStrcat(*buf, itemNode->name);
1828 *buf = xmlStrcat(*buf, BAD_CAST "'");
1830 FREE_AND_NULL(str)
1832 return (xmlEscapeFormatString(buf));
1836 * xmlSchemaFormatFacetEnumSet:
1837 * @buf: the string buffer
1838 * @type: the type holding the enumeration facets
1840 * Builds a string consisting of all enumeration elements.
1842 * Returns a string of all enumeration elements.
1844 static const xmlChar *
1845 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1846 xmlChar **buf, xmlSchemaTypePtr type)
1848 xmlSchemaFacetPtr facet;
1849 xmlSchemaWhitespaceValueType ws;
1850 xmlChar *value = NULL;
1851 int res, found = 0;
1853 if (*buf != NULL)
1854 xmlFree(*buf);
1855 *buf = NULL;
1857 do {
1859 * Use the whitespace type of the base type.
1861 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1862 for (facet = type->facets; facet != NULL; facet = facet->next) {
1863 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1864 continue;
1865 found = 1;
1866 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1867 ws, &value);
1868 if (res == -1) {
1869 xmlSchemaInternalErr(actxt,
1870 "xmlSchemaFormatFacetEnumSet",
1871 "compute the canonical lexical representation");
1872 if (*buf != NULL)
1873 xmlFree(*buf);
1874 *buf = NULL;
1875 return (NULL);
1877 if (*buf == NULL)
1878 *buf = xmlStrdup(BAD_CAST "'");
1879 else
1880 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1881 *buf = xmlStrcat(*buf, BAD_CAST value);
1882 *buf = xmlStrcat(*buf, BAD_CAST "'");
1883 if (value != NULL) {
1884 xmlFree((xmlChar *)value);
1885 value = NULL;
1889 * The enumeration facet of a type restricts the enumeration
1890 * facet of the ancestor type; i.e., such restricted enumerations
1891 * do not belong to the set of the given type. Thus we break
1892 * on the first found enumeration.
1894 if (found)
1895 break;
1896 type = type->baseType;
1897 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1899 return ((const xmlChar *) *buf);
1902 /************************************************************************
1904 * Error functions *
1906 ************************************************************************/
1908 #if 0
1909 static void
1910 xmlSchemaErrMemory(const char *msg)
1912 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1913 msg);
1915 #endif
1917 static void
1918 xmlSchemaPSimpleErr(const char *msg)
1920 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1921 msg);
1925 * xmlSchemaPErrMemory:
1926 * @node: a context node
1927 * @extra: extra information
1929 * Handle an out of memory condition
1931 static void
1932 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1933 const char *extra, xmlNodePtr node)
1935 if (ctxt != NULL)
1936 ctxt->nberrors++;
1937 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1938 extra);
1942 * xmlSchemaPErr:
1943 * @ctxt: the parsing context
1944 * @node: the context node
1945 * @error: the error code
1946 * @msg: the error message
1947 * @str1: extra data
1948 * @str2: extra data
1950 * Handle a parser error
1952 static void LIBXML_ATTR_FORMAT(4,0)
1953 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1954 const char *msg, const xmlChar * str1, const xmlChar * str2)
1956 xmlGenericErrorFunc channel = NULL;
1957 xmlStructuredErrorFunc schannel = NULL;
1958 void *data = NULL;
1960 if (ctxt != NULL) {
1961 ctxt->nberrors++;
1962 ctxt->err = error;
1963 channel = ctxt->error;
1964 data = ctxt->errCtxt;
1965 schannel = ctxt->serror;
1967 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1968 error, XML_ERR_ERROR, NULL, 0,
1969 (const char *) str1, (const char *) str2, NULL, 0, 0,
1970 msg, str1, str2);
1974 * xmlSchemaPErr2:
1975 * @ctxt: the parsing context
1976 * @node: the context node
1977 * @node: the current child
1978 * @error: the error code
1979 * @msg: the error message
1980 * @str1: extra data
1981 * @str2: extra data
1983 * Handle a parser error
1985 static void LIBXML_ATTR_FORMAT(5,0)
1986 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1987 xmlNodePtr child, int error,
1988 const char *msg, const xmlChar * str1, const xmlChar * str2)
1990 if (child != NULL)
1991 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1992 else
1993 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1998 * xmlSchemaPErrExt:
1999 * @ctxt: the parsing context
2000 * @node: the context node
2001 * @error: the error code
2002 * @strData1: extra data
2003 * @strData2: extra data
2004 * @strData3: extra data
2005 * @msg: the message
2006 * @str1: extra parameter for the message display
2007 * @str2: extra parameter for the message display
2008 * @str3: extra parameter for the message display
2009 * @str4: extra parameter for the message display
2010 * @str5: extra parameter for the message display
2012 * Handle a parser error
2014 static void LIBXML_ATTR_FORMAT(7,0)
2015 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
2016 const xmlChar * strData1, const xmlChar * strData2,
2017 const xmlChar * strData3, const char *msg, const xmlChar * str1,
2018 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
2019 const xmlChar * str5)
2022 xmlGenericErrorFunc channel = NULL;
2023 xmlStructuredErrorFunc schannel = NULL;
2024 void *data = NULL;
2026 if (ctxt != NULL) {
2027 ctxt->nberrors++;
2028 ctxt->err = error;
2029 channel = ctxt->error;
2030 data = ctxt->errCtxt;
2031 schannel = ctxt->serror;
2033 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
2034 error, XML_ERR_ERROR, NULL, 0,
2035 (const char *) strData1, (const char *) strData2,
2036 (const char *) strData3, 0, 0, msg, str1, str2,
2037 str3, str4, str5);
2040 /************************************************************************
2042 * Allround error functions *
2044 ************************************************************************/
2047 * xmlSchemaVTypeErrMemory:
2048 * @node: a context node
2049 * @extra: extra information
2051 * Handle an out of memory condition
2053 static void
2054 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2055 const char *extra, xmlNodePtr node)
2057 if (ctxt != NULL) {
2058 ctxt->nberrors++;
2059 ctxt->err = XML_SCHEMAV_INTERNAL;
2061 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2062 extra);
2065 static void LIBXML_ATTR_FORMAT(2,0)
2066 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2067 const char *msg, const xmlChar *str)
2069 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2070 msg, (const char *) str);
2073 #define WXS_ERROR_TYPE_ERROR 1
2074 #define WXS_ERROR_TYPE_WARNING 2
2076 * xmlSchemaErr4Line:
2077 * @ctxt: the validation context
2078 * @errorLevel: the error level
2079 * @error: the error code
2080 * @node: the context node
2081 * @line: the line number
2082 * @msg: the error message
2083 * @str1: extra data
2084 * @str2: extra data
2085 * @str3: extra data
2086 * @str4: extra data
2088 * Handle a validation error
2090 static void LIBXML_ATTR_FORMAT(6,0)
2091 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2092 xmlErrorLevel errorLevel,
2093 int error, xmlNodePtr node, int line, const char *msg,
2094 const xmlChar *str1, const xmlChar *str2,
2095 const xmlChar *str3, const xmlChar *str4)
2097 xmlStructuredErrorFunc schannel = NULL;
2098 xmlGenericErrorFunc channel = NULL;
2099 void *data = NULL;
2101 if (ctxt != NULL) {
2102 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2103 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2104 const char *file = NULL;
2105 int col = 0;
2106 if (errorLevel != XML_ERR_WARNING) {
2107 vctxt->nberrors++;
2108 vctxt->err = error;
2109 channel = vctxt->error;
2110 } else {
2111 channel = vctxt->warning;
2113 schannel = vctxt->serror;
2114 data = vctxt->errCtxt;
2117 * Error node. If we specify a line number, then
2118 * do not channel any node to the error function.
2120 if (line == 0) {
2121 if ((node == NULL) &&
2122 (vctxt->depth >= 0) &&
2123 (vctxt->inode != NULL)) {
2124 node = vctxt->inode->node;
2127 * Get filename and line if no node-tree.
2129 if ((node == NULL) &&
2130 (vctxt->parserCtxt != NULL) &&
2131 (vctxt->parserCtxt->input != NULL)) {
2132 file = vctxt->parserCtxt->input->filename;
2133 line = vctxt->parserCtxt->input->line;
2134 col = vctxt->parserCtxt->input->col;
2136 } else {
2138 * Override the given node's (if any) position
2139 * and channel only the given line number.
2141 node = NULL;
2143 * Get filename.
2145 if (vctxt->doc != NULL)
2146 file = (const char *) vctxt->doc->URL;
2147 else if ((vctxt->parserCtxt != NULL) &&
2148 (vctxt->parserCtxt->input != NULL))
2149 file = vctxt->parserCtxt->input->filename;
2151 if (vctxt->locFunc != NULL) {
2152 if ((file == NULL) || (line == 0)) {
2153 unsigned long l;
2154 const char *f;
2155 vctxt->locFunc(vctxt->locCtxt, &f, &l);
2156 if (file == NULL)
2157 file = f;
2158 if (line == 0)
2159 line = (int) l;
2162 if ((file == NULL) && (vctxt->filename != NULL))
2163 file = vctxt->filename;
2165 __xmlRaiseError(schannel, channel, data, ctxt,
2166 node, XML_FROM_SCHEMASV,
2167 error, errorLevel, file, line,
2168 (const char *) str1, (const char *) str2,
2169 (const char *) str3, 0, col, msg, str1, str2, str3, str4);
2171 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2172 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2173 if (errorLevel != XML_ERR_WARNING) {
2174 pctxt->nberrors++;
2175 pctxt->err = error;
2176 channel = pctxt->error;
2177 } else {
2178 channel = pctxt->warning;
2180 schannel = pctxt->serror;
2181 data = pctxt->errCtxt;
2182 __xmlRaiseError(schannel, channel, data, ctxt,
2183 node, XML_FROM_SCHEMASP, error,
2184 errorLevel, NULL, 0,
2185 (const char *) str1, (const char *) str2,
2186 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2187 } else {
2188 TODO
2194 * xmlSchemaErr3:
2195 * @ctxt: the validation context
2196 * @node: the context node
2197 * @error: the error code
2198 * @msg: the error message
2199 * @str1: extra data
2200 * @str2: extra data
2201 * @str3: extra data
2203 * Handle a validation error
2205 static void LIBXML_ATTR_FORMAT(4,0)
2206 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2207 int error, xmlNodePtr node, const char *msg,
2208 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2210 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2211 msg, str1, str2, str3, NULL);
2214 static void LIBXML_ATTR_FORMAT(4,0)
2215 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2216 int error, xmlNodePtr node, const char *msg,
2217 const xmlChar *str1, const xmlChar *str2,
2218 const xmlChar *str3, const xmlChar *str4)
2220 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2221 msg, str1, str2, str3, str4);
2224 static void LIBXML_ATTR_FORMAT(4,0)
2225 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2226 int error, xmlNodePtr node, const char *msg,
2227 const xmlChar *str1, const xmlChar *str2)
2229 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2232 static xmlChar *
2233 xmlSchemaFormatNodeForError(xmlChar ** msg,
2234 xmlSchemaAbstractCtxtPtr actxt,
2235 xmlNodePtr node)
2237 xmlChar *str = NULL;
2239 *msg = NULL;
2240 if ((node != NULL) &&
2241 (node->type != XML_ELEMENT_NODE) &&
2242 (node->type != XML_ATTRIBUTE_NODE))
2245 * Don't try to format other nodes than element and
2246 * attribute nodes.
2247 * Play safe and return an empty string.
2249 *msg = xmlStrdup(BAD_CAST "");
2250 return(*msg);
2252 if (node != NULL) {
2254 * Work on tree nodes.
2256 if (node->type == XML_ATTRIBUTE_NODE) {
2257 xmlNodePtr elem = node->parent;
2259 *msg = xmlStrdup(BAD_CAST "Element '");
2260 if (elem->ns != NULL)
2261 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2262 elem->ns->href, elem->name));
2263 else
2264 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2265 NULL, elem->name));
2266 FREE_AND_NULL(str);
2267 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2268 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2269 } else {
2270 *msg = xmlStrdup(BAD_CAST "Element '");
2272 if (node->ns != NULL)
2273 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2274 node->ns->href, node->name));
2275 else
2276 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2277 NULL, node->name));
2278 FREE_AND_NULL(str);
2279 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2280 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2281 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2283 * Work on node infos.
2285 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2286 xmlSchemaNodeInfoPtr ielem =
2287 vctxt->elemInfos[vctxt->depth];
2289 *msg = xmlStrdup(BAD_CAST "Element '");
2290 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2291 ielem->nsName, ielem->localName));
2292 FREE_AND_NULL(str);
2293 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2294 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2295 } else {
2296 *msg = xmlStrdup(BAD_CAST "Element '");
2298 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2299 vctxt->inode->nsName, vctxt->inode->localName));
2300 FREE_AND_NULL(str);
2301 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2302 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2304 * Hmm, no node while parsing?
2305 * Return an empty string, in case NULL will break something.
2307 *msg = xmlStrdup(BAD_CAST "");
2308 } else {
2309 TODO
2310 return (NULL);
2314 * xmlSchemaFormatItemForReport() also returns an escaped format
2315 * string, so do this before calling it below (in the future).
2317 xmlEscapeFormatString(msg);
2320 * VAL TODO: The output of the given schema component is currently
2321 * disabled.
2323 #if 0
2324 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2325 *msg = xmlStrcat(*msg, BAD_CAST " [");
2326 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2327 NULL, type, NULL, 0));
2328 FREE_AND_NULL(str)
2329 *msg = xmlStrcat(*msg, BAD_CAST "]");
2331 #endif
2332 return (*msg);
2335 static void LIBXML_ATTR_FORMAT(3,0)
2336 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2337 const char *funcName,
2338 const char *message,
2339 const xmlChar *str1,
2340 const xmlChar *str2)
2342 xmlChar *msg = NULL;
2344 if (actxt == NULL)
2345 return;
2346 msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2347 msg = xmlStrcat(msg, BAD_CAST message);
2348 msg = xmlStrcat(msg, BAD_CAST ".\n");
2350 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2351 xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2352 (const char *) msg, (const xmlChar *) funcName, str1, str2);
2353 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2354 xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2355 (const char *) msg, (const xmlChar *) funcName, str1, str2);
2357 FREE_AND_NULL(msg)
2360 static void LIBXML_ATTR_FORMAT(3,0)
2361 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2362 const char *funcName,
2363 const char *message)
2365 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2368 #if 0
2369 static void LIBXML_ATTR_FORMAT(3,0)
2370 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2371 const char *funcName,
2372 const char *message,
2373 const xmlChar *str1,
2374 const xmlChar *str2)
2376 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2377 str1, str2);
2379 #endif
2381 static void LIBXML_ATTR_FORMAT(5,0)
2382 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2383 xmlParserErrors error,
2384 xmlNodePtr node,
2385 xmlSchemaBasicItemPtr item,
2386 const char *message,
2387 const xmlChar *str1, const xmlChar *str2,
2388 const xmlChar *str3, const xmlChar *str4)
2390 xmlChar *msg = NULL;
2392 if ((node == NULL) && (item != NULL) &&
2393 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2394 node = WXS_ITEM_NODE(item);
2395 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2396 msg = xmlStrcat(msg, BAD_CAST ": ");
2397 } else
2398 xmlSchemaFormatNodeForError(&msg, actxt, node);
2399 msg = xmlStrcat(msg, (const xmlChar *) message);
2400 msg = xmlStrcat(msg, BAD_CAST ".\n");
2401 xmlSchemaErr4(actxt, error, node,
2402 (const char *) msg, str1, str2, str3, str4);
2403 FREE_AND_NULL(msg)
2406 static void LIBXML_ATTR_FORMAT(5,0)
2407 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2408 xmlParserErrors error,
2409 xmlNodePtr node,
2410 xmlSchemaBasicItemPtr item,
2411 const char *message,
2412 const xmlChar *str1,
2413 const xmlChar *str2)
2415 xmlSchemaCustomErr4(actxt, error, node, item,
2416 message, str1, str2, NULL, NULL);
2421 static void LIBXML_ATTR_FORMAT(5,0)
2422 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2423 xmlParserErrors error,
2424 xmlNodePtr node,
2425 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2426 const char *message,
2427 const xmlChar *str1,
2428 const xmlChar *str2,
2429 const xmlChar *str3)
2431 xmlChar *msg = NULL;
2433 xmlSchemaFormatNodeForError(&msg, actxt, node);
2434 msg = xmlStrcat(msg, (const xmlChar *) message);
2435 msg = xmlStrcat(msg, BAD_CAST ".\n");
2437 /* URGENT TODO: Set the error code to something sane. */
2438 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2439 (const char *) msg, str1, str2, str3, NULL);
2441 FREE_AND_NULL(msg)
2446 static void LIBXML_ATTR_FORMAT(5,0)
2447 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2448 xmlParserErrors error,
2449 xmlSchemaPSVIIDCNodePtr idcNode,
2450 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2451 const char *message,
2452 const xmlChar *str1,
2453 const xmlChar *str2)
2455 xmlChar *msg = NULL, *qname = NULL;
2457 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2458 msg = xmlStrcat(msg, (const xmlChar *) message);
2459 msg = xmlStrcat(msg, BAD_CAST ".\n");
2460 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2461 error, NULL, idcNode->nodeLine, (const char *) msg,
2462 xmlSchemaFormatQName(&qname,
2463 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2464 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2465 str1, str2, NULL);
2466 FREE_AND_NULL(qname);
2467 FREE_AND_NULL(msg);
2470 static int
2471 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2472 xmlNodePtr node)
2474 if (node != NULL)
2475 return (node->type);
2476 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2477 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2478 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2479 return (-1);
2482 static int
2483 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2485 switch (item->type) {
2486 case XML_SCHEMA_TYPE_COMPLEX:
2487 case XML_SCHEMA_TYPE_SIMPLE:
2488 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2489 return(1);
2490 break;
2491 case XML_SCHEMA_TYPE_GROUP:
2492 return (1);
2493 case XML_SCHEMA_TYPE_ELEMENT:
2494 if ( ((xmlSchemaElementPtr) item)->flags &
2495 XML_SCHEMAS_ELEM_GLOBAL)
2496 return(1);
2497 break;
2498 case XML_SCHEMA_TYPE_ATTRIBUTE:
2499 if ( ((xmlSchemaAttributePtr) item)->flags &
2500 XML_SCHEMAS_ATTR_GLOBAL)
2501 return(1);
2502 break;
2503 /* Note that attribute groups are always global. */
2504 default:
2505 return(1);
2507 return (0);
2510 static void
2511 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2512 xmlParserErrors error,
2513 xmlNodePtr node,
2514 const xmlChar *value,
2515 xmlSchemaTypePtr type,
2516 int displayValue)
2518 xmlChar *msg = NULL;
2520 xmlSchemaFormatNodeForError(&msg, actxt, node);
2522 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2523 XML_ATTRIBUTE_NODE))
2524 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2525 else
2526 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2527 "value of ");
2529 if (! xmlSchemaIsGlobalItem(type))
2530 msg = xmlStrcat(msg, BAD_CAST "the local ");
2531 else
2532 msg = xmlStrcat(msg, BAD_CAST "the ");
2534 if (WXS_IS_ATOMIC(type))
2535 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2536 else if (WXS_IS_LIST(type))
2537 msg = xmlStrcat(msg, BAD_CAST "list type");
2538 else if (WXS_IS_UNION(type))
2539 msg = xmlStrcat(msg, BAD_CAST "union type");
2541 if (xmlSchemaIsGlobalItem(type)) {
2542 xmlChar *str = NULL;
2543 msg = xmlStrcat(msg, BAD_CAST " '");
2544 if (type->builtInType != 0) {
2545 msg = xmlStrcat(msg, BAD_CAST "xs:");
2546 str = xmlStrdup(type->name);
2547 } else {
2548 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2549 if (!str)
2550 str = xmlStrdup(qName);
2552 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2553 msg = xmlStrcat(msg, BAD_CAST "'");
2554 FREE_AND_NULL(str);
2556 msg = xmlStrcat(msg, BAD_CAST ".\n");
2557 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2558 XML_ATTRIBUTE_NODE))
2559 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2560 else
2561 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2562 FREE_AND_NULL(msg)
2565 static const xmlChar *
2566 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2567 xmlSchemaNodeInfoPtr ni,
2568 xmlNodePtr node)
2570 if (node != NULL) {
2571 if (node->ns != NULL)
2572 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2573 else
2574 return (xmlSchemaFormatQName(str, NULL, node->name));
2575 } else if (ni != NULL)
2576 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2577 return (NULL);
2580 static void
2581 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2582 xmlParserErrors error,
2583 xmlSchemaAttrInfoPtr ni,
2584 xmlNodePtr node)
2586 xmlChar *msg = NULL, *str = NULL;
2588 xmlSchemaFormatNodeForError(&msg, actxt, node);
2589 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2590 xmlSchemaErr(actxt, error, node, (const char *) msg,
2591 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2592 NULL);
2593 FREE_AND_NULL(str)
2594 FREE_AND_NULL(msg)
2597 static void LIBXML_ATTR_FORMAT(5,0)
2598 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2599 xmlParserErrors error,
2600 xmlNodePtr node,
2601 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2602 const char *message,
2603 int nbval,
2604 int nbneg,
2605 xmlChar **values)
2607 xmlChar *str = NULL, *msg = NULL;
2608 xmlChar *localName, *nsName;
2609 const xmlChar *cur, *end;
2610 int i;
2612 xmlSchemaFormatNodeForError(&msg, actxt, node);
2613 msg = xmlStrcat(msg, (const xmlChar *) message);
2614 msg = xmlStrcat(msg, BAD_CAST ".");
2616 * Note that is does not make sense to report that we have a
2617 * wildcard here, since the wildcard might be unfolded into
2618 * multiple transitions.
2620 if (nbval + nbneg > 0) {
2621 if (nbval + nbneg > 1) {
2622 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2623 } else
2624 str = xmlStrdup(BAD_CAST " Expected is ( ");
2625 nsName = NULL;
2627 for (i = 0; i < nbval + nbneg; i++) {
2628 cur = values[i];
2629 if (cur == NULL)
2630 continue;
2631 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2632 (cur[3] == ' ')) {
2633 cur += 4;
2634 str = xmlStrcat(str, BAD_CAST "##other");
2637 * Get the local name.
2639 localName = NULL;
2641 end = cur;
2642 if (*end == '*') {
2643 localName = xmlStrdup(BAD_CAST "*");
2644 end++;
2645 } else {
2646 while ((*end != 0) && (*end != '|'))
2647 end++;
2648 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2650 if (*end != 0) {
2651 end++;
2653 * Skip "*|*" if they come with negated expressions, since
2654 * they represent the same negated wildcard.
2656 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2658 * Get the namespace name.
2660 cur = end;
2661 if (*end == '*') {
2662 nsName = xmlStrdup(BAD_CAST "{*}");
2663 } else {
2664 while (*end != 0)
2665 end++;
2667 if (i >= nbval)
2668 nsName = xmlStrdup(BAD_CAST "{##other:");
2669 else
2670 nsName = xmlStrdup(BAD_CAST "{");
2672 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2673 nsName = xmlStrcat(nsName, BAD_CAST "}");
2675 str = xmlStrcat(str, BAD_CAST nsName);
2676 FREE_AND_NULL(nsName)
2677 } else {
2678 FREE_AND_NULL(localName);
2679 continue;
2682 str = xmlStrcat(str, BAD_CAST localName);
2683 FREE_AND_NULL(localName);
2685 if (i < nbval + nbneg -1)
2686 str = xmlStrcat(str, BAD_CAST ", ");
2688 str = xmlStrcat(str, BAD_CAST " ).\n");
2689 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2690 FREE_AND_NULL(str)
2691 } else
2692 msg = xmlStrcat(msg, BAD_CAST "\n");
2693 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2694 xmlFree(msg);
2697 static void LIBXML_ATTR_FORMAT(8,0)
2698 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2699 xmlParserErrors error,
2700 xmlNodePtr node,
2701 const xmlChar *value,
2702 unsigned long length,
2703 xmlSchemaTypePtr type,
2704 xmlSchemaFacetPtr facet,
2705 const char *message,
2706 const xmlChar *str1,
2707 const xmlChar *str2)
2709 xmlChar *str = NULL, *msg = NULL;
2710 xmlSchemaTypeType facetType;
2711 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2713 xmlSchemaFormatNodeForError(&msg, actxt, node);
2714 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2715 facetType = XML_SCHEMA_FACET_ENUMERATION;
2717 * If enumerations are validated, one must not expect the
2718 * facet to be given.
2720 } else
2721 facetType = facet->type;
2722 msg = xmlStrcat(msg, BAD_CAST "[");
2723 msg = xmlStrcat(msg, BAD_CAST "facet '");
2724 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2725 msg = xmlStrcat(msg, BAD_CAST "'] ");
2726 if (message == NULL) {
2728 * Use a default message.
2730 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2731 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2732 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2734 char len[25], actLen[25];
2736 /* FIXME, TODO: What is the max expected string length of the
2737 * this value?
2739 if (nodeType == XML_ATTRIBUTE_NODE)
2740 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2741 else
2742 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2744 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2745 snprintf(actLen, 24, "%lu", length);
2747 if (facetType == XML_SCHEMA_FACET_LENGTH)
2748 msg = xmlStrcat(msg,
2749 BAD_CAST "this differs from the allowed length of '%s'.\n");
2750 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2751 msg = xmlStrcat(msg,
2752 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2753 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2754 msg = xmlStrcat(msg,
2755 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2757 if (nodeType == XML_ATTRIBUTE_NODE)
2758 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2759 value, (const xmlChar *) actLen, (const xmlChar *) len);
2760 else
2761 xmlSchemaErr(actxt, error, node, (const char *) msg,
2762 (const xmlChar *) actLen, (const xmlChar *) len);
2764 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2765 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2766 "of the set {%s}.\n");
2767 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2768 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2769 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2770 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2771 "by the pattern '%s'.\n");
2772 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2773 facet->value);
2774 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2775 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2776 "minimum value allowed ('%s').\n");
2777 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2778 facet->value);
2779 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2780 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2781 "maximum value allowed ('%s').\n");
2782 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2783 facet->value);
2784 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2785 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2786 "'%s'.\n");
2787 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2788 facet->value);
2789 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2790 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2791 "'%s'.\n");
2792 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2793 facet->value);
2794 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2795 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2796 "digits than are allowed ('%s').\n");
2797 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2798 facet->value);
2799 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2800 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2801 "digits than are allowed ('%s').\n");
2802 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2803 facet->value);
2804 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2805 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2806 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2807 } else {
2808 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2809 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2811 } else {
2812 msg = xmlStrcat(msg, (const xmlChar *) message);
2813 msg = xmlStrcat(msg, BAD_CAST ".\n");
2814 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2816 FREE_AND_NULL(str)
2817 xmlFree(msg);
2820 #define VERROR(err, type, msg) \
2821 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2823 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2825 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2826 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2828 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2832 * xmlSchemaPMissingAttrErr:
2833 * @ctxt: the schema validation context
2834 * @ownerItem: the owner as a schema object
2835 * @ownerElem: the owner as an element node
2836 * @node: the parent element node of the missing attribute node
2837 * @type: the corresponding type of the attribute node
2839 * Reports an illegal attribute.
2841 static void
2842 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2843 xmlParserErrors error,
2844 xmlSchemaBasicItemPtr ownerItem,
2845 xmlNodePtr ownerElem,
2846 const char *name,
2847 const char *message)
2849 xmlChar *des = NULL;
2851 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2853 if (message != NULL)
2854 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2855 else
2856 xmlSchemaPErr(ctxt, ownerElem, error,
2857 "%s: The attribute '%s' is required but missing.\n",
2858 BAD_CAST des, BAD_CAST name);
2859 FREE_AND_NULL(des);
2864 * xmlSchemaPResCompAttrErr:
2865 * @ctxt: the schema validation context
2866 * @error: the error code
2867 * @ownerItem: the owner as a schema object
2868 * @ownerElem: the owner as an element node
2869 * @name: the name of the attribute holding the QName
2870 * @refName: the referenced local name
2871 * @refURI: the referenced namespace URI
2872 * @message: optional message
2874 * Used to report QName attribute values that failed to resolve
2875 * to schema components.
2877 static void
2878 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2879 xmlParserErrors error,
2880 xmlSchemaBasicItemPtr ownerItem,
2881 xmlNodePtr ownerElem,
2882 const char *name,
2883 const xmlChar *refName,
2884 const xmlChar *refURI,
2885 xmlSchemaTypeType refType,
2886 const char *refTypeStr)
2888 xmlChar *des = NULL, *strA = NULL;
2890 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2891 if (refTypeStr == NULL)
2892 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2893 xmlSchemaPErrExt(ctxt, ownerElem, error,
2894 NULL, NULL, NULL,
2895 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2896 "%s.\n", BAD_CAST des, BAD_CAST name,
2897 xmlSchemaFormatQName(&strA, refURI, refName),
2898 BAD_CAST refTypeStr, NULL);
2899 FREE_AND_NULL(des)
2900 FREE_AND_NULL(strA)
2904 * xmlSchemaPCustomAttrErr:
2905 * @ctxt: the schema parser context
2906 * @error: the error code
2907 * @ownerDes: the designation of the owner
2908 * @ownerItem: the owner as a schema object
2909 * @attr: the illegal attribute node
2911 * Reports an illegal attribute during the parse.
2913 static void
2914 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2915 xmlParserErrors error,
2916 xmlChar **ownerDes,
2917 xmlSchemaBasicItemPtr ownerItem,
2918 xmlAttrPtr attr,
2919 const char *msg)
2921 xmlChar *des = NULL;
2923 if (ownerDes == NULL)
2924 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2925 else if (*ownerDes == NULL) {
2926 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2927 des = *ownerDes;
2928 } else
2929 des = *ownerDes;
2930 if (attr == NULL) {
2931 xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2932 "%s, attribute '%s': %s.\n",
2933 BAD_CAST des, (const xmlChar *) "Unknown",
2934 (const xmlChar *) msg, NULL, NULL);
2935 } else {
2936 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2937 "%s, attribute '%s': %s.\n",
2938 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2940 if (ownerDes == NULL)
2941 FREE_AND_NULL(des);
2945 * xmlSchemaPIllegalAttrErr:
2946 * @ctxt: the schema parser context
2947 * @error: the error code
2948 * @ownerItem: the attribute's owner item
2949 * @attr: the illegal attribute node
2951 * Reports an illegal attribute during the parse.
2953 static void
2954 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2955 xmlParserErrors error,
2956 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2957 xmlAttrPtr attr)
2959 xmlChar *strA = NULL, *strB = NULL;
2961 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2962 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2963 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2964 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2965 NULL, NULL);
2966 FREE_AND_NULL(strA);
2967 FREE_AND_NULL(strB);
2971 * xmlSchemaPCustomErr:
2972 * @ctxt: the schema parser context
2973 * @error: the error code
2974 * @itemDes: the designation of the schema item
2975 * @item: the schema item
2976 * @itemElem: the node of the schema item
2977 * @message: the error message
2978 * @str1: an optional param for the error message
2979 * @str2: an optional param for the error message
2980 * @str3: an optional param for the error message
2982 * Reports an error during parsing.
2984 static void LIBXML_ATTR_FORMAT(5,0)
2985 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2986 xmlParserErrors error,
2987 xmlSchemaBasicItemPtr item,
2988 xmlNodePtr itemElem,
2989 const char *message,
2990 const xmlChar *str1,
2991 const xmlChar *str2,
2992 const xmlChar *str3)
2994 xmlChar *des = NULL, *msg = NULL;
2996 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2997 msg = xmlStrdup(BAD_CAST "%s: ");
2998 msg = xmlStrcat(msg, (const xmlChar *) message);
2999 msg = xmlStrcat(msg, BAD_CAST ".\n");
3000 if ((itemElem == NULL) && (item != NULL))
3001 itemElem = WXS_ITEM_NODE(item);
3002 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
3003 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
3004 FREE_AND_NULL(des);
3005 FREE_AND_NULL(msg);
3009 * xmlSchemaPCustomErr:
3010 * @ctxt: the schema parser context
3011 * @error: the error code
3012 * @itemDes: the designation of the schema item
3013 * @item: the schema item
3014 * @itemElem: the node of the schema item
3015 * @message: the error message
3016 * @str1: the optional param for the error message
3018 * Reports an error during parsing.
3020 static void LIBXML_ATTR_FORMAT(5,0)
3021 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
3022 xmlParserErrors error,
3023 xmlSchemaBasicItemPtr item,
3024 xmlNodePtr itemElem,
3025 const char *message,
3026 const xmlChar *str1)
3028 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
3029 str1, NULL, NULL);
3033 * xmlSchemaPAttrUseErr:
3034 * @ctxt: the schema parser context
3035 * @error: the error code
3036 * @itemDes: the designation of the schema type
3037 * @item: the schema type
3038 * @itemElem: the node of the schema type
3039 * @attr: the invalid schema attribute
3040 * @message: the error message
3041 * @str1: the optional param for the error message
3043 * Reports an attribute use error during parsing.
3045 static void LIBXML_ATTR_FORMAT(6,0)
3046 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3047 xmlParserErrors error,
3048 xmlNodePtr node,
3049 xmlSchemaBasicItemPtr ownerItem,
3050 const xmlSchemaAttributeUsePtr attruse,
3051 const char *message,
3052 const xmlChar *str1, const xmlChar *str2,
3053 const xmlChar *str3,const xmlChar *str4)
3055 xmlChar *str = NULL, *msg = NULL;
3057 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3058 msg = xmlStrcat(msg, BAD_CAST ", ");
3059 msg = xmlStrcat(msg,
3060 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3061 WXS_BASIC_CAST attruse, NULL));
3062 FREE_AND_NULL(str);
3063 msg = xmlStrcat(msg, BAD_CAST ": ");
3064 msg = xmlStrcat(msg, (const xmlChar *) message);
3065 msg = xmlStrcat(msg, BAD_CAST ".\n");
3066 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3067 (const char *) msg, str1, str2, str3, str4);
3068 xmlFree(msg);
3072 * xmlSchemaPIllegalFacetAtomicErr:
3073 * @ctxt: the schema parser context
3074 * @error: the error code
3075 * @type: the schema type
3076 * @baseType: the base type of type
3077 * @facet: the illegal facet
3079 * Reports an illegal facet for atomic simple types.
3081 static void
3082 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3083 xmlParserErrors error,
3084 xmlSchemaTypePtr type,
3085 xmlSchemaTypePtr baseType,
3086 xmlSchemaFacetPtr facet)
3088 xmlChar *des = NULL, *strT = NULL;
3090 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3091 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3092 "%s: The facet '%s' is not allowed on types derived from the "
3093 "type %s.\n",
3094 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3095 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3096 NULL, NULL);
3097 FREE_AND_NULL(des);
3098 FREE_AND_NULL(strT);
3102 * xmlSchemaPIllegalFacetListUnionErr:
3103 * @ctxt: the schema parser context
3104 * @error: the error code
3105 * @itemDes: the designation of the schema item involved
3106 * @item: the schema item involved
3107 * @facet: the illegal facet
3109 * Reports an illegal facet for <list> and <union>.
3111 static void
3112 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3113 xmlParserErrors error,
3114 xmlSchemaTypePtr type,
3115 xmlSchemaFacetPtr facet)
3117 xmlChar *des = NULL;
3119 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3120 type->node);
3121 xmlSchemaPErr(ctxt, type->node, error,
3122 "%s: The facet '%s' is not allowed.\n",
3123 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3124 FREE_AND_NULL(des);
3128 * xmlSchemaPMutualExclAttrErr:
3129 * @ctxt: the schema validation context
3130 * @error: the error code
3131 * @elemDes: the designation of the parent element node
3132 * @attr: the bad attribute node
3133 * @type: the corresponding type of the attribute node
3135 * Reports an illegal attribute.
3137 static void
3138 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3139 xmlParserErrors error,
3140 xmlSchemaBasicItemPtr ownerItem,
3141 xmlAttrPtr attr,
3142 const char *name1,
3143 const char *name2)
3145 xmlChar *des = NULL;
3147 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3148 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3149 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3150 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3151 FREE_AND_NULL(des);
3155 * xmlSchemaPSimpleTypeErr:
3156 * @ctxt: the schema validation context
3157 * @error: the error code
3158 * @type: the type specifier
3159 * @ownerItem: the schema object if existent
3160 * @node: the validated node
3161 * @value: the validated value
3163 * Reports a simple type validation error.
3164 * TODO: Should this report the value of an element as well?
3166 static void LIBXML_ATTR_FORMAT(8,0)
3167 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3168 xmlParserErrors error,
3169 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3170 xmlNodePtr node,
3171 xmlSchemaTypePtr type,
3172 const char *expected,
3173 const xmlChar *value,
3174 const char *message,
3175 const xmlChar *str1,
3176 const xmlChar *str2)
3178 xmlChar *msg = NULL;
3180 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3181 if (message == NULL) {
3183 * Use default messages.
3185 if (type != NULL) {
3186 if (node->type == XML_ATTRIBUTE_NODE)
3187 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3188 else
3189 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3190 "valid value of ");
3191 if (! xmlSchemaIsGlobalItem(type))
3192 msg = xmlStrcat(msg, BAD_CAST "the local ");
3193 else
3194 msg = xmlStrcat(msg, BAD_CAST "the ");
3196 if (WXS_IS_ATOMIC(type))
3197 msg = xmlStrcat(msg, BAD_CAST "atomic type");
3198 else if (WXS_IS_LIST(type))
3199 msg = xmlStrcat(msg, BAD_CAST "list type");
3200 else if (WXS_IS_UNION(type))
3201 msg = xmlStrcat(msg, BAD_CAST "union type");
3203 if (xmlSchemaIsGlobalItem(type)) {
3204 xmlChar *str = NULL;
3205 msg = xmlStrcat(msg, BAD_CAST " '");
3206 if (type->builtInType != 0) {
3207 msg = xmlStrcat(msg, BAD_CAST "xs:");
3208 str = xmlStrdup(type->name);
3209 } else {
3210 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3211 if (!str)
3212 str = xmlStrdup(qName);
3214 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3215 msg = xmlStrcat(msg, BAD_CAST "'.");
3216 FREE_AND_NULL(str);
3218 } else {
3219 if (node->type == XML_ATTRIBUTE_NODE)
3220 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3221 else
3222 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3223 "valid.");
3225 if (expected) {
3226 xmlChar *expectedEscaped = xmlCharStrdup(expected);
3227 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3228 msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3229 FREE_AND_NULL(expectedEscaped);
3230 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3231 } else
3232 msg = xmlStrcat(msg, BAD_CAST "\n");
3233 if (node->type == XML_ATTRIBUTE_NODE)
3234 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3235 else
3236 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3237 } else {
3238 msg = xmlStrcat(msg, BAD_CAST message);
3239 msg = xmlStrcat(msg, BAD_CAST ".\n");
3240 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3241 (const char*) msg, str1, str2, NULL, NULL, NULL);
3243 /* Cleanup. */
3244 FREE_AND_NULL(msg)
3248 * xmlSchemaPContentErr:
3249 * @ctxt: the schema parser context
3250 * @error: the error code
3251 * @ownerItem: the owner item of the holder of the content
3252 * @ownerElem: the node of the holder of the content
3253 * @child: the invalid child node
3254 * @message: the optional error message
3255 * @content: the optional string describing the correct content
3257 * Reports an error concerning the content of a schema element.
3259 static void
3260 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3261 xmlParserErrors error,
3262 xmlSchemaBasicItemPtr ownerItem,
3263 xmlNodePtr ownerElem,
3264 xmlNodePtr child,
3265 const char *message,
3266 const char *content)
3268 xmlChar *des = NULL;
3270 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3271 if (message != NULL)
3272 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3273 "%s: %s.\n",
3274 BAD_CAST des, BAD_CAST message);
3275 else {
3276 if (content != NULL) {
3277 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3278 "%s: The content is not valid. Expected is %s.\n",
3279 BAD_CAST des, BAD_CAST content);
3280 } else {
3281 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3282 "%s: The content is not valid.\n",
3283 BAD_CAST des, NULL);
3286 FREE_AND_NULL(des)
3289 /************************************************************************
3291 * Streamable error functions *
3293 ************************************************************************/
3298 /************************************************************************
3300 * Validation helper functions *
3302 ************************************************************************/
3305 /************************************************************************
3307 * Allocation functions *
3309 ************************************************************************/
3312 * xmlSchemaNewSchemaForParserCtxt:
3313 * @ctxt: a schema validation context
3315 * Allocate a new Schema structure.
3317 * Returns the newly allocated structure or NULL in case or error
3319 static xmlSchemaPtr
3320 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3322 xmlSchemaPtr ret;
3324 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3325 if (ret == NULL) {
3326 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3327 return (NULL);
3329 memset(ret, 0, sizeof(xmlSchema));
3330 ret->dict = ctxt->dict;
3331 xmlDictReference(ret->dict);
3333 return (ret);
3337 * xmlSchemaNewFacet:
3339 * Allocate a new Facet structure.
3341 * Returns the newly allocated structure or NULL in case or error
3343 xmlSchemaFacetPtr
3344 xmlSchemaNewFacet(void)
3346 xmlSchemaFacetPtr ret;
3348 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3349 if (ret == NULL) {
3350 return (NULL);
3352 memset(ret, 0, sizeof(xmlSchemaFacet));
3354 return (ret);
3358 * xmlSchemaNewAnnot:
3359 * @ctxt: a schema validation context
3360 * @node: a node
3362 * Allocate a new annotation structure.
3364 * Returns the newly allocated structure or NULL in case or error
3366 static xmlSchemaAnnotPtr
3367 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3369 xmlSchemaAnnotPtr ret;
3371 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3372 if (ret == NULL) {
3373 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3374 return (NULL);
3376 memset(ret, 0, sizeof(xmlSchemaAnnot));
3377 ret->content = node;
3378 return (ret);
3381 static xmlSchemaItemListPtr
3382 xmlSchemaItemListCreate(void)
3384 xmlSchemaItemListPtr ret;
3386 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3387 if (ret == NULL) {
3388 xmlSchemaPErrMemory(NULL,
3389 "allocating an item list structure", NULL);
3390 return (NULL);
3392 memset(ret, 0, sizeof(xmlSchemaItemList));
3393 return (ret);
3396 static void
3397 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3399 if (list->items != NULL) {
3400 xmlFree(list->items);
3401 list->items = NULL;
3403 list->nbItems = 0;
3404 list->sizeItems = 0;
3407 static int
3408 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3410 if (list->items == NULL) {
3411 list->items = (void **) xmlMalloc(
3412 20 * sizeof(void *));
3413 if (list->items == NULL) {
3414 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3415 return(-1);
3417 list->sizeItems = 20;
3418 } else if (list->sizeItems <= list->nbItems) {
3419 list->sizeItems *= 2;
3420 list->items = (void **) xmlRealloc(list->items,
3421 list->sizeItems * sizeof(void *));
3422 if (list->items == NULL) {
3423 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3424 list->sizeItems = 0;
3425 return(-1);
3428 list->items[list->nbItems++] = item;
3429 return(0);
3432 static int
3433 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3434 int initialSize,
3435 void *item)
3437 if (list->items == NULL) {
3438 if (initialSize <= 0)
3439 initialSize = 1;
3440 list->items = (void **) xmlMalloc(
3441 initialSize * sizeof(void *));
3442 if (list->items == NULL) {
3443 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3444 return(-1);
3446 list->sizeItems = initialSize;
3447 } else if (list->sizeItems <= list->nbItems) {
3448 list->sizeItems *= 2;
3449 list->items = (void **) xmlRealloc(list->items,
3450 list->sizeItems * sizeof(void *));
3451 if (list->items == NULL) {
3452 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3453 list->sizeItems = 0;
3454 return(-1);
3457 list->items[list->nbItems++] = item;
3458 return(0);
3461 static int
3462 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3464 if (list->items == NULL) {
3465 list->items = (void **) xmlMalloc(
3466 20 * sizeof(void *));
3467 if (list->items == NULL) {
3468 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3469 return(-1);
3471 list->sizeItems = 20;
3472 } else if (list->sizeItems <= list->nbItems) {
3473 list->sizeItems *= 2;
3474 list->items = (void **) xmlRealloc(list->items,
3475 list->sizeItems * sizeof(void *));
3476 if (list->items == NULL) {
3477 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3478 list->sizeItems = 0;
3479 return(-1);
3483 * Just append if the index is greater/equal than the item count.
3485 if (idx >= list->nbItems) {
3486 list->items[list->nbItems++] = item;
3487 } else {
3488 int i;
3489 for (i = list->nbItems; i > idx; i--)
3490 list->items[i] = list->items[i-1];
3491 list->items[idx] = item;
3492 list->nbItems++;
3494 return(0);
3497 #if 0 /* enable if ever needed */
3498 static int
3499 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3500 int initialSize,
3501 void *item,
3502 int idx)
3504 if (list->items == NULL) {
3505 if (initialSize <= 0)
3506 initialSize = 1;
3507 list->items = (void **) xmlMalloc(
3508 initialSize * sizeof(void *));
3509 if (list->items == NULL) {
3510 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3511 return(-1);
3513 list->sizeItems = initialSize;
3514 } else if (list->sizeItems <= list->nbItems) {
3515 list->sizeItems *= 2;
3516 list->items = (void **) xmlRealloc(list->items,
3517 list->sizeItems * sizeof(void *));
3518 if (list->items == NULL) {
3519 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3520 list->sizeItems = 0;
3521 return(-1);
3525 * Just append if the index is greater/equal than the item count.
3527 if (idx >= list->nbItems) {
3528 list->items[list->nbItems++] = item;
3529 } else {
3530 int i;
3531 for (i = list->nbItems; i > idx; i--)
3532 list->items[i] = list->items[i-1];
3533 list->items[idx] = item;
3534 list->nbItems++;
3536 return(0);
3538 #endif
3540 static int
3541 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3543 int i;
3544 if ((list->items == NULL) || (idx >= list->nbItems)) {
3545 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3546 "index error.\n");
3547 return(-1);
3550 if (list->nbItems == 1) {
3551 /* TODO: Really free the list? */
3552 xmlFree(list->items);
3553 list->items = NULL;
3554 list->nbItems = 0;
3555 list->sizeItems = 0;
3556 } else if (list->nbItems -1 == idx) {
3557 list->nbItems--;
3558 } else {
3559 for (i = idx; i < list->nbItems -1; i++)
3560 list->items[i] = list->items[i+1];
3561 list->nbItems--;
3563 return(0);
3567 * xmlSchemaItemListFree:
3568 * @annot: a schema type structure
3570 * Deallocate a annotation structure
3572 static void
3573 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3575 if (list == NULL)
3576 return;
3577 if (list->items != NULL)
3578 xmlFree(list->items);
3579 xmlFree(list);
3582 static void
3583 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3585 if (bucket == NULL)
3586 return;
3587 if (bucket->globals != NULL) {
3588 xmlSchemaComponentListFree(bucket->globals);
3589 xmlSchemaItemListFree(bucket->globals);
3591 if (bucket->locals != NULL) {
3592 xmlSchemaComponentListFree(bucket->locals);
3593 xmlSchemaItemListFree(bucket->locals);
3595 if (bucket->relations != NULL) {
3596 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3597 do {
3598 prev = cur;
3599 cur = cur->next;
3600 xmlFree(prev);
3601 } while (cur != NULL);
3603 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3604 xmlFreeDoc(bucket->doc);
3606 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3607 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3608 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3610 xmlFree(bucket);
3613 static void
3614 xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3616 xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3619 static xmlSchemaBucketPtr
3620 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3621 int type, const xmlChar *targetNamespace)
3623 xmlSchemaBucketPtr ret;
3624 int size;
3625 xmlSchemaPtr mainSchema;
3627 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3628 PERROR_INT("xmlSchemaBucketCreate",
3629 "no main schema on constructor");
3630 return(NULL);
3632 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3633 /* Create the schema bucket. */
3634 if (WXS_IS_BUCKET_INCREDEF(type))
3635 size = sizeof(xmlSchemaInclude);
3636 else
3637 size = sizeof(xmlSchemaImport);
3638 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3639 if (ret == NULL) {
3640 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3641 return(NULL);
3643 memset(ret, 0, size);
3644 ret->targetNamespace = targetNamespace;
3645 ret->type = type;
3646 ret->globals = xmlSchemaItemListCreate();
3647 if (ret->globals == NULL) {
3648 xmlFree(ret);
3649 return(NULL);
3651 ret->locals = xmlSchemaItemListCreate();
3652 if (ret->locals == NULL) {
3653 xmlFree(ret);
3654 return(NULL);
3657 * The following will assure that only the first bucket is marked as
3658 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3659 * For each following import buckets an xmlSchema will be created.
3660 * An xmlSchema will be created for every distinct targetNamespace.
3661 * We assign the targetNamespace to the schemata here.
3663 if (! WXS_HAS_BUCKETS(pctxt)) {
3664 if (WXS_IS_BUCKET_INCREDEF(type)) {
3665 PERROR_INT("xmlSchemaBucketCreate",
3666 "first bucket but it's an include or redefine");
3667 xmlSchemaBucketFree(ret);
3668 return(NULL);
3670 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3671 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3672 /* Point to the *main* schema. */
3673 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3674 WXS_IMPBUCKET(ret)->schema = mainSchema;
3676 * Ensure that the main schema gets a targetNamespace.
3678 mainSchema->targetNamespace = targetNamespace;
3679 } else {
3680 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3681 PERROR_INT("xmlSchemaBucketCreate",
3682 "main bucket but it's not the first one");
3683 xmlSchemaBucketFree(ret);
3684 return(NULL);
3685 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3687 * Create a schema for imports and assign the
3688 * targetNamespace.
3690 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3691 if (WXS_IMPBUCKET(ret)->schema == NULL) {
3692 xmlSchemaBucketFree(ret);
3693 return(NULL);
3695 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3698 if (WXS_IS_BUCKET_IMPMAIN(type)) {
3699 int res;
3701 * Imports go into the "schemasImports" slot of the main *schema*.
3702 * Note that we create an import entry for the main schema as well; i.e.,
3703 * even if there's only one schema, we'll get an import.
3705 if (mainSchema->schemasImports == NULL) {
3706 mainSchema->schemasImports = xmlHashCreateDict(5,
3707 WXS_CONSTRUCTOR(pctxt)->dict);
3708 if (mainSchema->schemasImports == NULL) {
3709 xmlSchemaBucketFree(ret);
3710 return(NULL);
3713 if (targetNamespace == NULL)
3714 res = xmlHashAddEntry(mainSchema->schemasImports,
3715 XML_SCHEMAS_NO_NAMESPACE, ret);
3716 else
3717 res = xmlHashAddEntry(mainSchema->schemasImports,
3718 targetNamespace, ret);
3719 if (res != 0) {
3720 PERROR_INT("xmlSchemaBucketCreate",
3721 "failed to add the schema bucket to the hash");
3722 xmlSchemaBucketFree(ret);
3723 return(NULL);
3725 } else {
3726 /* Set the @ownerImport of an include bucket. */
3727 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3728 WXS_INCBUCKET(ret)->ownerImport =
3729 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3730 else
3731 WXS_INCBUCKET(ret)->ownerImport =
3732 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3734 /* Includes got into the "includes" slot of the *main* schema. */
3735 if (mainSchema->includes == NULL) {
3736 mainSchema->includes = xmlSchemaItemListCreate();
3737 if (mainSchema->includes == NULL) {
3738 xmlSchemaBucketFree(ret);
3739 return(NULL);
3742 xmlSchemaItemListAdd(mainSchema->includes, ret);
3745 * Add to list of all buckets; this is used for lookup
3746 * during schema construction time only.
3748 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3749 return(NULL);
3750 return(ret);
3753 static int
3754 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3756 if (*list == NULL) {
3757 *list = xmlSchemaItemListCreate();
3758 if (*list == NULL)
3759 return(-1);
3761 xmlSchemaItemListAddSize(*list, initialSize, item);
3762 return(0);
3766 * xmlSchemaFreeAnnot:
3767 * @annot: a schema type structure
3769 * Deallocate a annotation structure
3771 static void
3772 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3774 if (annot == NULL)
3775 return;
3776 if (annot->next == NULL) {
3777 xmlFree(annot);
3778 } else {
3779 xmlSchemaAnnotPtr prev;
3781 do {
3782 prev = annot;
3783 annot = annot->next;
3784 xmlFree(prev);
3785 } while (annot != NULL);
3790 * xmlSchemaFreeNotation:
3791 * @schema: a schema notation structure
3793 * Deallocate a Schema Notation structure.
3795 static void
3796 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3798 if (nota == NULL)
3799 return;
3800 xmlFree(nota);
3804 * xmlSchemaFreeAttribute:
3805 * @attr: an attribute declaration
3807 * Deallocates an attribute declaration structure.
3809 static void
3810 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3812 if (attr == NULL)
3813 return;
3814 if (attr->annot != NULL)
3815 xmlSchemaFreeAnnot(attr->annot);
3816 if (attr->defVal != NULL)
3817 xmlSchemaFreeValue(attr->defVal);
3818 xmlFree(attr);
3822 * xmlSchemaFreeAttributeUse:
3823 * @use: an attribute use
3825 * Deallocates an attribute use structure.
3827 static void
3828 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3830 if (use == NULL)
3831 return;
3832 if (use->annot != NULL)
3833 xmlSchemaFreeAnnot(use->annot);
3834 if (use->defVal != NULL)
3835 xmlSchemaFreeValue(use->defVal);
3836 xmlFree(use);
3840 * xmlSchemaFreeAttributeUseProhib:
3841 * @prohib: an attribute use prohibition
3843 * Deallocates an attribute use structure.
3845 static void
3846 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3848 if (prohib == NULL)
3849 return;
3850 xmlFree(prohib);
3854 * xmlSchemaFreeWildcardNsSet:
3855 * set: a schema wildcard namespace
3857 * Deallocates a list of wildcard constraint structures.
3859 static void
3860 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3862 xmlSchemaWildcardNsPtr next;
3864 while (set != NULL) {
3865 next = set->next;
3866 xmlFree(set);
3867 set = next;
3872 * xmlSchemaFreeWildcard:
3873 * @wildcard: a wildcard structure
3875 * Deallocates a wildcard structure.
3877 void
3878 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3880 if (wildcard == NULL)
3881 return;
3882 if (wildcard->annot != NULL)
3883 xmlSchemaFreeAnnot(wildcard->annot);
3884 if (wildcard->nsSet != NULL)
3885 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3886 if (wildcard->negNsSet != NULL)
3887 xmlFree(wildcard->negNsSet);
3888 xmlFree(wildcard);
3892 * xmlSchemaFreeAttributeGroup:
3893 * @schema: a schema attribute group structure
3895 * Deallocate a Schema Attribute Group structure.
3897 static void
3898 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3900 if (attrGr == NULL)
3901 return;
3902 if (attrGr->annot != NULL)
3903 xmlSchemaFreeAnnot(attrGr->annot);
3904 if (attrGr->attrUses != NULL)
3905 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3906 xmlFree(attrGr);
3910 * xmlSchemaFreeQNameRef:
3911 * @item: a QName reference structure
3913 * Deallocatea a QName reference structure.
3915 static void
3916 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3918 xmlFree(item);
3922 * xmlSchemaFreeTypeLinkList:
3923 * @alink: a type link
3925 * Deallocate a list of types.
3927 static void
3928 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3930 xmlSchemaTypeLinkPtr next;
3932 while (link != NULL) {
3933 next = link->next;
3934 xmlFree(link);
3935 link = next;
3939 static void
3940 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3942 xmlSchemaIDCStateObjPtr next;
3943 while (sto != NULL) {
3944 next = sto->next;
3945 if (sto->history != NULL)
3946 xmlFree(sto->history);
3947 if (sto->xpathCtxt != NULL)
3948 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3949 xmlFree(sto);
3950 sto = next;
3955 * xmlSchemaFreeIDC:
3956 * @idc: a identity-constraint definition
3958 * Deallocates an identity-constraint definition.
3960 static void
3961 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3963 xmlSchemaIDCSelectPtr cur, prev;
3965 if (idcDef == NULL)
3966 return;
3967 if (idcDef->annot != NULL)
3968 xmlSchemaFreeAnnot(idcDef->annot);
3969 /* Selector */
3970 if (idcDef->selector != NULL) {
3971 if (idcDef->selector->xpathComp != NULL)
3972 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3973 xmlFree(idcDef->selector);
3975 /* Fields */
3976 if (idcDef->fields != NULL) {
3977 cur = idcDef->fields;
3978 do {
3979 prev = cur;
3980 cur = cur->next;
3981 if (prev->xpathComp != NULL)
3982 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3983 xmlFree(prev);
3984 } while (cur != NULL);
3986 xmlFree(idcDef);
3990 * xmlSchemaFreeElement:
3991 * @schema: a schema element structure
3993 * Deallocate a Schema Element structure.
3995 static void
3996 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3998 if (elem == NULL)
3999 return;
4000 if (elem->annot != NULL)
4001 xmlSchemaFreeAnnot(elem->annot);
4002 if (elem->contModel != NULL)
4003 xmlRegFreeRegexp(elem->contModel);
4004 if (elem->defVal != NULL)
4005 xmlSchemaFreeValue(elem->defVal);
4006 xmlFree(elem);
4010 * xmlSchemaFreeFacet:
4011 * @facet: a schema facet structure
4013 * Deallocate a Schema Facet structure.
4015 void
4016 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
4018 if (facet == NULL)
4019 return;
4020 if (facet->val != NULL)
4021 xmlSchemaFreeValue(facet->val);
4022 if (facet->regexp != NULL)
4023 xmlRegFreeRegexp(facet->regexp);
4024 if (facet->annot != NULL)
4025 xmlSchemaFreeAnnot(facet->annot);
4026 xmlFree(facet);
4030 * xmlSchemaFreeType:
4031 * @type: a schema type structure
4033 * Deallocate a Schema Type structure.
4035 void
4036 xmlSchemaFreeType(xmlSchemaTypePtr type)
4038 if (type == NULL)
4039 return;
4040 if (type->annot != NULL)
4041 xmlSchemaFreeAnnot(type->annot);
4042 if (type->facets != NULL) {
4043 xmlSchemaFacetPtr facet, next;
4045 facet = type->facets;
4046 while (facet != NULL) {
4047 next = facet->next;
4048 xmlSchemaFreeFacet(facet);
4049 facet = next;
4052 if (type->attrUses != NULL)
4053 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4054 if (type->memberTypes != NULL)
4055 xmlSchemaFreeTypeLinkList(type->memberTypes);
4056 if (type->facetSet != NULL) {
4057 xmlSchemaFacetLinkPtr next, link;
4059 link = type->facetSet;
4060 do {
4061 next = link->next;
4062 xmlFree(link);
4063 link = next;
4064 } while (link != NULL);
4066 if (type->contModel != NULL)
4067 xmlRegFreeRegexp(type->contModel);
4068 xmlFree(type);
4072 * xmlSchemaFreeModelGroupDef:
4073 * @item: a schema model group definition
4075 * Deallocates a schema model group definition.
4077 static void
4078 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4080 if (item->annot != NULL)
4081 xmlSchemaFreeAnnot(item->annot);
4082 xmlFree(item);
4086 * xmlSchemaFreeModelGroup:
4087 * @item: a schema model group
4089 * Deallocates a schema model group structure.
4091 static void
4092 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4094 if (item->annot != NULL)
4095 xmlSchemaFreeAnnot(item->annot);
4096 xmlFree(item);
4099 static void
4100 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4102 if ((list == NULL) || (list->nbItems == 0))
4103 return;
4105 xmlSchemaTreeItemPtr item;
4106 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4107 int i;
4109 for (i = 0; i < list->nbItems; i++) {
4110 item = items[i];
4111 if (item == NULL)
4112 continue;
4113 switch (item->type) {
4114 case XML_SCHEMA_TYPE_SIMPLE:
4115 case XML_SCHEMA_TYPE_COMPLEX:
4116 xmlSchemaFreeType((xmlSchemaTypePtr) item);
4117 break;
4118 case XML_SCHEMA_TYPE_ATTRIBUTE:
4119 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4120 break;
4121 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4122 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4123 break;
4124 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4125 xmlSchemaFreeAttributeUseProhib(
4126 (xmlSchemaAttributeUseProhibPtr) item);
4127 break;
4128 case XML_SCHEMA_TYPE_ELEMENT:
4129 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4130 break;
4131 case XML_SCHEMA_TYPE_PARTICLE:
4132 if (item->annot != NULL)
4133 xmlSchemaFreeAnnot(item->annot);
4134 xmlFree(item);
4135 break;
4136 case XML_SCHEMA_TYPE_SEQUENCE:
4137 case XML_SCHEMA_TYPE_CHOICE:
4138 case XML_SCHEMA_TYPE_ALL:
4139 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4140 break;
4141 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4142 xmlSchemaFreeAttributeGroup(
4143 (xmlSchemaAttributeGroupPtr) item);
4144 break;
4145 case XML_SCHEMA_TYPE_GROUP:
4146 xmlSchemaFreeModelGroupDef(
4147 (xmlSchemaModelGroupDefPtr) item);
4148 break;
4149 case XML_SCHEMA_TYPE_ANY:
4150 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4151 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4152 break;
4153 case XML_SCHEMA_TYPE_IDC_KEY:
4154 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4155 case XML_SCHEMA_TYPE_IDC_KEYREF:
4156 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4157 break;
4158 case XML_SCHEMA_TYPE_NOTATION:
4159 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4160 break;
4161 case XML_SCHEMA_EXTRA_QNAMEREF:
4162 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4163 break;
4164 default: {
4165 /* TODO: This should never be hit. */
4166 xmlSchemaPSimpleInternalErr(NULL,
4167 "Internal error: xmlSchemaComponentListFree, "
4168 "unexpected component type '%s'\n",
4169 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4171 break;
4174 list->nbItems = 0;
4179 * xmlSchemaFree:
4180 * @schema: a schema structure
4182 * Deallocate a Schema structure.
4184 void
4185 xmlSchemaFree(xmlSchemaPtr schema)
4187 if (schema == NULL)
4188 return;
4189 /* @volatiles is not used anymore :-/ */
4190 if (schema->volatiles != NULL)
4191 TODO
4193 * Note that those slots are not responsible for freeing
4194 * schema components anymore; this will now be done by
4195 * the schema buckets.
4197 if (schema->notaDecl != NULL)
4198 xmlHashFree(schema->notaDecl, NULL);
4199 if (schema->attrDecl != NULL)
4200 xmlHashFree(schema->attrDecl, NULL);
4201 if (schema->attrgrpDecl != NULL)
4202 xmlHashFree(schema->attrgrpDecl, NULL);
4203 if (schema->elemDecl != NULL)
4204 xmlHashFree(schema->elemDecl, NULL);
4205 if (schema->typeDecl != NULL)
4206 xmlHashFree(schema->typeDecl, NULL);
4207 if (schema->groupDecl != NULL)
4208 xmlHashFree(schema->groupDecl, NULL);
4209 if (schema->idcDef != NULL)
4210 xmlHashFree(schema->idcDef, NULL);
4212 if (schema->schemasImports != NULL)
4213 xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4214 if (schema->includes != NULL) {
4215 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4216 int i;
4217 for (i = 0; i < list->nbItems; i++) {
4218 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4220 xmlSchemaItemListFree(list);
4222 if (schema->annot != NULL)
4223 xmlSchemaFreeAnnot(schema->annot);
4224 /* Never free the doc here, since this will be done by the buckets. */
4226 xmlDictFree(schema->dict);
4227 xmlFree(schema);
4230 /************************************************************************
4232 * Debug functions *
4234 ************************************************************************/
4236 #ifdef LIBXML_OUTPUT_ENABLED
4238 static void
4239 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4242 * xmlSchemaElementDump:
4243 * @elem: an element
4244 * @output: the file output
4246 * Dump the element
4248 static void
4249 xmlSchemaElementDump(void *payload, void *data,
4250 const xmlChar * name ATTRIBUTE_UNUSED,
4251 const xmlChar * namespace ATTRIBUTE_UNUSED,
4252 const xmlChar * context ATTRIBUTE_UNUSED)
4254 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4255 FILE *output = (FILE *) data;
4256 if (elem == NULL)
4257 return;
4260 fprintf(output, "Element");
4261 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4262 fprintf(output, " (global)");
4263 fprintf(output, ": '%s' ", elem->name);
4264 if (namespace != NULL)
4265 fprintf(output, "ns '%s'", namespace);
4266 fprintf(output, "\n");
4267 #if 0
4268 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4269 fprintf(output, " min %d ", elem->minOccurs);
4270 if (elem->maxOccurs >= UNBOUNDED)
4271 fprintf(output, "max: unbounded\n");
4272 else if (elem->maxOccurs != 1)
4273 fprintf(output, "max: %d\n", elem->maxOccurs);
4274 else
4275 fprintf(output, "\n");
4277 #endif
4279 * Misc other properties.
4281 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4282 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4283 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4284 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4285 fprintf(output, " props: ");
4286 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4287 fprintf(output, "[fixed] ");
4288 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4289 fprintf(output, "[default] ");
4290 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4291 fprintf(output, "[abstract] ");
4292 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4293 fprintf(output, "[nillable] ");
4294 fprintf(output, "\n");
4297 * Default/fixed value.
4299 if (elem->value != NULL)
4300 fprintf(output, " value: '%s'\n", elem->value);
4302 * Type.
4304 if (elem->namedType != NULL) {
4305 fprintf(output, " type: '%s' ", elem->namedType);
4306 if (elem->namedTypeNs != NULL)
4307 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4308 else
4309 fprintf(output, "\n");
4310 } else if (elem->subtypes != NULL) {
4312 * Dump local types.
4314 xmlSchemaTypeDump(elem->subtypes, output);
4317 * Substitution group.
4319 if (elem->substGroup != NULL) {
4320 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
4321 if (elem->substGroupNs != NULL)
4322 fprintf(output, "ns '%s'\n", elem->substGroupNs);
4323 else
4324 fprintf(output, "\n");
4329 * xmlSchemaAnnotDump:
4330 * @output: the file output
4331 * @annot: a annotation
4333 * Dump the annotation
4335 static void
4336 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4338 xmlChar *content;
4340 if (annot == NULL)
4341 return;
4343 content = xmlNodeGetContent(annot->content);
4344 if (content != NULL) {
4345 fprintf(output, " Annot: %s\n", content);
4346 xmlFree(content);
4347 } else
4348 fprintf(output, " Annot: empty\n");
4352 * xmlSchemaContentModelDump:
4353 * @particle: the schema particle
4354 * @output: the file output
4355 * @depth: the depth used for indentation
4357 * Dump a SchemaType structure
4359 static void
4360 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4362 xmlChar *str = NULL;
4363 xmlSchemaTreeItemPtr term;
4364 char shift[100];
4365 int i;
4367 if (particle == NULL)
4368 return;
4369 for (i = 0;((i < depth) && (i < 25));i++)
4370 shift[2 * i] = shift[2 * i + 1] = ' ';
4371 shift[2 * i] = shift[2 * i + 1] = 0;
4372 fprintf(output, "%s", shift);
4373 if (particle->children == NULL) {
4374 fprintf(output, "MISSING particle term\n");
4375 return;
4377 term = particle->children;
4378 if (term == NULL) {
4379 fprintf(output, "(NULL)");
4380 } else {
4381 switch (term->type) {
4382 case XML_SCHEMA_TYPE_ELEMENT:
4383 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4384 ((xmlSchemaElementPtr)term)->targetNamespace,
4385 ((xmlSchemaElementPtr)term)->name));
4386 FREE_AND_NULL(str);
4387 break;
4388 case XML_SCHEMA_TYPE_SEQUENCE:
4389 fprintf(output, "SEQUENCE");
4390 break;
4391 case XML_SCHEMA_TYPE_CHOICE:
4392 fprintf(output, "CHOICE");
4393 break;
4394 case XML_SCHEMA_TYPE_ALL:
4395 fprintf(output, "ALL");
4396 break;
4397 case XML_SCHEMA_TYPE_ANY:
4398 fprintf(output, "ANY");
4399 break;
4400 default:
4401 fprintf(output, "UNKNOWN\n");
4402 return;
4405 if (particle->minOccurs != 1)
4406 fprintf(output, " min: %d", particle->minOccurs);
4407 if (particle->maxOccurs >= UNBOUNDED)
4408 fprintf(output, " max: unbounded");
4409 else if (particle->maxOccurs != 1)
4410 fprintf(output, " max: %d", particle->maxOccurs);
4411 fprintf(output, "\n");
4412 if (term &&
4413 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4414 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4415 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4416 (term->children != NULL)) {
4417 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4418 output, depth +1);
4420 if (particle->next != NULL)
4421 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4422 output, depth);
4426 * xmlSchemaAttrUsesDump:
4427 * @uses: attribute uses list
4428 * @output: the file output
4430 * Dumps a list of attribute use components.
4432 static void
4433 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4435 xmlSchemaAttributeUsePtr use;
4436 xmlSchemaAttributeUseProhibPtr prohib;
4437 xmlSchemaQNameRefPtr ref;
4438 const xmlChar *name, *tns;
4439 xmlChar *str = NULL;
4440 int i;
4442 if ((uses == NULL) || (uses->nbItems == 0))
4443 return;
4445 fprintf(output, " attributes:\n");
4446 for (i = 0; i < uses->nbItems; i++) {
4447 use = uses->items[i];
4448 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4449 fprintf(output, " [prohibition] ");
4450 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4451 name = prohib->name;
4452 tns = prohib->targetNamespace;
4453 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4454 fprintf(output, " [reference] ");
4455 ref = (xmlSchemaQNameRefPtr) use;
4456 name = ref->name;
4457 tns = ref->targetNamespace;
4458 } else {
4459 fprintf(output, " [use] ");
4460 name = WXS_ATTRUSE_DECL_NAME(use);
4461 tns = WXS_ATTRUSE_DECL_TNS(use);
4463 fprintf(output, "'%s'\n",
4464 (const char *) xmlSchemaFormatQName(&str, tns, name));
4465 FREE_AND_NULL(str);
4470 * xmlSchemaTypeDump:
4471 * @output: the file output
4472 * @type: a type structure
4474 * Dump a SchemaType structure
4476 static void
4477 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4479 if (type == NULL) {
4480 fprintf(output, "Type: NULL\n");
4481 return;
4483 fprintf(output, "Type: ");
4484 if (type->name != NULL)
4485 fprintf(output, "'%s' ", type->name);
4486 else
4487 fprintf(output, "(no name) ");
4488 if (type->targetNamespace != NULL)
4489 fprintf(output, "ns '%s' ", type->targetNamespace);
4490 switch (type->type) {
4491 case XML_SCHEMA_TYPE_BASIC:
4492 fprintf(output, "[basic] ");
4493 break;
4494 case XML_SCHEMA_TYPE_SIMPLE:
4495 fprintf(output, "[simple] ");
4496 break;
4497 case XML_SCHEMA_TYPE_COMPLEX:
4498 fprintf(output, "[complex] ");
4499 break;
4500 case XML_SCHEMA_TYPE_SEQUENCE:
4501 fprintf(output, "[sequence] ");
4502 break;
4503 case XML_SCHEMA_TYPE_CHOICE:
4504 fprintf(output, "[choice] ");
4505 break;
4506 case XML_SCHEMA_TYPE_ALL:
4507 fprintf(output, "[all] ");
4508 break;
4509 case XML_SCHEMA_TYPE_UR:
4510 fprintf(output, "[ur] ");
4511 break;
4512 case XML_SCHEMA_TYPE_RESTRICTION:
4513 fprintf(output, "[restriction] ");
4514 break;
4515 case XML_SCHEMA_TYPE_EXTENSION:
4516 fprintf(output, "[extension] ");
4517 break;
4518 default:
4519 fprintf(output, "[unknown type %d] ", type->type);
4520 break;
4522 fprintf(output, "content: ");
4523 switch (type->contentType) {
4524 case XML_SCHEMA_CONTENT_UNKNOWN:
4525 fprintf(output, "[unknown] ");
4526 break;
4527 case XML_SCHEMA_CONTENT_EMPTY:
4528 fprintf(output, "[empty] ");
4529 break;
4530 case XML_SCHEMA_CONTENT_ELEMENTS:
4531 fprintf(output, "[element] ");
4532 break;
4533 case XML_SCHEMA_CONTENT_MIXED:
4534 fprintf(output, "[mixed] ");
4535 break;
4536 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4537 /* not used. */
4538 break;
4539 case XML_SCHEMA_CONTENT_BASIC:
4540 fprintf(output, "[basic] ");
4541 break;
4542 case XML_SCHEMA_CONTENT_SIMPLE:
4543 fprintf(output, "[simple] ");
4544 break;
4545 case XML_SCHEMA_CONTENT_ANY:
4546 fprintf(output, "[any] ");
4547 break;
4549 fprintf(output, "\n");
4550 if (type->base != NULL) {
4551 fprintf(output, " base type: '%s'", type->base);
4552 if (type->baseNs != NULL)
4553 fprintf(output, " ns '%s'\n", type->baseNs);
4554 else
4555 fprintf(output, "\n");
4557 if (type->attrUses != NULL)
4558 xmlSchemaAttrUsesDump(type->attrUses, output);
4559 if (type->annot != NULL)
4560 xmlSchemaAnnotDump(output, type->annot);
4561 #ifdef DUMP_CONTENT_MODEL
4562 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4563 (type->subtypes != NULL)) {
4564 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4565 output, 1);
4567 #endif
4570 static void
4571 xmlSchemaTypeDumpEntry(void *type, void *output,
4572 const xmlChar *name ATTRIBUTE_UNUSED)
4574 xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4578 * xmlSchemaDump:
4579 * @output: the file output
4580 * @schema: a schema structure
4582 * Dump a Schema structure.
4584 void
4585 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4587 if (output == NULL)
4588 return;
4589 if (schema == NULL) {
4590 fprintf(output, "Schemas: NULL\n");
4591 return;
4593 fprintf(output, "Schemas: ");
4594 if (schema->name != NULL)
4595 fprintf(output, "%s, ", schema->name);
4596 else
4597 fprintf(output, "no name, ");
4598 if (schema->targetNamespace != NULL)
4599 fprintf(output, "%s", (const char *) schema->targetNamespace);
4600 else
4601 fprintf(output, "no target namespace");
4602 fprintf(output, "\n");
4603 if (schema->annot != NULL)
4604 xmlSchemaAnnotDump(output, schema->annot);
4605 xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4606 xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4609 #ifdef DEBUG_IDC_NODE_TABLE
4611 * xmlSchemaDebugDumpIDCTable:
4612 * @vctxt: the WXS validation context
4614 * Displays the current IDC table for debug purposes.
4616 static void
4617 xmlSchemaDebugDumpIDCTable(FILE * output,
4618 const xmlChar *namespaceName,
4619 const xmlChar *localName,
4620 xmlSchemaPSVIIDCBindingPtr bind)
4622 xmlChar *str = NULL;
4623 const xmlChar *value;
4624 xmlSchemaPSVIIDCNodePtr tab;
4625 xmlSchemaPSVIIDCKeyPtr key;
4626 int i, j, res;
4628 fprintf(output, "IDC: TABLES on '%s'\n",
4629 xmlSchemaFormatQName(&str, namespaceName, localName));
4630 FREE_AND_NULL(str)
4632 if (bind == NULL)
4633 return;
4634 do {
4635 fprintf(output, "IDC: BINDING '%s' (%d)\n",
4636 xmlSchemaGetComponentQName(&str,
4637 bind->definition), bind->nbNodes);
4638 FREE_AND_NULL(str)
4639 for (i = 0; i < bind->nbNodes; i++) {
4640 tab = bind->nodeTable[i];
4641 fprintf(output, " ( ");
4642 for (j = 0; j < bind->definition->nbFields; j++) {
4643 key = tab->keys[j];
4644 if ((key != NULL) && (key->val != NULL)) {
4645 res = xmlSchemaGetCanonValue(key->val, &value);
4646 if (res >= 0)
4647 fprintf(output, "'%s' ", value);
4648 else
4649 fprintf(output, "CANON-VALUE-FAILED ");
4650 if (res == 0)
4651 FREE_AND_NULL(value)
4652 } else if (key != NULL)
4653 fprintf(output, "(no val), ");
4654 else
4655 fprintf(output, "(key missing), ");
4657 fprintf(output, ")\n");
4659 if (bind->dupls && bind->dupls->nbItems) {
4660 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
4661 for (i = 0; i < bind->dupls->nbItems; i++) {
4662 tab = bind->dupls->items[i];
4663 fprintf(output, " ( ");
4664 for (j = 0; j < bind->definition->nbFields; j++) {
4665 key = tab->keys[j];
4666 if ((key != NULL) && (key->val != NULL)) {
4667 res = xmlSchemaGetCanonValue(key->val, &value);
4668 if (res >= 0)
4669 fprintf(output, "'%s' ", value);
4670 else
4671 fprintf(output, "CANON-VALUE-FAILED ");
4672 if (res == 0)
4673 FREE_AND_NULL(value)
4674 } else if (key != NULL)
4675 fprintf(output, "(no val), ");
4676 else
4677 fprintf(output, "(key missing), ");
4679 fprintf(output, ")\n");
4682 bind = bind->next;
4683 } while (bind != NULL);
4685 #endif /* DEBUG_IDC */
4686 #endif /* LIBXML_OUTPUT_ENABLED */
4688 /************************************************************************
4690 * Utilities *
4692 ************************************************************************/
4695 * xmlSchemaGetPropNode:
4696 * @node: the element node
4697 * @name: the name of the attribute
4699 * Seeks an attribute with a name of @name in
4700 * no namespace.
4702 * Returns the attribute or NULL if not present.
4704 static xmlAttrPtr
4705 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4707 xmlAttrPtr prop;
4709 if ((node == NULL) || (name == NULL))
4710 return(NULL);
4711 prop = node->properties;
4712 while (prop != NULL) {
4713 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4714 return(prop);
4715 prop = prop->next;
4717 return (NULL);
4721 * xmlSchemaGetPropNodeNs:
4722 * @node: the element node
4723 * @uri: the uri
4724 * @name: the name of the attribute
4726 * Seeks an attribute with a local name of @name and
4727 * a namespace URI of @uri.
4729 * Returns the attribute or NULL if not present.
4731 static xmlAttrPtr
4732 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4734 xmlAttrPtr prop;
4736 if ((node == NULL) || (name == NULL))
4737 return(NULL);
4738 prop = node->properties;
4739 while (prop != NULL) {
4740 if ((prop->ns != NULL) &&
4741 xmlStrEqual(prop->name, BAD_CAST name) &&
4742 xmlStrEqual(prop->ns->href, BAD_CAST uri))
4743 return(prop);
4744 prop = prop->next;
4746 return (NULL);
4749 static const xmlChar *
4750 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4752 xmlChar *val;
4753 const xmlChar *ret;
4755 val = xmlNodeGetContent(node);
4756 if (val == NULL)
4757 val = xmlStrdup((xmlChar *)"");
4758 ret = xmlDictLookup(ctxt->dict, val, -1);
4759 xmlFree(val);
4760 return(ret);
4763 static const xmlChar *
4764 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4766 return((const xmlChar*) xmlNodeGetContent(node));
4770 * xmlSchemaGetProp:
4771 * @ctxt: the parser context
4772 * @node: the node
4773 * @name: the property name
4775 * Read a attribute value and internalize the string
4777 * Returns the string or NULL if not present.
4779 static const xmlChar *
4780 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4781 const char *name)
4783 xmlChar *val;
4784 const xmlChar *ret;
4786 val = xmlGetNoNsProp(node, BAD_CAST name);
4787 if (val == NULL)
4788 return(NULL);
4789 ret = xmlDictLookup(ctxt->dict, val, -1);
4790 xmlFree(val);
4791 return(ret);
4794 /************************************************************************
4796 * Parsing functions *
4798 ************************************************************************/
4800 #define WXS_FIND_GLOBAL_ITEM(slot) \
4801 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4802 ret = xmlHashLookup(schema->slot, name); \
4803 if (ret != NULL) goto exit; \
4805 if (xmlHashSize(schema->schemasImports) > 1) { \
4806 xmlSchemaImportPtr import; \
4807 if (nsName == NULL) \
4808 import = xmlHashLookup(schema->schemasImports, \
4809 XML_SCHEMAS_NO_NAMESPACE); \
4810 else \
4811 import = xmlHashLookup(schema->schemasImports, nsName); \
4812 if (import == NULL) \
4813 goto exit; \
4814 ret = xmlHashLookup(import->schema->slot, name); \
4818 * xmlSchemaGetElem:
4819 * @schema: the schema context
4820 * @name: the element name
4821 * @ns: the element namespace
4823 * Lookup a global element declaration in the schema.
4825 * Returns the element declaration or NULL if not found.
4827 static xmlSchemaElementPtr
4828 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4829 const xmlChar * nsName)
4831 xmlSchemaElementPtr ret = NULL;
4833 if ((name == NULL) || (schema == NULL))
4834 return(NULL);
4835 if (schema != NULL) {
4836 WXS_FIND_GLOBAL_ITEM(elemDecl)
4838 exit:
4839 #ifdef DEBUG
4840 if (ret == NULL) {
4841 if (nsName == NULL)
4842 fprintf(stderr, "Unable to lookup element decl. %s", name);
4843 else
4844 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4845 nsName);
4847 #endif
4848 return (ret);
4852 * xmlSchemaGetType:
4853 * @schema: the main schema
4854 * @name: the type's name
4855 * nsName: the type's namespace
4857 * Lookup a type in the schemas or the predefined types
4859 * Returns the group definition or NULL if not found.
4861 static xmlSchemaTypePtr
4862 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4863 const xmlChar * nsName)
4865 xmlSchemaTypePtr ret = NULL;
4867 if (name == NULL)
4868 return (NULL);
4869 /* First try the built-in types. */
4870 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4871 ret = xmlSchemaGetPredefinedType(name, nsName);
4872 if (ret != NULL)
4873 goto exit;
4875 * Note that we try the parsed schemas as well here
4876 * since one might have parsed the S4S, which contain more
4877 * than the built-in types.
4878 * TODO: Can we optimize this?
4881 if (schema != NULL) {
4882 WXS_FIND_GLOBAL_ITEM(typeDecl)
4884 exit:
4886 #ifdef DEBUG
4887 if (ret == NULL) {
4888 if (nsName == NULL)
4889 fprintf(stderr, "Unable to lookup type %s", name);
4890 else
4891 fprintf(stderr, "Unable to lookup type %s:%s", name,
4892 nsName);
4894 #endif
4895 return (ret);
4899 * xmlSchemaGetAttributeDecl:
4900 * @schema: the context of the schema
4901 * @name: the name of the attribute
4902 * @ns: the target namespace of the attribute
4904 * Lookup a an attribute in the schema or imported schemas
4906 * Returns the attribute declaration or NULL if not found.
4908 static xmlSchemaAttributePtr
4909 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4910 const xmlChar * nsName)
4912 xmlSchemaAttributePtr ret = NULL;
4914 if ((name == NULL) || (schema == NULL))
4915 return (NULL);
4916 if (schema != NULL) {
4917 WXS_FIND_GLOBAL_ITEM(attrDecl)
4919 exit:
4920 #ifdef DEBUG
4921 if (ret == NULL) {
4922 if (nsName == NULL)
4923 fprintf(stderr, "Unable to lookup attribute %s", name);
4924 else
4925 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4926 nsName);
4928 #endif
4929 return (ret);
4933 * xmlSchemaGetAttributeGroup:
4934 * @schema: the context of the schema
4935 * @name: the name of the attribute group
4936 * @ns: the target namespace of the attribute group
4938 * Lookup a an attribute group in the schema or imported schemas
4940 * Returns the attribute group definition or NULL if not found.
4942 static xmlSchemaAttributeGroupPtr
4943 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4944 const xmlChar * nsName)
4946 xmlSchemaAttributeGroupPtr ret = NULL;
4948 if ((name == NULL) || (schema == NULL))
4949 return (NULL);
4950 if (schema != NULL) {
4951 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4953 exit:
4954 /* TODO:
4955 if ((ret != NULL) && (ret->redef != NULL)) {
4956 * Return the last redefinition. *
4957 ret = ret->redef;
4960 #ifdef DEBUG
4961 if (ret == NULL) {
4962 if (nsName == NULL)
4963 fprintf(stderr, "Unable to lookup attribute group %s", name);
4964 else
4965 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4966 nsName);
4968 #endif
4969 return (ret);
4973 * xmlSchemaGetGroup:
4974 * @schema: the context of the schema
4975 * @name: the name of the group
4976 * @ns: the target namespace of the group
4978 * Lookup a group in the schema or imported schemas
4980 * Returns the group definition or NULL if not found.
4982 static xmlSchemaModelGroupDefPtr
4983 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4984 const xmlChar * nsName)
4986 xmlSchemaModelGroupDefPtr ret = NULL;
4988 if ((name == NULL) || (schema == NULL))
4989 return (NULL);
4990 if (schema != NULL) {
4991 WXS_FIND_GLOBAL_ITEM(groupDecl)
4993 exit:
4995 #ifdef DEBUG
4996 if (ret == NULL) {
4997 if (nsName == NULL)
4998 fprintf(stderr, "Unable to lookup group %s", name);
4999 else
5000 fprintf(stderr, "Unable to lookup group %s:%s", name,
5001 nsName);
5003 #endif
5004 return (ret);
5007 static xmlSchemaNotationPtr
5008 xmlSchemaGetNotation(xmlSchemaPtr schema,
5009 const xmlChar *name,
5010 const xmlChar *nsName)
5012 xmlSchemaNotationPtr ret = NULL;
5014 if ((name == NULL) || (schema == NULL))
5015 return (NULL);
5016 if (schema != NULL) {
5017 WXS_FIND_GLOBAL_ITEM(notaDecl)
5019 exit:
5020 return (ret);
5023 static xmlSchemaIDCPtr
5024 xmlSchemaGetIDC(xmlSchemaPtr schema,
5025 const xmlChar *name,
5026 const xmlChar *nsName)
5028 xmlSchemaIDCPtr ret = NULL;
5030 if ((name == NULL) || (schema == NULL))
5031 return (NULL);
5032 if (schema != NULL) {
5033 WXS_FIND_GLOBAL_ITEM(idcDef)
5035 exit:
5036 return (ret);
5040 * xmlSchemaGetNamedComponent:
5041 * @schema: the schema
5042 * @name: the name of the group
5043 * @ns: the target namespace of the group
5045 * Lookup a group in the schema or imported schemas
5047 * Returns the group definition or NULL if not found.
5049 static xmlSchemaBasicItemPtr
5050 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
5051 xmlSchemaTypeType itemType,
5052 const xmlChar *name,
5053 const xmlChar *targetNs)
5055 switch (itemType) {
5056 case XML_SCHEMA_TYPE_GROUP:
5057 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
5058 name, targetNs));
5059 case XML_SCHEMA_TYPE_ELEMENT:
5060 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
5061 name, targetNs));
5062 default:
5063 TODO
5064 return (NULL);
5068 /************************************************************************
5070 * Parsing functions *
5072 ************************************************************************/
5074 #define IS_BLANK_NODE(n) \
5075 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
5078 * xmlSchemaIsBlank:
5079 * @str: a string
5080 * @len: the length of the string or -1
5082 * Check if a string is ignorable
5084 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5086 static int
5087 xmlSchemaIsBlank(xmlChar * str, int len)
5089 if (str == NULL)
5090 return (1);
5091 if (len < 0) {
5092 while (*str != 0) {
5093 if (!(IS_BLANK_CH(*str)))
5094 return (0);
5095 str++;
5097 } else while ((*str != 0) && (len != 0)) {
5098 if (!(IS_BLANK_CH(*str)))
5099 return (0);
5100 str++;
5101 len--;
5104 return (1);
5107 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5108 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5110 * xmlSchemaFindRedefCompInGraph:
5111 * ATTENTION TODO: This uses pointer comp. for strings.
5113 static xmlSchemaBasicItemPtr
5114 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5115 xmlSchemaTypeType type,
5116 const xmlChar *name,
5117 const xmlChar *nsName)
5119 xmlSchemaBasicItemPtr ret;
5120 int i;
5122 if ((bucket == NULL) || (name == NULL))
5123 return(NULL);
5124 if ((bucket->globals == NULL) ||
5125 (bucket->globals->nbItems == 0))
5126 goto subschemas;
5128 * Search in global components.
5130 for (i = 0; i < bucket->globals->nbItems; i++) {
5131 ret = bucket->globals->items[i];
5132 if (ret->type == type) {
5133 switch (type) {
5134 case XML_SCHEMA_TYPE_COMPLEX:
5135 case XML_SCHEMA_TYPE_SIMPLE:
5136 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5137 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5138 nsName))
5140 return(ret);
5142 break;
5143 case XML_SCHEMA_TYPE_GROUP:
5144 if ((WXS_COMP_NAME(ret,
5145 xmlSchemaModelGroupDefPtr) == name) &&
5146 (WXS_COMP_TNS(ret,
5147 xmlSchemaModelGroupDefPtr) == nsName))
5149 return(ret);
5151 break;
5152 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5153 if ((WXS_COMP_NAME(ret,
5154 xmlSchemaAttributeGroupPtr) == name) &&
5155 (WXS_COMP_TNS(ret,
5156 xmlSchemaAttributeGroupPtr) == nsName))
5158 return(ret);
5160 break;
5161 default:
5162 /* Should not be hit. */
5163 return(NULL);
5167 subschemas:
5169 * Process imported/included schemas.
5171 if (bucket->relations != NULL) {
5172 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5175 * TODO: Marking the bucket will not avoid multiple searches
5176 * in the same schema, but avoids at least circularity.
5178 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5179 do {
5180 if ((rel->bucket != NULL) &&
5181 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5182 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5183 type, name, nsName);
5184 if (ret != NULL)
5185 return(ret);
5187 rel = rel->next;
5188 } while (rel != NULL);
5189 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5191 return(NULL);
5195 * xmlSchemaAddNotation:
5196 * @ctxt: a schema parser context
5197 * @schema: the schema being built
5198 * @name: the item name
5200 * Add an XML schema annotation declaration
5201 * *WARNING* this interface is highly subject to change
5203 * Returns the new structure or NULL in case of error
5205 static xmlSchemaNotationPtr
5206 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5207 const xmlChar *name, const xmlChar *nsName,
5208 xmlNodePtr node ATTRIBUTE_UNUSED)
5210 xmlSchemaNotationPtr ret = NULL;
5212 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5213 return (NULL);
5215 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5216 if (ret == NULL) {
5217 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5218 return (NULL);
5220 memset(ret, 0, sizeof(xmlSchemaNotation));
5221 ret->type = XML_SCHEMA_TYPE_NOTATION;
5222 ret->name = name;
5223 ret->targetNamespace = nsName;
5224 /* TODO: do we need the node to be set?
5225 * ret->node = node;*/
5226 WXS_ADD_GLOBAL(ctxt, ret);
5227 return (ret);
5231 * xmlSchemaAddAttribute:
5232 * @ctxt: a schema parser context
5233 * @schema: the schema being built
5234 * @name: the item name
5235 * @namespace: the namespace
5237 * Add an XML schema Attribute declaration
5238 * *WARNING* this interface is highly subject to change
5240 * Returns the new structure or NULL in case of error
5242 static xmlSchemaAttributePtr
5243 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5244 const xmlChar * name, const xmlChar * nsName,
5245 xmlNodePtr node, int topLevel)
5247 xmlSchemaAttributePtr ret = NULL;
5249 if ((ctxt == NULL) || (schema == NULL))
5250 return (NULL);
5252 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5253 if (ret == NULL) {
5254 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5255 return (NULL);
5257 memset(ret, 0, sizeof(xmlSchemaAttribute));
5258 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5259 ret->node = node;
5260 ret->name = name;
5261 ret->targetNamespace = nsName;
5263 if (topLevel)
5264 WXS_ADD_GLOBAL(ctxt, ret);
5265 else
5266 WXS_ADD_LOCAL(ctxt, ret);
5267 WXS_ADD_PENDING(ctxt, ret);
5268 return (ret);
5272 * xmlSchemaAddAttributeUse:
5273 * @ctxt: a schema parser context
5274 * @schema: the schema being built
5275 * @name: the item name
5276 * @namespace: the namespace
5278 * Add an XML schema Attribute declaration
5279 * *WARNING* this interface is highly subject to change
5281 * Returns the new structure or NULL in case of error
5283 static xmlSchemaAttributeUsePtr
5284 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5285 xmlNodePtr node)
5287 xmlSchemaAttributeUsePtr ret = NULL;
5289 if (pctxt == NULL)
5290 return (NULL);
5292 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5293 if (ret == NULL) {
5294 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5295 return (NULL);
5297 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5298 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5299 ret->node = node;
5301 WXS_ADD_LOCAL(pctxt, ret);
5302 return (ret);
5306 * xmlSchemaAddRedef:
5308 * Adds a redefinition information. This is used at a later stage to:
5309 * resolve references to the redefined components and to check constraints.
5311 static xmlSchemaRedefPtr
5312 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5313 xmlSchemaBucketPtr targetBucket,
5314 void *item,
5315 const xmlChar *refName,
5316 const xmlChar *refTargetNs)
5318 xmlSchemaRedefPtr ret;
5320 ret = (xmlSchemaRedefPtr)
5321 xmlMalloc(sizeof(xmlSchemaRedef));
5322 if (ret == NULL) {
5323 xmlSchemaPErrMemory(pctxt,
5324 "allocating redefinition info", NULL);
5325 return (NULL);
5327 memset(ret, 0, sizeof(xmlSchemaRedef));
5328 ret->item = item;
5329 ret->targetBucket = targetBucket;
5330 ret->refName = refName;
5331 ret->refTargetNs = refTargetNs;
5332 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5333 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5334 else
5335 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5336 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5338 return (ret);
5342 * xmlSchemaAddAttributeGroupDefinition:
5343 * @ctxt: a schema parser context
5344 * @schema: the schema being built
5345 * @name: the item name
5346 * @nsName: the target namespace
5347 * @node: the corresponding node
5349 * Add an XML schema Attribute Group definition.
5351 * Returns the new structure or NULL in case of error
5353 static xmlSchemaAttributeGroupPtr
5354 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5355 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5356 const xmlChar *name,
5357 const xmlChar *nsName,
5358 xmlNodePtr node)
5360 xmlSchemaAttributeGroupPtr ret = NULL;
5362 if ((pctxt == NULL) || (name == NULL))
5363 return (NULL);
5365 ret = (xmlSchemaAttributeGroupPtr)
5366 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5367 if (ret == NULL) {
5368 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5369 return (NULL);
5371 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5372 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5373 ret->name = name;
5374 ret->targetNamespace = nsName;
5375 ret->node = node;
5377 /* TODO: Remove the flag. */
5378 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5379 if (pctxt->isRedefine) {
5380 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5381 ret, name, nsName);
5382 if (pctxt->redef == NULL) {
5383 xmlFree(ret);
5384 return(NULL);
5386 pctxt->redefCounter = 0;
5388 WXS_ADD_GLOBAL(pctxt, ret);
5389 WXS_ADD_PENDING(pctxt, ret);
5390 return (ret);
5394 * xmlSchemaAddElement:
5395 * @ctxt: a schema parser context
5396 * @schema: the schema being built
5397 * @name: the type name
5398 * @namespace: the type namespace
5400 * Add an XML schema Element declaration
5401 * *WARNING* this interface is highly subject to change
5403 * Returns the new structure or NULL in case of error
5405 static xmlSchemaElementPtr
5406 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5407 const xmlChar * name, const xmlChar * nsName,
5408 xmlNodePtr node, int topLevel)
5410 xmlSchemaElementPtr ret = NULL;
5412 if ((ctxt == NULL) || (name == NULL))
5413 return (NULL);
5415 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5416 if (ret == NULL) {
5417 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5418 return (NULL);
5420 memset(ret, 0, sizeof(xmlSchemaElement));
5421 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5422 ret->name = name;
5423 ret->targetNamespace = nsName;
5424 ret->node = node;
5426 if (topLevel)
5427 WXS_ADD_GLOBAL(ctxt, ret);
5428 else
5429 WXS_ADD_LOCAL(ctxt, ret);
5430 WXS_ADD_PENDING(ctxt, ret);
5431 return (ret);
5435 * xmlSchemaAddType:
5436 * @ctxt: a schema parser context
5437 * @schema: the schema being built
5438 * @name: the item name
5439 * @namespace: the namespace
5441 * Add an XML schema item
5442 * *WARNING* this interface is highly subject to change
5444 * Returns the new structure or NULL in case of error
5446 static xmlSchemaTypePtr
5447 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5448 xmlSchemaTypeType type,
5449 const xmlChar * name, const xmlChar * nsName,
5450 xmlNodePtr node, int topLevel)
5452 xmlSchemaTypePtr ret = NULL;
5454 if ((ctxt == NULL) || (schema == NULL))
5455 return (NULL);
5457 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5458 if (ret == NULL) {
5459 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5460 return (NULL);
5462 memset(ret, 0, sizeof(xmlSchemaType));
5463 ret->type = type;
5464 ret->name = name;
5465 ret->targetNamespace = nsName;
5466 ret->node = node;
5467 if (topLevel) {
5468 if (ctxt->isRedefine) {
5469 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5470 ret, name, nsName);
5471 if (ctxt->redef == NULL) {
5472 xmlFree(ret);
5473 return(NULL);
5475 ctxt->redefCounter = 0;
5477 WXS_ADD_GLOBAL(ctxt, ret);
5478 } else
5479 WXS_ADD_LOCAL(ctxt, ret);
5480 WXS_ADD_PENDING(ctxt, ret);
5481 return (ret);
5484 static xmlSchemaQNameRefPtr
5485 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5486 xmlSchemaTypeType refType,
5487 const xmlChar *refName,
5488 const xmlChar *refNs)
5490 xmlSchemaQNameRefPtr ret;
5492 ret = (xmlSchemaQNameRefPtr)
5493 xmlMalloc(sizeof(xmlSchemaQNameRef));
5494 if (ret == NULL) {
5495 xmlSchemaPErrMemory(pctxt,
5496 "allocating QName reference item", NULL);
5497 return (NULL);
5499 ret->node = NULL;
5500 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5501 ret->name = refName;
5502 ret->targetNamespace = refNs;
5503 ret->item = NULL;
5504 ret->itemType = refType;
5506 * Store the reference item in the schema.
5508 WXS_ADD_LOCAL(pctxt, ret);
5509 return (ret);
5512 static xmlSchemaAttributeUseProhibPtr
5513 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5515 xmlSchemaAttributeUseProhibPtr ret;
5517 ret = (xmlSchemaAttributeUseProhibPtr)
5518 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5519 if (ret == NULL) {
5520 xmlSchemaPErrMemory(pctxt,
5521 "allocating attribute use prohibition", NULL);
5522 return (NULL);
5524 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5525 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5526 WXS_ADD_LOCAL(pctxt, ret);
5527 return (ret);
5532 * xmlSchemaAddModelGroup:
5533 * @ctxt: a schema parser context
5534 * @schema: the schema being built
5535 * @type: the "compositor" type of the model group
5536 * @node: the node in the schema doc
5538 * Adds a schema model group
5539 * *WARNING* this interface is highly subject to change
5541 * Returns the new structure or NULL in case of error
5543 static xmlSchemaModelGroupPtr
5544 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5545 xmlSchemaPtr schema,
5546 xmlSchemaTypeType type,
5547 xmlNodePtr node)
5549 xmlSchemaModelGroupPtr ret = NULL;
5551 if ((ctxt == NULL) || (schema == NULL))
5552 return (NULL);
5554 ret = (xmlSchemaModelGroupPtr)
5555 xmlMalloc(sizeof(xmlSchemaModelGroup));
5556 if (ret == NULL) {
5557 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5558 NULL);
5559 return (NULL);
5561 memset(ret, 0, sizeof(xmlSchemaModelGroup));
5562 ret->type = type;
5563 ret->node = node;
5564 WXS_ADD_LOCAL(ctxt, ret);
5565 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5566 (type == XML_SCHEMA_TYPE_CHOICE))
5567 WXS_ADD_PENDING(ctxt, ret);
5568 return (ret);
5573 * xmlSchemaAddParticle:
5574 * @ctxt: a schema parser context
5575 * @schema: the schema being built
5576 * @node: the corresponding node in the schema doc
5577 * @min: the minOccurs
5578 * @max: the maxOccurs
5580 * Adds an XML schema particle component.
5581 * *WARNING* this interface is highly subject to change
5583 * Returns the new structure or NULL in case of error
5585 static xmlSchemaParticlePtr
5586 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5587 xmlNodePtr node, int min, int max)
5589 xmlSchemaParticlePtr ret = NULL;
5590 if (ctxt == NULL)
5591 return (NULL);
5593 #ifdef DEBUG
5594 fprintf(stderr, "Adding particle component\n");
5595 #endif
5596 ret = (xmlSchemaParticlePtr)
5597 xmlMalloc(sizeof(xmlSchemaParticle));
5598 if (ret == NULL) {
5599 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5600 NULL);
5601 return (NULL);
5603 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5604 ret->annot = NULL;
5605 ret->node = node;
5606 ret->minOccurs = min;
5607 ret->maxOccurs = max;
5608 ret->next = NULL;
5609 ret->children = NULL;
5611 WXS_ADD_LOCAL(ctxt, ret);
5613 * Note that addition to pending components will be done locally
5614 * to the specific parsing function, since the most particles
5615 * need not to be fixed up (i.e. the reference to be resolved).
5616 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5618 return (ret);
5622 * xmlSchemaAddModelGroupDefinition:
5623 * @ctxt: a schema validation context
5624 * @schema: the schema being built
5625 * @name: the group name
5627 * Add an XML schema Group definition
5629 * Returns the new structure or NULL in case of error
5631 static xmlSchemaModelGroupDefPtr
5632 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5633 xmlSchemaPtr schema,
5634 const xmlChar *name,
5635 const xmlChar *nsName,
5636 xmlNodePtr node)
5638 xmlSchemaModelGroupDefPtr ret = NULL;
5640 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5641 return (NULL);
5643 ret = (xmlSchemaModelGroupDefPtr)
5644 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5645 if (ret == NULL) {
5646 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5647 return (NULL);
5649 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5650 ret->name = name;
5651 ret->type = XML_SCHEMA_TYPE_GROUP;
5652 ret->node = node;
5653 ret->targetNamespace = nsName;
5655 if (ctxt->isRedefine) {
5656 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5657 ret, name, nsName);
5658 if (ctxt->redef == NULL) {
5659 xmlFree(ret);
5660 return(NULL);
5662 ctxt->redefCounter = 0;
5664 WXS_ADD_GLOBAL(ctxt, ret);
5665 WXS_ADD_PENDING(ctxt, ret);
5666 return (ret);
5670 * xmlSchemaNewWildcardNs:
5671 * @ctxt: a schema validation context
5673 * Creates a new wildcard namespace constraint.
5675 * Returns the new structure or NULL in case of error
5677 static xmlSchemaWildcardNsPtr
5678 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5680 xmlSchemaWildcardNsPtr ret;
5682 ret = (xmlSchemaWildcardNsPtr)
5683 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5684 if (ret == NULL) {
5685 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5686 return (NULL);
5688 ret->value = NULL;
5689 ret->next = NULL;
5690 return (ret);
5693 static xmlSchemaIDCPtr
5694 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5695 const xmlChar *name, const xmlChar *nsName,
5696 int category, xmlNodePtr node)
5698 xmlSchemaIDCPtr ret = NULL;
5700 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5701 return (NULL);
5703 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5704 if (ret == NULL) {
5705 xmlSchemaPErrMemory(ctxt,
5706 "allocating an identity-constraint definition", NULL);
5707 return (NULL);
5709 memset(ret, 0, sizeof(xmlSchemaIDC));
5710 /* The target namespace of the parent element declaration. */
5711 ret->targetNamespace = nsName;
5712 ret->name = name;
5713 ret->type = category;
5714 ret->node = node;
5716 WXS_ADD_GLOBAL(ctxt, ret);
5718 * Only keyrefs need to be fixup up.
5720 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5721 WXS_ADD_PENDING(ctxt, ret);
5722 return (ret);
5726 * xmlSchemaAddWildcard:
5727 * @ctxt: a schema validation context
5728 * @schema: a schema
5730 * Adds a wildcard.
5731 * It corresponds to a xsd:anyAttribute and xsd:any.
5733 * Returns the new structure or NULL in case of error
5735 static xmlSchemaWildcardPtr
5736 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5737 xmlSchemaTypeType type, xmlNodePtr node)
5739 xmlSchemaWildcardPtr ret = NULL;
5741 if ((ctxt == NULL) || (schema == NULL))
5742 return (NULL);
5744 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5745 if (ret == NULL) {
5746 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5747 return (NULL);
5749 memset(ret, 0, sizeof(xmlSchemaWildcard));
5750 ret->type = type;
5751 ret->node = node;
5752 WXS_ADD_LOCAL(ctxt, ret);
5753 return (ret);
5756 static void
5757 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5759 if (group == NULL)
5760 return;
5761 if (group->members != NULL)
5762 xmlSchemaItemListFree(group->members);
5763 xmlFree(group);
5766 static void
5767 xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5769 xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5772 static xmlSchemaSubstGroupPtr
5773 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5774 xmlSchemaElementPtr head)
5776 xmlSchemaSubstGroupPtr ret;
5778 /* Init subst group hash. */
5779 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5780 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5781 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5782 return(NULL);
5784 /* Create a new substitution group. */
5785 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5786 if (ret == NULL) {
5787 xmlSchemaPErrMemory(NULL,
5788 "allocating a substitution group container", NULL);
5789 return(NULL);
5791 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5792 ret->head = head;
5793 /* Create list of members. */
5794 ret->members = xmlSchemaItemListCreate();
5795 if (ret->members == NULL) {
5796 xmlSchemaSubstGroupFree(ret);
5797 return(NULL);
5799 /* Add subst group to hash. */
5800 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5801 head->name, head->targetNamespace, ret) != 0) {
5802 PERROR_INT("xmlSchemaSubstGroupAdd",
5803 "failed to add a new substitution container");
5804 xmlSchemaSubstGroupFree(ret);
5805 return(NULL);
5807 return(ret);
5810 static xmlSchemaSubstGroupPtr
5811 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5812 xmlSchemaElementPtr head)
5814 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5815 return(NULL);
5816 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5817 head->name, head->targetNamespace));
5822 * xmlSchemaAddElementSubstitutionMember:
5823 * @pctxt: a schema parser context
5824 * @head: the head of the substitution group
5825 * @member: the new member of the substitution group
5827 * Allocate a new annotation structure.
5829 * Returns the newly allocated structure or NULL in case or error
5831 static int
5832 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5833 xmlSchemaElementPtr head,
5834 xmlSchemaElementPtr member)
5836 xmlSchemaSubstGroupPtr substGroup = NULL;
5838 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5839 return (-1);
5841 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5842 if (substGroup == NULL)
5843 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5844 if (substGroup == NULL)
5845 return(-1);
5846 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5847 return(-1);
5848 return(0);
5851 /************************************************************************
5853 * Utilities for parsing *
5855 ************************************************************************/
5858 * xmlSchemaPValAttrNodeQNameValue:
5859 * @ctxt: a schema parser context
5860 * @schema: the schema context
5861 * @ownerItem: the parent as a schema object
5862 * @value: the QName value
5863 * @uri: the resulting namespace URI if found
5864 * @local: the resulting local part if found, the attribute value otherwise
5866 * Extracts the local name and the URI of a QName value and validates it.
5867 * This one is intended to be used on attribute values that
5868 * should resolve to schema components.
5870 * Returns 0, in case the QName is valid, a positive error code
5871 * if not valid and -1 if an internal error occurs.
5873 static int
5874 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5875 xmlSchemaPtr schema,
5876 xmlSchemaBasicItemPtr ownerItem,
5877 xmlAttrPtr attr,
5878 const xmlChar *value,
5879 const xmlChar **uri,
5880 const xmlChar **local)
5882 const xmlChar *pref;
5883 xmlNsPtr ns;
5884 int len, ret;
5886 *uri = NULL;
5887 *local = NULL;
5888 ret = xmlValidateQName(value, 1);
5889 if (ret > 0) {
5890 xmlSchemaPSimpleTypeErr(ctxt,
5891 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5892 ownerItem, (xmlNodePtr) attr,
5893 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5894 NULL, value, NULL, NULL, NULL);
5895 *local = value;
5896 return (ctxt->err);
5897 } else if (ret < 0)
5898 return (-1);
5900 if (!strchr((char *) value, ':')) {
5901 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5902 if (ns && ns->href && ns->href[0])
5903 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5904 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5905 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5906 * parser context. */
5908 * This one takes care of included schemas with no
5909 * target namespace.
5911 *uri = ctxt->targetNamespace;
5913 *local = xmlDictLookup(ctxt->dict, value, -1);
5914 return (0);
5917 * At this point xmlSplitQName3 has to return a local name.
5919 *local = xmlSplitQName3(value, &len);
5920 *local = xmlDictLookup(ctxt->dict, *local, -1);
5921 pref = xmlDictLookup(ctxt->dict, value, len);
5922 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5923 if (ns == NULL) {
5924 xmlSchemaPSimpleTypeErr(ctxt,
5925 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5926 ownerItem, (xmlNodePtr) attr,
5927 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5928 "The value '%s' of simple type 'xs:QName' has no "
5929 "corresponding namespace declaration in scope", value, NULL);
5930 return (ctxt->err);
5931 } else {
5932 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5934 return (0);
5938 * xmlSchemaPValAttrNodeQName:
5939 * @ctxt: a schema parser context
5940 * @schema: the schema context
5941 * @ownerItem: the owner as a schema object
5942 * @attr: the attribute node
5943 * @uri: the resulting namespace URI if found
5944 * @local: the resulting local part if found, the attribute value otherwise
5946 * Extracts and validates the QName of an attribute value.
5947 * This one is intended to be used on attribute values that
5948 * should resolve to schema components.
5950 * Returns 0, in case the QName is valid, a positive error code
5951 * if not valid and -1 if an internal error occurs.
5953 static int
5954 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5955 xmlSchemaPtr schema,
5956 xmlSchemaBasicItemPtr ownerItem,
5957 xmlAttrPtr attr,
5958 const xmlChar **uri,
5959 const xmlChar **local)
5961 const xmlChar *value;
5963 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5964 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5965 ownerItem, attr, value, uri, local));
5969 * xmlSchemaPValAttrQName:
5970 * @ctxt: a schema parser context
5971 * @schema: the schema context
5972 * @ownerItem: the owner as a schema object
5973 * @ownerElem: the parent node of the attribute
5974 * @name: the name of the attribute
5975 * @uri: the resulting namespace URI if found
5976 * @local: the resulting local part if found, the attribute value otherwise
5978 * Extracts and validates the QName of an attribute value.
5980 * Returns 0, in case the QName is valid, a positive error code
5981 * if not valid and -1 if an internal error occurs.
5983 static int
5984 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5985 xmlSchemaPtr schema,
5986 xmlSchemaBasicItemPtr ownerItem,
5987 xmlNodePtr ownerElem,
5988 const char *name,
5989 const xmlChar **uri,
5990 const xmlChar **local)
5992 xmlAttrPtr attr;
5994 attr = xmlSchemaGetPropNode(ownerElem, name);
5995 if (attr == NULL) {
5996 *local = NULL;
5997 *uri = NULL;
5998 return (0);
6000 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
6001 ownerItem, attr, uri, local));
6005 * xmlSchemaPValAttrID:
6006 * @ctxt: a schema parser context
6008 * Extracts and validates the ID of an attribute value.
6010 * Returns 0, in case the ID is valid, a positive error code
6011 * if not valid and -1 if an internal error occurs.
6013 static int
6014 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
6016 int ret;
6017 const xmlChar *value;
6019 if (attr == NULL)
6020 return(0);
6021 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
6022 ret = xmlValidateNCName(value, 1);
6023 if (ret == 0) {
6025 * NOTE: the IDness might have already be declared in the DTD
6027 if (attr->atype != XML_ATTRIBUTE_ID) {
6028 xmlIDPtr res;
6029 xmlChar *strip;
6032 * TODO: Use xmlSchemaStrip here; it's not exported at this
6033 * moment.
6035 strip = xmlSchemaCollapseString(value);
6036 if (strip != NULL) {
6037 xmlFree((xmlChar *) value);
6038 value = strip;
6040 res = xmlAddID(NULL, attr->doc, value, attr);
6041 if (res == NULL) {
6042 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6043 xmlSchemaPSimpleTypeErr(ctxt,
6044 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6045 NULL, (xmlNodePtr) attr,
6046 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6047 NULL, NULL, "Duplicate value '%s' of simple "
6048 "type 'xs:ID'", value, NULL);
6049 } else
6050 attr->atype = XML_ATTRIBUTE_ID;
6052 } else if (ret > 0) {
6053 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6054 xmlSchemaPSimpleTypeErr(ctxt,
6055 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6056 NULL, (xmlNodePtr) attr,
6057 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6058 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
6059 "not a valid 'xs:NCName'",
6060 value, NULL);
6062 if (value != NULL)
6063 xmlFree((xmlChar *)value);
6065 return (ret);
6068 static int
6069 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
6070 xmlNodePtr ownerElem,
6071 const xmlChar *name)
6073 xmlAttrPtr attr;
6075 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
6076 if (attr == NULL)
6077 return(0);
6078 return(xmlSchemaPValAttrNodeID(ctxt, attr));
6083 * xmlGetMaxOccurs:
6084 * @ctxt: a schema validation context
6085 * @node: a subtree containing XML Schema information
6087 * Get the maxOccurs property
6089 * Returns the default if not found, or the value
6091 static int
6092 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6093 int min, int max, int def, const char *expected)
6095 const xmlChar *val, *cur;
6096 int ret = 0;
6097 xmlAttrPtr attr;
6099 attr = xmlSchemaGetPropNode(node, "maxOccurs");
6100 if (attr == NULL)
6101 return (def);
6102 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6104 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6105 if (max != UNBOUNDED) {
6106 xmlSchemaPSimpleTypeErr(ctxt,
6107 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6108 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6109 NULL, (xmlNodePtr) attr, NULL, expected,
6110 val, NULL, NULL, NULL);
6111 return (def);
6112 } else
6113 return (UNBOUNDED); /* encoding it with -1 might be another option */
6116 cur = val;
6117 while (IS_BLANK_CH(*cur))
6118 cur++;
6119 if (*cur == 0) {
6120 xmlSchemaPSimpleTypeErr(ctxt,
6121 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6122 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6123 NULL, (xmlNodePtr) attr, NULL, expected,
6124 val, NULL, NULL, NULL);
6125 return (def);
6127 while ((*cur >= '0') && (*cur <= '9')) {
6128 if (ret > INT_MAX / 10) {
6129 ret = INT_MAX;
6130 } else {
6131 int digit = *cur - '0';
6132 ret *= 10;
6133 if (ret > INT_MAX - digit)
6134 ret = INT_MAX;
6135 else
6136 ret += digit;
6138 cur++;
6140 while (IS_BLANK_CH(*cur))
6141 cur++;
6143 * TODO: Restrict the maximal value to Integer.
6145 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6146 xmlSchemaPSimpleTypeErr(ctxt,
6147 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6148 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6149 NULL, (xmlNodePtr) attr, NULL, expected,
6150 val, NULL, NULL, NULL);
6151 return (def);
6153 return (ret);
6157 * xmlGetMinOccurs:
6158 * @ctxt: a schema validation context
6159 * @node: a subtree containing XML Schema information
6161 * Get the minOccurs property
6163 * Returns the default if not found, or the value
6165 static int
6166 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6167 int min, int max, int def, const char *expected)
6169 const xmlChar *val, *cur;
6170 int ret = 0;
6171 xmlAttrPtr attr;
6173 attr = xmlSchemaGetPropNode(node, "minOccurs");
6174 if (attr == NULL)
6175 return (def);
6176 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6177 cur = val;
6178 while (IS_BLANK_CH(*cur))
6179 cur++;
6180 if (*cur == 0) {
6181 xmlSchemaPSimpleTypeErr(ctxt,
6182 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6183 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6184 NULL, (xmlNodePtr) attr, NULL, expected,
6185 val, NULL, NULL, NULL);
6186 return (def);
6188 while ((*cur >= '0') && (*cur <= '9')) {
6189 if (ret > INT_MAX / 10) {
6190 ret = INT_MAX;
6191 } else {
6192 int digit = *cur - '0';
6193 ret *= 10;
6194 if (ret > INT_MAX - digit)
6195 ret = INT_MAX;
6196 else
6197 ret += digit;
6199 cur++;
6201 while (IS_BLANK_CH(*cur))
6202 cur++;
6204 * TODO: Restrict the maximal value to Integer.
6206 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6207 xmlSchemaPSimpleTypeErr(ctxt,
6208 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6209 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6210 NULL, (xmlNodePtr) attr, NULL, expected,
6211 val, NULL, NULL, NULL);
6212 return (def);
6214 return (ret);
6218 * xmlSchemaPGetBoolNodeValue:
6219 * @ctxt: a schema validation context
6220 * @ownerItem: the owner as a schema item
6221 * @node: the node holding the value
6223 * Converts a boolean string value into 1 or 0.
6225 * Returns 0 or 1.
6227 static int
6228 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6229 xmlSchemaBasicItemPtr ownerItem,
6230 xmlNodePtr node)
6232 xmlChar *value = NULL;
6233 int res = 0;
6235 value = xmlNodeGetContent(node);
6237 * 3.2.2.1 Lexical representation
6238 * An instance of a datatype that is defined as `boolean`
6239 * can have the following legal literals {true, false, 1, 0}.
6241 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6242 res = 1;
6243 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6244 res = 0;
6245 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6246 res = 1;
6247 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6248 res = 0;
6249 else {
6250 xmlSchemaPSimpleTypeErr(ctxt,
6251 XML_SCHEMAP_INVALID_BOOLEAN,
6252 ownerItem, node,
6253 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6254 NULL, BAD_CAST value,
6255 NULL, NULL, NULL);
6257 if (value != NULL)
6258 xmlFree(value);
6259 return (res);
6263 * xmlGetBooleanProp:
6264 * @ctxt: a schema validation context
6265 * @node: a subtree containing XML Schema information
6266 * @name: the attribute name
6267 * @def: the default value
6269 * Evaluate if a boolean property is set
6271 * Returns the default if not found, 0 if found to be false,
6272 * 1 if found to be true
6274 static int
6275 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6276 xmlNodePtr node,
6277 const char *name, int def)
6279 const xmlChar *val;
6281 val = xmlSchemaGetProp(ctxt, node, name);
6282 if (val == NULL)
6283 return (def);
6285 * 3.2.2.1 Lexical representation
6286 * An instance of a datatype that is defined as `boolean`
6287 * can have the following legal literals {true, false, 1, 0}.
6289 if (xmlStrEqual(val, BAD_CAST "true"))
6290 def = 1;
6291 else if (xmlStrEqual(val, BAD_CAST "false"))
6292 def = 0;
6293 else if (xmlStrEqual(val, BAD_CAST "1"))
6294 def = 1;
6295 else if (xmlStrEqual(val, BAD_CAST "0"))
6296 def = 0;
6297 else {
6298 xmlSchemaPSimpleTypeErr(ctxt,
6299 XML_SCHEMAP_INVALID_BOOLEAN,
6300 NULL,
6301 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6302 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6303 NULL, val, NULL, NULL, NULL);
6305 return (def);
6308 /************************************************************************
6310 * Schema extraction from an Infoset *
6312 ************************************************************************/
6313 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6314 ctxt, xmlSchemaPtr schema,
6315 xmlNodePtr node,
6316 int topLevel);
6317 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6318 ctxt,
6319 xmlSchemaPtr schema,
6320 xmlNodePtr node,
6321 int topLevel);
6322 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6323 ctxt,
6324 xmlSchemaPtr schema,
6325 xmlNodePtr node,
6326 xmlSchemaTypeType parentType);
6327 static xmlSchemaBasicItemPtr
6328 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6329 xmlSchemaPtr schema,
6330 xmlNodePtr node,
6331 xmlSchemaItemListPtr uses,
6332 int parentType);
6333 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6334 xmlSchemaPtr schema,
6335 xmlNodePtr node);
6336 static xmlSchemaWildcardPtr
6337 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6338 xmlSchemaPtr schema, xmlNodePtr node);
6341 * xmlSchemaPValAttrNodeValue:
6343 * @pctxt: a schema parser context
6344 * @ownerItem: the schema object owner if existent
6345 * @attr: the schema attribute node being validated
6346 * @value: the value
6347 * @type: the built-in type to be validated against
6349 * Validates a value against the given built-in type.
6350 * This one is intended to be used internally for validation
6351 * of schema attribute values during parsing of the schema.
6353 * Returns 0 if the value is valid, a positive error code
6354 * number otherwise and -1 in case of an internal or API error.
6356 static int
6357 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6358 xmlSchemaBasicItemPtr ownerItem,
6359 xmlAttrPtr attr,
6360 const xmlChar *value,
6361 xmlSchemaTypePtr type)
6364 int ret = 0;
6367 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6368 * one is really meant to be used internally, so better not.
6370 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6371 return (-1);
6372 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6373 PERROR_INT("xmlSchemaPValAttrNodeValue",
6374 "the given type is not a built-in type");
6375 return (-1);
6377 switch (type->builtInType) {
6378 case XML_SCHEMAS_NCNAME:
6379 case XML_SCHEMAS_QNAME:
6380 case XML_SCHEMAS_ANYURI:
6381 case XML_SCHEMAS_TOKEN:
6382 case XML_SCHEMAS_LANGUAGE:
6383 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6384 (xmlNodePtr) attr);
6385 break;
6386 default: {
6387 PERROR_INT("xmlSchemaPValAttrNodeValue",
6388 "validation using the given type is not supported while "
6389 "parsing a schema");
6390 return (-1);
6394 * TODO: Should we use the S4S error codes instead?
6396 if (ret < 0) {
6397 PERROR_INT("xmlSchemaPValAttrNodeValue",
6398 "failed to validate a schema attribute value");
6399 return (-1);
6400 } else if (ret > 0) {
6401 if (WXS_IS_LIST(type))
6402 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6403 else
6404 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6405 xmlSchemaPSimpleTypeErr(pctxt,
6406 ret, ownerItem, (xmlNodePtr) attr,
6407 type, NULL, value, NULL, NULL, NULL);
6409 return (ret);
6413 * xmlSchemaPValAttrNode:
6415 * @ctxt: a schema parser context
6416 * @ownerItem: the schema object owner if existent
6417 * @attr: the schema attribute node being validated
6418 * @type: the built-in type to be validated against
6419 * @value: the resulting value if any
6421 * Extracts and validates a value against the given built-in type.
6422 * This one is intended to be used internally for validation
6423 * of schema attribute values during parsing of the schema.
6425 * Returns 0 if the value is valid, a positive error code
6426 * number otherwise and -1 in case of an internal or API error.
6428 static int
6429 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6430 xmlSchemaBasicItemPtr ownerItem,
6431 xmlAttrPtr attr,
6432 xmlSchemaTypePtr type,
6433 const xmlChar **value)
6435 const xmlChar *val;
6437 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6438 return (-1);
6440 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6441 if (value != NULL)
6442 *value = val;
6444 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6445 val, type));
6449 * xmlSchemaPValAttr:
6451 * @ctxt: a schema parser context
6452 * @node: the element node of the attribute
6453 * @ownerItem: the schema object owner if existent
6454 * @ownerElem: the owner element node
6455 * @name: the name of the schema attribute node
6456 * @type: the built-in type to be validated against
6457 * @value: the resulting value if any
6459 * Extracts and validates a value against the given built-in type.
6460 * This one is intended to be used internally for validation
6461 * of schema attribute values during parsing of the schema.
6463 * Returns 0 if the value is valid, a positive error code
6464 * number otherwise and -1 in case of an internal or API error.
6466 static int
6467 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6468 xmlSchemaBasicItemPtr ownerItem,
6469 xmlNodePtr ownerElem,
6470 const char *name,
6471 xmlSchemaTypePtr type,
6472 const xmlChar **value)
6474 xmlAttrPtr attr;
6476 if ((ctxt == NULL) || (type == NULL)) {
6477 if (value != NULL)
6478 *value = NULL;
6479 return (-1);
6481 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6482 if (value != NULL)
6483 *value = NULL;
6484 xmlSchemaPErr(ctxt, ownerElem,
6485 XML_SCHEMAP_INTERNAL,
6486 "Internal error: xmlSchemaPValAttr, the given "
6487 "type '%s' is not a built-in type.\n",
6488 type->name, NULL);
6489 return (-1);
6491 attr = xmlSchemaGetPropNode(ownerElem, name);
6492 if (attr == NULL) {
6493 if (value != NULL)
6494 *value = NULL;
6495 return (0);
6497 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6498 type, value));
6501 static int
6502 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6503 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6504 xmlNodePtr node,
6505 xmlAttrPtr attr,
6506 const xmlChar *namespaceName)
6508 /* TODO: Pointer comparison instead? */
6509 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6510 return (0);
6511 if (xmlStrEqual(xmlSchemaNs, namespaceName))
6512 return (0);
6514 * Check if the referenced namespace was <import>ed.
6516 if (WXS_BUCKET(pctxt)->relations != NULL) {
6517 xmlSchemaSchemaRelationPtr rel;
6519 rel = WXS_BUCKET(pctxt)->relations;
6520 do {
6521 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6522 xmlStrEqual(namespaceName, rel->importNamespace))
6523 return (0);
6524 rel = rel->next;
6525 } while (rel != NULL);
6528 * No matching <import>ed namespace found.
6531 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6533 if (namespaceName == NULL)
6534 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6535 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6536 "References from this schema to components in no "
6537 "namespace are not allowed, since not indicated by an "
6538 "import statement", NULL, NULL);
6539 else
6540 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6541 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6542 "References from this schema to components in the "
6543 "namespace '%s' are not allowed, since not indicated by an "
6544 "import statement", namespaceName, NULL);
6546 return (XML_SCHEMAP_SRC_RESOLVE);
6550 * xmlSchemaParseLocalAttributes:
6551 * @ctxt: a schema validation context
6552 * @schema: the schema being built
6553 * @node: a subtree containing XML Schema information
6554 * @type: the hosting type where the attributes will be anchored
6556 * Parses attribute uses and attribute declarations and
6557 * attribute group references.
6559 static int
6560 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6561 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6562 int parentType, int *hasRefs)
6564 void *item;
6566 while ((IS_SCHEMA((*child), "attribute")) ||
6567 (IS_SCHEMA((*child), "attributeGroup"))) {
6568 if (IS_SCHEMA((*child), "attribute")) {
6569 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6570 *list, parentType);
6571 } else {
6572 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6573 if ((item != NULL) && (hasRefs != NULL))
6574 *hasRefs = 1;
6576 if (item != NULL) {
6577 if (*list == NULL) {
6578 /* TODO: Customize grow factor. */
6579 *list = xmlSchemaItemListCreate();
6580 if (*list == NULL)
6581 return(-1);
6583 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6584 return(-1);
6586 *child = (*child)->next;
6588 return (0);
6592 * xmlSchemaParseAnnotation:
6593 * @ctxt: a schema validation context
6594 * @schema: the schema being built
6595 * @node: a subtree containing XML Schema information
6597 * parse a XML schema Attribute declaration
6598 * *WARNING* this interface is highly subject to change
6600 * Returns -1 in case of error, 0 if the declaration is improper and
6601 * 1 in case of success.
6603 static xmlSchemaAnnotPtr
6604 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6606 xmlSchemaAnnotPtr ret;
6607 xmlNodePtr child = NULL;
6608 xmlAttrPtr attr;
6609 int barked = 0;
6612 * INFO: S4S completed.
6615 * id = ID
6616 * {any attributes with non-schema namespace . . .}>
6617 * Content: (appinfo | documentation)*
6619 if ((ctxt == NULL) || (node == NULL))
6620 return (NULL);
6621 if (needed)
6622 ret = xmlSchemaNewAnnot(ctxt, node);
6623 else
6624 ret = NULL;
6625 attr = node->properties;
6626 while (attr != NULL) {
6627 if (((attr->ns == NULL) &&
6628 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6629 ((attr->ns != NULL) &&
6630 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6632 xmlSchemaPIllegalAttrErr(ctxt,
6633 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6635 attr = attr->next;
6637 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6639 * And now for the children...
6641 child = node->children;
6642 while (child != NULL) {
6643 if (IS_SCHEMA(child, "appinfo")) {
6644 /* TODO: make available the content of "appinfo". */
6646 * source = anyURI
6647 * {any attributes with non-schema namespace . . .}>
6648 * Content: ({any})*
6650 attr = child->properties;
6651 while (attr != NULL) {
6652 if (((attr->ns == NULL) &&
6653 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6654 ((attr->ns != NULL) &&
6655 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6657 xmlSchemaPIllegalAttrErr(ctxt,
6658 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6660 attr = attr->next;
6662 xmlSchemaPValAttr(ctxt, NULL, child, "source",
6663 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6664 child = child->next;
6665 } else if (IS_SCHEMA(child, "documentation")) {
6666 /* TODO: make available the content of "documentation". */
6668 * source = anyURI
6669 * {any attributes with non-schema namespace . . .}>
6670 * Content: ({any})*
6672 attr = child->properties;
6673 while (attr != NULL) {
6674 if (attr->ns == NULL) {
6675 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6676 xmlSchemaPIllegalAttrErr(ctxt,
6677 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6679 } else {
6680 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6681 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6682 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6684 xmlSchemaPIllegalAttrErr(ctxt,
6685 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6688 attr = attr->next;
6691 * Attribute "xml:lang".
6693 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6694 if (attr != NULL)
6695 xmlSchemaPValAttrNode(ctxt, NULL, attr,
6696 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6697 child = child->next;
6698 } else {
6699 if (!barked)
6700 xmlSchemaPContentErr(ctxt,
6701 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6702 NULL, node, child, NULL, "(appinfo | documentation)*");
6703 barked = 1;
6704 child = child->next;
6708 return (ret);
6712 * xmlSchemaParseFacet:
6713 * @ctxt: a schema validation context
6714 * @schema: the schema being built
6715 * @node: a subtree containing XML Schema information
6717 * parse a XML schema Facet declaration
6718 * *WARNING* this interface is highly subject to change
6720 * Returns the new type structure or NULL in case of error
6722 static xmlSchemaFacetPtr
6723 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6724 xmlNodePtr node)
6726 xmlSchemaFacetPtr facet;
6727 xmlNodePtr child = NULL;
6728 const xmlChar *value;
6730 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6731 return (NULL);
6733 facet = xmlSchemaNewFacet();
6734 if (facet == NULL) {
6735 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6736 return (NULL);
6738 facet->node = node;
6739 value = xmlSchemaGetProp(ctxt, node, "value");
6740 if (value == NULL) {
6741 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6742 "Facet %s has no value\n", node->name, NULL);
6743 xmlSchemaFreeFacet(facet);
6744 return (NULL);
6746 if (IS_SCHEMA(node, "minInclusive")) {
6747 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6748 } else if (IS_SCHEMA(node, "minExclusive")) {
6749 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6750 } else if (IS_SCHEMA(node, "maxInclusive")) {
6751 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6752 } else if (IS_SCHEMA(node, "maxExclusive")) {
6753 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6754 } else if (IS_SCHEMA(node, "totalDigits")) {
6755 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6756 } else if (IS_SCHEMA(node, "fractionDigits")) {
6757 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6758 } else if (IS_SCHEMA(node, "pattern")) {
6759 facet->type = XML_SCHEMA_FACET_PATTERN;
6760 } else if (IS_SCHEMA(node, "enumeration")) {
6761 facet->type = XML_SCHEMA_FACET_ENUMERATION;
6762 } else if (IS_SCHEMA(node, "whiteSpace")) {
6763 facet->type = XML_SCHEMA_FACET_WHITESPACE;
6764 } else if (IS_SCHEMA(node, "length")) {
6765 facet->type = XML_SCHEMA_FACET_LENGTH;
6766 } else if (IS_SCHEMA(node, "maxLength")) {
6767 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6768 } else if (IS_SCHEMA(node, "minLength")) {
6769 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6770 } else {
6771 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6772 "Unknown facet type %s\n", node->name, NULL);
6773 xmlSchemaFreeFacet(facet);
6774 return (NULL);
6776 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6777 facet->value = value;
6778 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6779 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6780 const xmlChar *fixed;
6782 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6783 if (fixed != NULL) {
6784 if (xmlStrEqual(fixed, BAD_CAST "true"))
6785 facet->fixed = 1;
6788 child = node->children;
6790 if (IS_SCHEMA(child, "annotation")) {
6791 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6792 child = child->next;
6794 if (child != NULL) {
6795 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6796 "Facet %s has unexpected child content\n",
6797 node->name, NULL);
6799 return (facet);
6803 * xmlSchemaParseWildcardNs:
6804 * @ctxt: a schema parser context
6805 * @wildc: the wildcard, already created
6806 * @node: a subtree containing XML Schema information
6808 * Parses the attribute "processContents" and "namespace"
6809 * of a xsd:anyAttribute and xsd:any.
6810 * *WARNING* this interface is highly subject to change
6812 * Returns 0 if everything goes fine, a positive error code
6813 * if something is not valid and -1 if an internal error occurs.
6815 static int
6816 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6817 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6818 xmlSchemaWildcardPtr wildc,
6819 xmlNodePtr node)
6821 const xmlChar *pc, *ns, *dictnsItem;
6822 int ret = 0;
6823 xmlChar *nsItem;
6824 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6825 xmlAttrPtr attr;
6827 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6828 if ((pc == NULL)
6829 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6830 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6831 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6832 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6833 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6834 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6835 } else {
6836 xmlSchemaPSimpleTypeErr(ctxt,
6837 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6838 NULL, node,
6839 NULL, "(strict | skip | lax)", pc,
6840 NULL, NULL, NULL);
6841 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6842 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6845 * Build the namespace constraints.
6847 attr = xmlSchemaGetPropNode(node, "namespace");
6848 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6849 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6850 wildc->any = 1;
6851 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6852 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6853 if (wildc->negNsSet == NULL) {
6854 return (-1);
6856 wildc->negNsSet->value = ctxt->targetNamespace;
6857 } else {
6858 const xmlChar *end, *cur;
6860 cur = ns;
6861 do {
6862 while (IS_BLANK_CH(*cur))
6863 cur++;
6864 end = cur;
6865 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6866 end++;
6867 if (end == cur)
6868 break;
6869 nsItem = xmlStrndup(cur, end - cur);
6870 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6871 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6872 xmlSchemaPSimpleTypeErr(ctxt,
6873 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6874 NULL, (xmlNodePtr) attr,
6875 NULL,
6876 "((##any | ##other) | List of (xs:anyURI | "
6877 "(##targetNamespace | ##local)))",
6878 nsItem, NULL, NULL, NULL);
6879 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6880 } else {
6881 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6882 dictnsItem = ctxt->targetNamespace;
6883 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6884 dictnsItem = NULL;
6885 } else {
6887 * Validate the item (anyURI).
6889 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6890 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6891 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6894 * Avoid duplicate namespaces.
6896 tmp = wildc->nsSet;
6897 while (tmp != NULL) {
6898 if (dictnsItem == tmp->value)
6899 break;
6900 tmp = tmp->next;
6902 if (tmp == NULL) {
6903 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6904 if (tmp == NULL) {
6905 xmlFree(nsItem);
6906 return (-1);
6908 tmp->value = dictnsItem;
6909 tmp->next = NULL;
6910 if (wildc->nsSet == NULL)
6911 wildc->nsSet = tmp;
6912 else if (lastNs != NULL)
6913 lastNs->next = tmp;
6914 lastNs = tmp;
6918 xmlFree(nsItem);
6919 cur = end;
6920 } while (*cur != 0);
6922 return (ret);
6925 static int
6926 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6927 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6928 xmlNodePtr node,
6929 int minOccurs,
6930 int maxOccurs) {
6932 if ((maxOccurs == 0) && ( minOccurs == 0))
6933 return (0);
6934 if (maxOccurs != UNBOUNDED) {
6936 * TODO: Maybe we should better not create the particle,
6937 * if min/max is invalid, since it could confuse the build of the
6938 * content model.
6941 * 3.9.6 Schema Component Constraint: Particle Correct
6944 if (maxOccurs < 1) {
6946 * 2.2 {max occurs} must be greater than or equal to 1.
6948 xmlSchemaPCustomAttrErr(ctxt,
6949 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6950 NULL, NULL,
6951 xmlSchemaGetPropNode(node, "maxOccurs"),
6952 "The value must be greater than or equal to 1");
6953 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6954 } else if (minOccurs > maxOccurs) {
6956 * 2.1 {min occurs} must not be greater than {max occurs}.
6958 xmlSchemaPCustomAttrErr(ctxt,
6959 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6960 NULL, NULL,
6961 xmlSchemaGetPropNode(node, "minOccurs"),
6962 "The value must not be greater than the value of 'maxOccurs'");
6963 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6966 return (0);
6970 * xmlSchemaParseAny:
6971 * @ctxt: a schema validation context
6972 * @schema: the schema being built
6973 * @node: a subtree containing XML Schema information
6975 * Parsea a XML schema <any> element. A particle and wildcard
6976 * will be created (except if minOccurs==maxOccurs==0, in this case
6977 * nothing will be created).
6978 * *WARNING* this interface is highly subject to change
6980 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6982 static xmlSchemaParticlePtr
6983 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6984 xmlNodePtr node)
6986 xmlSchemaParticlePtr particle;
6987 xmlNodePtr child = NULL;
6988 xmlSchemaWildcardPtr wild;
6989 int min, max;
6990 xmlAttrPtr attr;
6991 xmlSchemaAnnotPtr annot = NULL;
6993 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6994 return (NULL);
6996 * Check for illegal attributes.
6998 attr = node->properties;
6999 while (attr != NULL) {
7000 if (attr->ns == NULL) {
7001 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7002 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
7003 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7004 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7005 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7006 xmlSchemaPIllegalAttrErr(ctxt,
7007 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7009 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7010 xmlSchemaPIllegalAttrErr(ctxt,
7011 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7013 attr = attr->next;
7015 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7017 * minOccurs/maxOccurs.
7019 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7020 "(xs:nonNegativeInteger | unbounded)");
7021 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
7022 "xs:nonNegativeInteger");
7023 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7025 * Create & parse the wildcard.
7027 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
7028 if (wild == NULL)
7029 return (NULL);
7030 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
7032 * And now for the children...
7034 child = node->children;
7035 if (IS_SCHEMA(child, "annotation")) {
7036 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7037 child = child->next;
7039 if (child != NULL) {
7040 xmlSchemaPContentErr(ctxt,
7041 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7042 NULL, node, child,
7043 NULL, "(annotation?)");
7046 * No component if minOccurs==maxOccurs==0.
7048 if ((min == 0) && (max == 0)) {
7049 /* Don't free the wildcard, since it's already on the list. */
7050 return (NULL);
7053 * Create the particle.
7055 particle = xmlSchemaAddParticle(ctxt, node, min, max);
7056 if (particle == NULL)
7057 return (NULL);
7058 particle->annot = annot;
7059 particle->children = (xmlSchemaTreeItemPtr) wild;
7061 return (particle);
7065 * xmlSchemaParseNotation:
7066 * @ctxt: a schema validation context
7067 * @schema: the schema being built
7068 * @node: a subtree containing XML Schema information
7070 * parse a XML schema Notation declaration
7072 * Returns the new structure or NULL in case of error
7074 static xmlSchemaNotationPtr
7075 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7076 xmlNodePtr node)
7078 const xmlChar *name;
7079 xmlSchemaNotationPtr ret;
7080 xmlNodePtr child = NULL;
7082 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7083 return (NULL);
7084 name = xmlSchemaGetProp(ctxt, node, "name");
7085 if (name == NULL) {
7086 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
7087 "Notation has no name\n", NULL, NULL);
7088 return (NULL);
7090 ret = xmlSchemaAddNotation(ctxt, schema, name,
7091 ctxt->targetNamespace, node);
7092 if (ret == NULL)
7093 return (NULL);
7094 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7096 child = node->children;
7097 if (IS_SCHEMA(child, "annotation")) {
7098 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7099 child = child->next;
7101 if (child != NULL) {
7102 xmlSchemaPContentErr(ctxt,
7103 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7104 NULL, node, child,
7105 NULL, "(annotation?)");
7108 return (ret);
7112 * xmlSchemaParseAnyAttribute:
7113 * @ctxt: a schema validation context
7114 * @schema: the schema being built
7115 * @node: a subtree containing XML Schema information
7117 * parse a XML schema AnyAttribute declaration
7118 * *WARNING* this interface is highly subject to change
7120 * Returns a wildcard or NULL.
7122 static xmlSchemaWildcardPtr
7123 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7124 xmlSchemaPtr schema, xmlNodePtr node)
7126 xmlSchemaWildcardPtr ret;
7127 xmlNodePtr child = NULL;
7128 xmlAttrPtr attr;
7130 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7131 return (NULL);
7133 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7134 node);
7135 if (ret == NULL) {
7136 return (NULL);
7139 * Check for illegal attributes.
7141 attr = node->properties;
7142 while (attr != NULL) {
7143 if (attr->ns == NULL) {
7144 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7145 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7146 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7147 xmlSchemaPIllegalAttrErr(ctxt,
7148 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7150 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7151 xmlSchemaPIllegalAttrErr(ctxt,
7152 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7154 attr = attr->next;
7156 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7158 * Parse the namespace list.
7160 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7161 return (NULL);
7163 * And now for the children...
7165 child = node->children;
7166 if (IS_SCHEMA(child, "annotation")) {
7167 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7168 child = child->next;
7170 if (child != NULL) {
7171 xmlSchemaPContentErr(ctxt,
7172 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7173 NULL, node, child,
7174 NULL, "(annotation?)");
7177 return (ret);
7182 * xmlSchemaParseAttribute:
7183 * @ctxt: a schema validation context
7184 * @schema: the schema being built
7185 * @node: a subtree containing XML Schema information
7187 * parse a XML schema Attribute declaration
7188 * *WARNING* this interface is highly subject to change
7190 * Returns the attribute declaration.
7192 static xmlSchemaBasicItemPtr
7193 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7194 xmlSchemaPtr schema,
7195 xmlNodePtr node,
7196 xmlSchemaItemListPtr uses,
7197 int parentType)
7199 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7200 xmlSchemaAttributeUsePtr use = NULL;
7201 xmlNodePtr child = NULL;
7202 xmlAttrPtr attr;
7203 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7204 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7205 int nberrors, hasForm = 0, defValueType = 0;
7207 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7208 #define WXS_ATTR_DEF_VAL_FIXED 2
7211 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7214 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7215 return (NULL);
7216 attr = xmlSchemaGetPropNode(node, "ref");
7217 if (attr != NULL) {
7218 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7219 NULL, attr, &tmpNs, &tmpName) != 0) {
7220 return (NULL);
7222 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7223 return(NULL);
7224 isRef = 1;
7226 nberrors = pctxt->nberrors;
7228 * Check for illegal attributes.
7230 attr = node->properties;
7231 while (attr != NULL) {
7232 if (attr->ns == NULL) {
7233 if (isRef) {
7234 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7235 xmlSchemaPValAttrNodeID(pctxt, attr);
7236 goto attr_next;
7237 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7238 goto attr_next;
7240 } else {
7241 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7242 goto attr_next;
7243 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7244 xmlSchemaPValAttrNodeID(pctxt, attr);
7245 goto attr_next;
7246 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7247 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7248 attr, &tmpNs, &tmpName);
7249 goto attr_next;
7250 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7252 * Evaluate the target namespace
7254 hasForm = 1;
7255 attrValue = xmlSchemaGetNodeContent(pctxt,
7256 (xmlNodePtr) attr);
7257 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7258 ns = pctxt->targetNamespace;
7259 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7261 xmlSchemaPSimpleTypeErr(pctxt,
7262 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7263 NULL, (xmlNodePtr) attr,
7264 NULL, "(qualified | unqualified)",
7265 attrValue, NULL, NULL, NULL);
7267 goto attr_next;
7270 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7272 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7273 /* TODO: Maybe we need to normalize the value beforehand. */
7274 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7275 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7276 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7277 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7278 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7279 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7280 else {
7281 xmlSchemaPSimpleTypeErr(pctxt,
7282 XML_SCHEMAP_INVALID_ATTR_USE,
7283 NULL, (xmlNodePtr) attr,
7284 NULL, "(optional | prohibited | required)",
7285 attrValue, NULL, NULL, NULL);
7287 goto attr_next;
7288 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7290 * 3.2.3 : 1
7291 * default and fixed must not both be present.
7293 if (defValue) {
7294 xmlSchemaPMutualExclAttrErr(pctxt,
7295 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7296 NULL, attr, "default", "fixed");
7297 } else {
7298 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7299 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7301 goto attr_next;
7302 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
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_FIXED;
7315 goto attr_next;
7317 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7318 goto attr_next;
7320 xmlSchemaPIllegalAttrErr(pctxt,
7321 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7323 attr_next:
7324 attr = attr->next;
7327 * 3.2.3 : 2
7328 * If default and use are both present, use must have
7329 * the actual value optional.
7331 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7332 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7333 xmlSchemaPSimpleTypeErr(pctxt,
7334 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7335 NULL, node, NULL,
7336 "(optional | prohibited | required)", NULL,
7337 "The value of the attribute 'use' must be 'optional' "
7338 "if the attribute 'default' is present",
7339 NULL, NULL);
7342 * We want correct attributes.
7344 if (nberrors != pctxt->nberrors)
7345 return(NULL);
7346 if (! isRef) {
7347 xmlSchemaAttributePtr attrDecl;
7349 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7350 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7351 ns = pctxt->targetNamespace;
7353 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7354 * TODO: Move this to the component layer.
7356 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7357 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7358 XML_SCHEMAP_NO_XSI,
7359 node, NULL,
7360 "The target namespace must not match '%s'",
7361 xmlSchemaInstanceNs, NULL);
7363 attr = xmlSchemaGetPropNode(node, "name");
7364 if (attr == NULL) {
7365 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7366 NULL, node, "name", NULL);
7367 return (NULL);
7369 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7370 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7371 return (NULL);
7374 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7375 * TODO: Move this to the component layer.
7377 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7378 xmlSchemaPSimpleTypeErr(pctxt,
7379 XML_SCHEMAP_NO_XMLNS,
7380 NULL, (xmlNodePtr) attr,
7381 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7382 "The value of the attribute must not match 'xmlns'",
7383 NULL, NULL);
7384 return (NULL);
7386 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7387 goto check_children;
7389 * Create the attribute use component.
7391 use = xmlSchemaAddAttributeUse(pctxt, node);
7392 if (use == NULL)
7393 return(NULL);
7394 use->occurs = occurs;
7396 * Create the attribute declaration.
7398 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7399 if (attrDecl == NULL)
7400 return (NULL);
7401 if (tmpName != NULL) {
7402 attrDecl->typeName = tmpName;
7403 attrDecl->typeNs = tmpNs;
7405 use->attrDecl = attrDecl;
7407 * Value constraint.
7409 if (defValue != NULL) {
7410 attrDecl->defValue = defValue;
7411 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7412 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7414 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7415 xmlSchemaQNameRefPtr ref;
7418 * Create the attribute use component.
7420 use = xmlSchemaAddAttributeUse(pctxt, node);
7421 if (use == NULL)
7422 return(NULL);
7424 * We need to resolve the reference at later stage.
7426 WXS_ADD_PENDING(pctxt, use);
7427 use->occurs = occurs;
7429 * Create a QName reference to the attribute declaration.
7431 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7432 tmpName, tmpNs);
7433 if (ref == NULL)
7434 return(NULL);
7436 * Assign the reference. This will be substituted for the
7437 * referenced attribute declaration when the QName is resolved.
7439 use->attrDecl = WXS_ATTR_CAST ref;
7441 * Value constraint.
7443 if (defValue != NULL)
7444 use->defValue = defValue;
7445 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7446 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7449 check_children:
7451 * And now for the children...
7453 child = node->children;
7454 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7455 xmlSchemaAttributeUseProhibPtr prohib;
7457 if (IS_SCHEMA(child, "annotation")) {
7458 xmlSchemaParseAnnotation(pctxt, child, 0);
7459 child = child->next;
7461 if (child != NULL) {
7462 xmlSchemaPContentErr(pctxt,
7463 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464 NULL, node, child, NULL,
7465 "(annotation?)");
7468 * Check for pointlessness of attribute prohibitions.
7470 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7471 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7472 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7473 node, NULL,
7474 "Skipping attribute use prohibition, since it is "
7475 "pointless inside an <attributeGroup>",
7476 NULL, NULL, NULL);
7477 return(NULL);
7478 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7479 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7480 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7481 node, NULL,
7482 "Skipping attribute use prohibition, since it is "
7483 "pointless when extending a type",
7484 NULL, NULL, NULL);
7485 return(NULL);
7487 if (! isRef) {
7488 tmpName = name;
7489 tmpNs = ns;
7492 * Check for duplicate attribute prohibitions.
7494 if (uses) {
7495 int i;
7497 for (i = 0; i < uses->nbItems; i++) {
7498 use = uses->items[i];
7499 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7500 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7501 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7503 xmlChar *str = NULL;
7505 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7506 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7507 node, NULL,
7508 "Skipping duplicate attribute use prohibition '%s'",
7509 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7510 NULL, NULL);
7511 FREE_AND_NULL(str)
7512 return(NULL);
7517 * Create the attribute prohibition helper component.
7519 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7520 if (prohib == NULL)
7521 return(NULL);
7522 prohib->node = node;
7523 prohib->name = tmpName;
7524 prohib->targetNamespace = tmpNs;
7525 if (isRef) {
7527 * We need at least to resolve to the attribute declaration.
7529 WXS_ADD_PENDING(pctxt, prohib);
7531 return(WXS_BASIC_CAST prohib);
7532 } else {
7533 if (IS_SCHEMA(child, "annotation")) {
7535 * TODO: Should this go into the attr decl?
7537 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7538 child = child->next;
7540 if (isRef) {
7541 if (child != NULL) {
7542 if (IS_SCHEMA(child, "simpleType"))
7544 * 3.2.3 : 3.2
7545 * If ref is present, then all of <simpleType>,
7546 * form and type must be absent.
7548 xmlSchemaPContentErr(pctxt,
7549 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7550 NULL, node, child, NULL,
7551 "(annotation?)");
7552 else
7553 xmlSchemaPContentErr(pctxt,
7554 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7555 NULL, node, child, NULL,
7556 "(annotation?)");
7558 } else {
7559 if (IS_SCHEMA(child, "simpleType")) {
7560 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7562 * 3.2.3 : 4
7563 * type and <simpleType> must not both be present.
7565 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7566 NULL, node, child,
7567 "The attribute 'type' and the <simpleType> child "
7568 "are mutually exclusive", NULL);
7569 } else
7570 WXS_ATTRUSE_TYPEDEF(use) =
7571 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7572 child = child->next;
7574 if (child != NULL)
7575 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7576 NULL, node, child, NULL,
7577 "(annotation?, simpleType?)");
7580 return (WXS_BASIC_CAST use);
7584 static xmlSchemaAttributePtr
7585 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7586 xmlSchemaPtr schema,
7587 xmlNodePtr node)
7589 const xmlChar *attrValue;
7590 xmlSchemaAttributePtr ret;
7591 xmlNodePtr child = NULL;
7592 xmlAttrPtr attr;
7595 * Note that the w3c spec assumes the schema to be validated with schema
7596 * for schemas beforehand.
7598 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7600 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7601 return (NULL);
7603 * 3.2.3 : 3.1
7604 * One of ref or name must be present, but not both
7606 attr = xmlSchemaGetPropNode(node, "name");
7607 if (attr == NULL) {
7608 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7609 NULL, node, "name", NULL);
7610 return (NULL);
7612 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7613 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7614 return (NULL);
7617 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7618 * TODO: Move this to the component layer.
7620 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7621 xmlSchemaPSimpleTypeErr(pctxt,
7622 XML_SCHEMAP_NO_XMLNS,
7623 NULL, (xmlNodePtr) attr,
7624 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7625 "The value of the attribute must not match 'xmlns'",
7626 NULL, NULL);
7627 return (NULL);
7630 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7631 * TODO: Move this to the component layer.
7632 * Or better leave it here and add it to the component layer
7633 * if we have a schema construction API.
7635 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7636 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7637 XML_SCHEMAP_NO_XSI, node, NULL,
7638 "The target namespace must not match '%s'",
7639 xmlSchemaInstanceNs, NULL);
7642 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7643 pctxt->targetNamespace, node, 1);
7644 if (ret == NULL)
7645 return (NULL);
7646 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7649 * Check for illegal attributes.
7651 attr = node->properties;
7652 while (attr != NULL) {
7653 if (attr->ns == NULL) {
7654 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7655 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7656 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7657 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7658 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7660 xmlSchemaPIllegalAttrErr(pctxt,
7661 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7663 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7664 xmlSchemaPIllegalAttrErr(pctxt,
7665 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7667 attr = attr->next;
7669 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7670 node, "type", &ret->typeNs, &ret->typeName);
7672 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7674 * Attribute "fixed".
7676 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7677 if (ret->defValue != NULL)
7678 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7680 * Attribute "default".
7682 attr = xmlSchemaGetPropNode(node, "default");
7683 if (attr != NULL) {
7685 * 3.2.3 : 1
7686 * default and fixed must not both be present.
7688 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7689 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7690 WXS_BASIC_CAST ret, attr, "default", "fixed");
7691 } else
7692 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7695 * And now for the children...
7697 child = node->children;
7698 if (IS_SCHEMA(child, "annotation")) {
7699 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7700 child = child->next;
7702 if (IS_SCHEMA(child, "simpleType")) {
7703 if (ret->typeName != NULL) {
7705 * 3.2.3 : 4
7706 * type and <simpleType> must not both be present.
7708 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7709 NULL, node, child,
7710 "The attribute 'type' and the <simpleType> child "
7711 "are mutually exclusive", NULL);
7712 } else
7713 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7714 child = child->next;
7716 if (child != NULL)
7717 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7718 NULL, node, child, NULL,
7719 "(annotation?, simpleType?)");
7721 return (ret);
7725 * xmlSchemaParseAttributeGroupRef:
7726 * @ctxt: a schema validation context
7727 * @schema: the schema being built
7728 * @node: a subtree containing XML Schema information
7730 * Parse an attribute group definition reference.
7731 * Note that a reference to an attribute group does not
7732 * correspond to any component at all.
7733 * *WARNING* this interface is highly subject to change
7735 * Returns the attribute group or NULL in case of error.
7737 static xmlSchemaQNameRefPtr
7738 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7739 xmlSchemaPtr schema,
7740 xmlNodePtr node)
7742 xmlSchemaQNameRefPtr ret;
7743 xmlNodePtr child = NULL;
7744 xmlAttrPtr attr;
7745 const xmlChar *refNs = NULL, *ref = NULL;
7747 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7748 return (NULL);
7750 attr = xmlSchemaGetPropNode(node, "ref");
7751 if (attr == NULL) {
7752 xmlSchemaPMissingAttrErr(pctxt,
7753 XML_SCHEMAP_S4S_ATTR_MISSING,
7754 NULL, node, "ref", NULL);
7755 return (NULL);
7757 xmlSchemaPValAttrNodeQName(pctxt, schema,
7758 NULL, attr, &refNs, &ref);
7759 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7760 return(NULL);
7763 * Check for illegal attributes.
7765 attr = node->properties;
7766 while (attr != NULL) {
7767 if (attr->ns == NULL) {
7768 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7769 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7771 xmlSchemaPIllegalAttrErr(pctxt,
7772 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7774 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7775 xmlSchemaPIllegalAttrErr(pctxt,
7776 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7778 attr = attr->next;
7780 /* Attribute ID */
7781 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7784 * And now for the children...
7786 child = node->children;
7787 if (IS_SCHEMA(child, "annotation")) {
7789 * TODO: We do not have a place to store the annotation, do we?
7791 xmlSchemaParseAnnotation(pctxt, child, 0);
7792 child = child->next;
7794 if (child != NULL) {
7795 xmlSchemaPContentErr(pctxt,
7796 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7797 NULL, node, child, NULL,
7798 "(annotation?)");
7802 * Handle attribute group redefinitions.
7804 if (pctxt->isRedefine && pctxt->redef &&
7805 (pctxt->redef->item->type ==
7806 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7807 (ref == pctxt->redef->refName) &&
7808 (refNs == pctxt->redef->refTargetNs))
7811 * SPEC src-redefine:
7812 * (7.1) "If it has an <attributeGroup> among its contents
7813 * the `actual value` of whose ref [attribute] is the same
7814 * as the `actual value` of its own name attribute plus
7815 * target namespace, then it must have exactly one such group."
7817 if (pctxt->redefCounter != 0) {
7818 xmlChar *str = NULL;
7820 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7821 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7822 "The redefining attribute group definition "
7823 "'%s' must not contain more than one "
7824 "reference to the redefined definition",
7825 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7826 FREE_AND_NULL(str);
7827 return(NULL);
7829 pctxt->redefCounter++;
7831 * URGENT TODO: How to ensure that the reference will not be
7832 * handled by the normal component resolution mechanism?
7834 ret = xmlSchemaNewQNameRef(pctxt,
7835 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7836 if (ret == NULL)
7837 return(NULL);
7838 ret->node = node;
7839 pctxt->redef->reference = WXS_BASIC_CAST ret;
7840 } else {
7842 * Create a QName-reference helper component. We will substitute this
7843 * component for the attribute uses of the referenced attribute group
7844 * definition.
7846 ret = xmlSchemaNewQNameRef(pctxt,
7847 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7848 if (ret == NULL)
7849 return(NULL);
7850 ret->node = node;
7851 /* Add to pending items, to be able to resolve the reference. */
7852 WXS_ADD_PENDING(pctxt, ret);
7854 return (ret);
7858 * xmlSchemaParseAttributeGroupDefinition:
7859 * @pctxt: a schema validation context
7860 * @schema: the schema being built
7861 * @node: a subtree containing XML Schema information
7863 * parse a XML schema Attribute Group declaration
7864 * *WARNING* this interface is highly subject to change
7866 * Returns the attribute group definition or NULL in case of error.
7868 static xmlSchemaAttributeGroupPtr
7869 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7870 xmlSchemaPtr schema,
7871 xmlNodePtr node)
7873 const xmlChar *name;
7874 xmlSchemaAttributeGroupPtr ret;
7875 xmlNodePtr child = NULL;
7876 xmlAttrPtr attr;
7877 int hasRefs = 0;
7879 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7880 return (NULL);
7882 attr = xmlSchemaGetPropNode(node, "name");
7883 if (attr == NULL) {
7884 xmlSchemaPMissingAttrErr(pctxt,
7885 XML_SCHEMAP_S4S_ATTR_MISSING,
7886 NULL, node, "name", NULL);
7887 return (NULL);
7890 * The name is crucial, exit if invalid.
7892 if (xmlSchemaPValAttrNode(pctxt,
7893 NULL, attr,
7894 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7895 return (NULL);
7897 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7898 name, pctxt->targetNamespace, node);
7899 if (ret == NULL)
7900 return (NULL);
7902 * Check for illegal attributes.
7904 attr = node->properties;
7905 while (attr != NULL) {
7906 if (attr->ns == NULL) {
7907 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7908 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7910 xmlSchemaPIllegalAttrErr(pctxt,
7911 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7913 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7914 xmlSchemaPIllegalAttrErr(pctxt,
7915 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7917 attr = attr->next;
7919 /* Attribute ID */
7920 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7922 * And now for the children...
7924 child = node->children;
7925 if (IS_SCHEMA(child, "annotation")) {
7926 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7927 child = child->next;
7930 * Parse contained attribute decls/refs.
7932 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7933 (xmlSchemaItemListPtr *) &(ret->attrUses),
7934 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7935 return(NULL);
7936 if (hasRefs)
7937 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7939 * Parse the attribute wildcard.
7941 if (IS_SCHEMA(child, "anyAttribute")) {
7942 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7943 schema, child);
7944 child = child->next;
7946 if (child != NULL) {
7947 xmlSchemaPContentErr(pctxt,
7948 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7949 NULL, node, child, NULL,
7950 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7952 return (ret);
7956 * xmlSchemaPValAttrFormDefault:
7957 * @value: the value
7958 * @flags: the flags to be modified
7959 * @flagQualified: the specific flag for "qualified"
7961 * Returns 0 if the value is valid, 1 otherwise.
7963 static int
7964 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7965 int *flags,
7966 int flagQualified)
7968 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7969 if ((*flags & flagQualified) == 0)
7970 *flags |= flagQualified;
7971 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7972 return (1);
7974 return (0);
7978 * xmlSchemaPValAttrBlockFinal:
7979 * @value: the value
7980 * @flags: the flags to be modified
7981 * @flagAll: the specific flag for "#all"
7982 * @flagExtension: the specific flag for "extension"
7983 * @flagRestriction: the specific flag for "restriction"
7984 * @flagSubstitution: the specific flag for "substitution"
7985 * @flagList: the specific flag for "list"
7986 * @flagUnion: the specific flag for "union"
7988 * Validates the value of the attribute "final" and "block". The value
7989 * is converted into the specified flag values and returned in @flags.
7991 * Returns 0 if the value is valid, 1 otherwise.
7994 static int
7995 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7996 int *flags,
7997 int flagAll,
7998 int flagExtension,
7999 int flagRestriction,
8000 int flagSubstitution,
8001 int flagList,
8002 int flagUnion)
8004 int ret = 0;
8007 * TODO: This does not check for duplicate entries.
8009 if ((flags == NULL) || (value == NULL))
8010 return (-1);
8011 if (value[0] == 0)
8012 return (0);
8013 if (xmlStrEqual(value, BAD_CAST "#all")) {
8014 if (flagAll != -1)
8015 *flags |= flagAll;
8016 else {
8017 if (flagExtension != -1)
8018 *flags |= flagExtension;
8019 if (flagRestriction != -1)
8020 *flags |= flagRestriction;
8021 if (flagSubstitution != -1)
8022 *flags |= flagSubstitution;
8023 if (flagList != -1)
8024 *flags |= flagList;
8025 if (flagUnion != -1)
8026 *flags |= flagUnion;
8028 } else {
8029 const xmlChar *end, *cur = value;
8030 xmlChar *item;
8032 do {
8033 while (IS_BLANK_CH(*cur))
8034 cur++;
8035 end = cur;
8036 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8037 end++;
8038 if (end == cur)
8039 break;
8040 item = xmlStrndup(cur, end - cur);
8041 if (xmlStrEqual(item, BAD_CAST "extension")) {
8042 if (flagExtension != -1) {
8043 if ((*flags & flagExtension) == 0)
8044 *flags |= flagExtension;
8045 } else
8046 ret = 1;
8047 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
8048 if (flagRestriction != -1) {
8049 if ((*flags & flagRestriction) == 0)
8050 *flags |= flagRestriction;
8051 } else
8052 ret = 1;
8053 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
8054 if (flagSubstitution != -1) {
8055 if ((*flags & flagSubstitution) == 0)
8056 *flags |= flagSubstitution;
8057 } else
8058 ret = 1;
8059 } else if (xmlStrEqual(item, BAD_CAST "list")) {
8060 if (flagList != -1) {
8061 if ((*flags & flagList) == 0)
8062 *flags |= flagList;
8063 } else
8064 ret = 1;
8065 } else if (xmlStrEqual(item, BAD_CAST "union")) {
8066 if (flagUnion != -1) {
8067 if ((*flags & flagUnion) == 0)
8068 *flags |= flagUnion;
8069 } else
8070 ret = 1;
8071 } else
8072 ret = 1;
8073 if (item != NULL)
8074 xmlFree(item);
8075 cur = end;
8076 } while ((ret == 0) && (*cur != 0));
8079 return (ret);
8082 static int
8083 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
8084 xmlSchemaIDCPtr idc,
8085 xmlSchemaIDCSelectPtr selector,
8086 xmlAttrPtr attr,
8087 int isField)
8089 xmlNodePtr node;
8092 * c-selector-xpath:
8093 * Schema Component Constraint: Selector Value OK
8095 * TODO: 1 The {selector} must be a valid XPath expression, as defined
8096 * in [XPath].
8098 if (selector == NULL) {
8099 xmlSchemaPErr(ctxt, idc->node,
8100 XML_SCHEMAP_INTERNAL,
8101 "Internal error: xmlSchemaCheckCSelectorXPath, "
8102 "the selector is not specified.\n", NULL, NULL);
8103 return (-1);
8105 if (attr == NULL)
8106 node = idc->node;
8107 else
8108 node = (xmlNodePtr) attr;
8109 if (selector->xpath == NULL) {
8110 xmlSchemaPCustomErr(ctxt,
8111 /* TODO: Adjust error code. */
8112 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8113 NULL, node,
8114 "The XPath expression of the selector is not valid", NULL);
8115 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8116 } else {
8117 const xmlChar **nsArray = NULL;
8118 xmlNsPtr *nsList = NULL;
8120 * Compile the XPath expression.
8123 * TODO: We need the array of in-scope namespaces for compilation.
8124 * TODO: Call xmlPatterncompile with different options for selector/
8125 * field.
8127 if (attr == NULL)
8128 nsList = NULL;
8129 else
8130 nsList = xmlGetNsList(attr->doc, attr->parent);
8132 * Build an array of prefixes and namespaces.
8134 if (nsList != NULL) {
8135 int i, count = 0;
8137 for (i = 0; nsList[i] != NULL; i++)
8138 count++;
8140 nsArray = (const xmlChar **) xmlMalloc(
8141 (count * 2 + 1) * sizeof(const xmlChar *));
8142 if (nsArray == NULL) {
8143 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8144 NULL);
8145 xmlFree(nsList);
8146 return (-1);
8148 for (i = 0; i < count; i++) {
8149 nsArray[2 * i] = nsList[i]->href;
8150 nsArray[2 * i + 1] = nsList[i]->prefix;
8152 nsArray[count * 2] = NULL;
8153 xmlFree(nsList);
8156 * TODO: Differentiate between "selector" and "field".
8158 if (isField)
8159 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8160 NULL, XML_PATTERN_XSFIELD, nsArray);
8161 else
8162 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8163 NULL, XML_PATTERN_XSSEL, nsArray);
8164 if (nsArray != NULL)
8165 xmlFree((xmlChar **) nsArray);
8167 if (selector->xpathComp == NULL) {
8168 xmlSchemaPCustomErr(ctxt,
8169 /* TODO: Adjust error code? */
8170 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8171 NULL, node,
8172 "The XPath expression '%s' could not be "
8173 "compiled", selector->xpath);
8174 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8177 return (0);
8180 #define ADD_ANNOTATION(annot) \
8181 xmlSchemaAnnotPtr cur = item->annot; \
8182 if (item->annot == NULL) { \
8183 item->annot = annot; \
8184 return (annot); \
8186 cur = item->annot; \
8187 if (cur->next != NULL) { \
8188 cur = cur->next; \
8190 cur->next = annot;
8193 * xmlSchemaAssignAnnotation:
8194 * @item: the schema component
8195 * @annot: the annotation
8197 * Adds the annotation to the given schema component.
8199 * Returns the given annotation.
8201 static xmlSchemaAnnotPtr
8202 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8203 xmlSchemaAnnotPtr annot)
8205 if ((annItem == NULL) || (annot == NULL))
8206 return (NULL);
8207 switch (annItem->type) {
8208 case XML_SCHEMA_TYPE_ELEMENT: {
8209 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8210 ADD_ANNOTATION(annot)
8212 break;
8213 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8214 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8215 ADD_ANNOTATION(annot)
8217 break;
8218 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8219 case XML_SCHEMA_TYPE_ANY: {
8220 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8221 ADD_ANNOTATION(annot)
8223 break;
8224 case XML_SCHEMA_TYPE_PARTICLE:
8225 case XML_SCHEMA_TYPE_IDC_KEY:
8226 case XML_SCHEMA_TYPE_IDC_KEYREF:
8227 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8228 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8229 ADD_ANNOTATION(annot)
8231 break;
8232 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8233 xmlSchemaAttributeGroupPtr item =
8234 (xmlSchemaAttributeGroupPtr) annItem;
8235 ADD_ANNOTATION(annot)
8237 break;
8238 case XML_SCHEMA_TYPE_NOTATION: {
8239 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8240 ADD_ANNOTATION(annot)
8242 break;
8243 case XML_SCHEMA_FACET_MININCLUSIVE:
8244 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8245 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8246 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8247 case XML_SCHEMA_FACET_TOTALDIGITS:
8248 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8249 case XML_SCHEMA_FACET_PATTERN:
8250 case XML_SCHEMA_FACET_ENUMERATION:
8251 case XML_SCHEMA_FACET_WHITESPACE:
8252 case XML_SCHEMA_FACET_LENGTH:
8253 case XML_SCHEMA_FACET_MAXLENGTH:
8254 case XML_SCHEMA_FACET_MINLENGTH: {
8255 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8256 ADD_ANNOTATION(annot)
8258 break;
8259 case XML_SCHEMA_TYPE_SIMPLE:
8260 case XML_SCHEMA_TYPE_COMPLEX: {
8261 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8262 ADD_ANNOTATION(annot)
8264 break;
8265 case XML_SCHEMA_TYPE_GROUP: {
8266 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8267 ADD_ANNOTATION(annot)
8269 break;
8270 case XML_SCHEMA_TYPE_SEQUENCE:
8271 case XML_SCHEMA_TYPE_CHOICE:
8272 case XML_SCHEMA_TYPE_ALL: {
8273 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8274 ADD_ANNOTATION(annot)
8276 break;
8277 default:
8278 xmlSchemaPCustomErr(NULL,
8279 XML_SCHEMAP_INTERNAL,
8280 NULL, NULL,
8281 "Internal error: xmlSchemaAddAnnotation, "
8282 "The item is not a annotated schema component", NULL);
8283 break;
8285 return (annot);
8289 * xmlSchemaParseIDCSelectorAndField:
8290 * @ctxt: a schema validation context
8291 * @schema: the schema being built
8292 * @node: a subtree containing XML Schema information
8294 * Parses a XML Schema identity-constraint definition's
8295 * <selector> and <field> elements.
8297 * Returns the parsed identity-constraint definition.
8299 static xmlSchemaIDCSelectPtr
8300 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8301 xmlSchemaIDCPtr idc,
8302 xmlNodePtr node,
8303 int isField)
8305 xmlSchemaIDCSelectPtr item;
8306 xmlNodePtr child = NULL;
8307 xmlAttrPtr attr;
8310 * Check for illegal attributes.
8312 attr = node->properties;
8313 while (attr != NULL) {
8314 if (attr->ns == NULL) {
8315 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8316 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8317 xmlSchemaPIllegalAttrErr(ctxt,
8318 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8320 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8321 xmlSchemaPIllegalAttrErr(ctxt,
8322 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8324 attr = attr->next;
8327 * Create the item.
8329 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8330 if (item == NULL) {
8331 xmlSchemaPErrMemory(ctxt,
8332 "allocating a 'selector' of an identity-constraint definition",
8333 NULL);
8334 return (NULL);
8336 memset(item, 0, sizeof(xmlSchemaIDCSelect));
8338 * Attribute "xpath" (mandatory).
8340 attr = xmlSchemaGetPropNode(node, "xpath");
8341 if (attr == NULL) {
8342 xmlSchemaPMissingAttrErr(ctxt,
8343 XML_SCHEMAP_S4S_ATTR_MISSING,
8344 NULL, node,
8345 "name", NULL);
8346 } else {
8347 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8349 * URGENT TODO: "field"s have an other syntax than "selector"s.
8352 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8353 isField) == -1) {
8354 xmlSchemaPErr(ctxt,
8355 (xmlNodePtr) attr,
8356 XML_SCHEMAP_INTERNAL,
8357 "Internal error: xmlSchemaParseIDCSelectorAndField, "
8358 "validating the XPath expression of a IDC selector.\n",
8359 NULL, NULL);
8363 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8365 * And now for the children...
8367 child = node->children;
8368 if (IS_SCHEMA(child, "annotation")) {
8370 * Add the annotation to the parent IDC.
8372 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8373 xmlSchemaParseAnnotation(ctxt, child, 1));
8374 child = child->next;
8376 if (child != NULL) {
8377 xmlSchemaPContentErr(ctxt,
8378 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8379 NULL, node, child,
8380 NULL, "(annotation?)");
8383 return (item);
8387 * xmlSchemaParseIDC:
8388 * @ctxt: a schema validation context
8389 * @schema: the schema being built
8390 * @node: a subtree containing XML Schema information
8392 * Parses a XML Schema identity-constraint definition.
8394 * Returns the parsed identity-constraint definition.
8396 static xmlSchemaIDCPtr
8397 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8398 xmlSchemaPtr schema,
8399 xmlNodePtr node,
8400 xmlSchemaTypeType idcCategory,
8401 const xmlChar *targetNamespace)
8403 xmlSchemaIDCPtr item = NULL;
8404 xmlNodePtr child = NULL;
8405 xmlAttrPtr attr;
8406 const xmlChar *name = NULL;
8407 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8410 * Check for illegal attributes.
8412 attr = node->properties;
8413 while (attr != NULL) {
8414 if (attr->ns == NULL) {
8415 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8416 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8417 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8418 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8419 xmlSchemaPIllegalAttrErr(ctxt,
8420 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8422 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8423 xmlSchemaPIllegalAttrErr(ctxt,
8424 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8426 attr = attr->next;
8429 * Attribute "name" (mandatory).
8431 attr = xmlSchemaGetPropNode(node, "name");
8432 if (attr == NULL) {
8433 xmlSchemaPMissingAttrErr(ctxt,
8434 XML_SCHEMAP_S4S_ATTR_MISSING,
8435 NULL, node,
8436 "name", NULL);
8437 return (NULL);
8438 } else if (xmlSchemaPValAttrNode(ctxt,
8439 NULL, attr,
8440 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8441 return (NULL);
8443 /* Create the component. */
8444 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8445 idcCategory, node);
8446 if (item == NULL)
8447 return(NULL);
8449 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8450 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8452 * Attribute "refer" (mandatory).
8454 attr = xmlSchemaGetPropNode(node, "refer");
8455 if (attr == NULL) {
8456 xmlSchemaPMissingAttrErr(ctxt,
8457 XML_SCHEMAP_S4S_ATTR_MISSING,
8458 NULL, node,
8459 "refer", NULL);
8460 } else {
8462 * Create a reference item.
8464 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8465 NULL, NULL);
8466 if (item->ref == NULL)
8467 return (NULL);
8468 xmlSchemaPValAttrNodeQName(ctxt, schema,
8469 NULL, attr,
8470 &(item->ref->targetNamespace),
8471 &(item->ref->name));
8472 xmlSchemaCheckReference(ctxt, schema, node, attr,
8473 item->ref->targetNamespace);
8477 * And now for the children...
8479 child = node->children;
8480 if (IS_SCHEMA(child, "annotation")) {
8481 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8482 child = child->next;
8484 if (child == NULL) {
8485 xmlSchemaPContentErr(ctxt,
8486 XML_SCHEMAP_S4S_ELEM_MISSING,
8487 NULL, node, child,
8488 "A child element is missing",
8489 "(annotation?, (selector, field+))");
8492 * Child element <selector>.
8494 if (IS_SCHEMA(child, "selector")) {
8495 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8496 item, child, 0);
8497 child = child->next;
8499 * Child elements <field>.
8501 if (IS_SCHEMA(child, "field")) {
8502 do {
8503 field = xmlSchemaParseIDCSelectorAndField(ctxt,
8504 item, child, 1);
8505 if (field != NULL) {
8506 field->index = item->nbFields;
8507 item->nbFields++;
8508 if (lastField != NULL)
8509 lastField->next = field;
8510 else
8511 item->fields = field;
8512 lastField = field;
8514 child = child->next;
8515 } while (IS_SCHEMA(child, "field"));
8516 } else {
8517 xmlSchemaPContentErr(ctxt,
8518 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8519 NULL, node, child,
8520 NULL, "(annotation?, (selector, field+))");
8523 if (child != NULL) {
8524 xmlSchemaPContentErr(ctxt,
8525 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8526 NULL, node, child,
8527 NULL, "(annotation?, (selector, field+))");
8530 return (item);
8534 * xmlSchemaParseElement:
8535 * @ctxt: a schema validation context
8536 * @schema: the schema being built
8537 * @node: a subtree containing XML Schema information
8538 * @topLevel: indicates if this is global declaration
8540 * Parses a XML schema element declaration.
8541 * *WARNING* this interface is highly subject to change
8543 * Returns the element declaration or a particle; NULL in case
8544 * of an error or if the particle has minOccurs==maxOccurs==0.
8546 static xmlSchemaBasicItemPtr
8547 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8548 xmlNodePtr node, int *isElemRef, int topLevel)
8550 xmlSchemaElementPtr decl = NULL;
8551 xmlSchemaParticlePtr particle = NULL;
8552 xmlSchemaAnnotPtr annot = NULL;
8553 xmlNodePtr child = NULL;
8554 xmlAttrPtr attr, nameAttr;
8555 int min, max, isRef = 0;
8556 xmlChar *des = NULL;
8558 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8559 /* TODO: Complete implementation of 3.3.6 */
8561 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8562 return (NULL);
8564 if (isElemRef != NULL)
8565 *isElemRef = 0;
8567 * If we get a "ref" attribute on a local <element> we will assume it's
8568 * a reference - even if there's a "name" attribute; this seems to be more
8569 * robust.
8571 nameAttr = xmlSchemaGetPropNode(node, "name");
8572 attr = xmlSchemaGetPropNode(node, "ref");
8573 if ((topLevel) || (attr == NULL)) {
8574 if (nameAttr == NULL) {
8575 xmlSchemaPMissingAttrErr(ctxt,
8576 XML_SCHEMAP_S4S_ATTR_MISSING,
8577 NULL, node, "name", NULL);
8578 return (NULL);
8580 } else
8581 isRef = 1;
8583 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8584 child = node->children;
8585 if (IS_SCHEMA(child, "annotation")) {
8586 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8587 child = child->next;
8590 * Skip particle part if a global declaration.
8592 if (topLevel)
8593 goto declaration_part;
8595 * The particle part ==================================================
8597 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8598 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8599 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8600 particle = xmlSchemaAddParticle(ctxt, node, min, max);
8601 if (particle == NULL)
8602 goto return_null;
8604 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8606 if (isRef) {
8607 const xmlChar *refNs = NULL, *ref = NULL;
8608 xmlSchemaQNameRefPtr refer = NULL;
8610 * The reference part =============================================
8612 if (isElemRef != NULL)
8613 *isElemRef = 1;
8615 xmlSchemaPValAttrNodeQName(ctxt, schema,
8616 NULL, attr, &refNs, &ref);
8617 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8619 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8621 if (nameAttr != NULL) {
8622 xmlSchemaPMutualExclAttrErr(ctxt,
8623 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8626 * Check for illegal attributes.
8628 attr = node->properties;
8629 while (attr != NULL) {
8630 if (attr->ns == NULL) {
8631 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8632 xmlStrEqual(attr->name, BAD_CAST "name") ||
8633 xmlStrEqual(attr->name, BAD_CAST "id") ||
8634 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8635 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8637 attr = attr->next;
8638 continue;
8639 } else {
8640 /* SPEC (3.3.3 : 2.2) */
8641 xmlSchemaPCustomAttrErr(ctxt,
8642 XML_SCHEMAP_SRC_ELEMENT_2_2,
8643 NULL, NULL, attr,
8644 "Only the attributes 'minOccurs', 'maxOccurs' and "
8645 "'id' are allowed in addition to 'ref'");
8646 break;
8648 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8649 xmlSchemaPIllegalAttrErr(ctxt,
8650 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8652 attr = attr->next;
8655 * No children except <annotation> expected.
8657 if (child != NULL) {
8658 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8659 NULL, node, child, NULL, "(annotation?)");
8661 if ((min == 0) && (max == 0))
8662 goto return_null;
8664 * Create the reference item and attach it to the particle.
8666 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8667 ref, refNs);
8668 if (refer == NULL)
8669 goto return_null;
8670 particle->children = (xmlSchemaTreeItemPtr) refer;
8671 particle->annot = annot;
8673 * Add the particle to pending components, since the reference
8674 * need to be resolved.
8676 WXS_ADD_PENDING(ctxt, particle);
8677 return ((xmlSchemaBasicItemPtr) particle);
8680 * The declaration part ===============================================
8682 declaration_part:
8684 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8685 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8687 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8688 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8689 goto return_null;
8691 * Evaluate the target namespace.
8693 if (topLevel) {
8694 ns = ctxt->targetNamespace;
8695 } else {
8696 attr = xmlSchemaGetPropNode(node, "form");
8697 if (attr != NULL) {
8698 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8699 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8700 ns = ctxt->targetNamespace;
8701 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8702 xmlSchemaPSimpleTypeErr(ctxt,
8703 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8704 NULL, (xmlNodePtr) attr,
8705 NULL, "(qualified | unqualified)",
8706 attrValue, NULL, NULL, NULL);
8708 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8709 ns = ctxt->targetNamespace;
8711 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8712 if (decl == NULL) {
8713 goto return_null;
8716 * Check for illegal attributes.
8718 attr = node->properties;
8719 while (attr != NULL) {
8720 if (attr->ns == NULL) {
8721 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8722 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8723 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8724 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8725 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8726 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8727 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8729 if (topLevel == 0) {
8730 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8731 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8732 (!xmlStrEqual(attr->name, BAD_CAST "form")))
8734 xmlSchemaPIllegalAttrErr(ctxt,
8735 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8737 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8738 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8739 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8741 xmlSchemaPIllegalAttrErr(ctxt,
8742 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8745 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8747 xmlSchemaPIllegalAttrErr(ctxt,
8748 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8750 attr = attr->next;
8753 * Extract/validate attributes.
8755 if (topLevel) {
8757 * Process top attributes of global element declarations here.
8759 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8760 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8761 xmlSchemaPValAttrQName(ctxt, schema,
8762 NULL, node, "substitutionGroup",
8763 &(decl->substGroupNs), &(decl->substGroup));
8764 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8765 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8767 * Attribute "final".
8769 attr = xmlSchemaGetPropNode(node, "final");
8770 if (attr == NULL) {
8771 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8772 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8773 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8774 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8775 } else {
8776 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8777 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8779 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8780 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8781 xmlSchemaPSimpleTypeErr(ctxt,
8782 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8783 NULL, (xmlNodePtr) attr,
8784 NULL, "(#all | List of (extension | restriction))",
8785 attrValue, NULL, NULL, NULL);
8790 * Attribute "block".
8792 attr = xmlSchemaGetPropNode(node, "block");
8793 if (attr == NULL) {
8795 * Apply default "block" values.
8797 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8798 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8799 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8800 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8801 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8802 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8803 } else {
8804 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8805 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8807 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8808 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8809 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8810 xmlSchemaPSimpleTypeErr(ctxt,
8811 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8812 NULL, (xmlNodePtr) attr,
8813 NULL, "(#all | List of (extension | "
8814 "restriction | substitution))", attrValue,
8815 NULL, NULL, NULL);
8818 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8819 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8821 attr = xmlSchemaGetPropNode(node, "type");
8822 if (attr != NULL) {
8823 xmlSchemaPValAttrNodeQName(ctxt, schema,
8824 NULL, attr,
8825 &(decl->namedTypeNs), &(decl->namedType));
8826 xmlSchemaCheckReference(ctxt, schema, node,
8827 attr, decl->namedTypeNs);
8829 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8830 attr = xmlSchemaGetPropNode(node, "fixed");
8831 if (attr != NULL) {
8832 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8833 if (decl->value != NULL) {
8835 * 3.3.3 : 1
8836 * default and fixed must not both be present.
8838 xmlSchemaPMutualExclAttrErr(ctxt,
8839 XML_SCHEMAP_SRC_ELEMENT_1,
8840 NULL, attr, "default", "fixed");
8841 } else {
8842 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8843 decl->value = fixed;
8847 * And now for the children...
8849 if (IS_SCHEMA(child, "complexType")) {
8851 * 3.3.3 : 3
8852 * "type" and either <simpleType> or <complexType> are mutually
8853 * exclusive
8855 if (decl->namedType != NULL) {
8856 xmlSchemaPContentErr(ctxt,
8857 XML_SCHEMAP_SRC_ELEMENT_3,
8858 NULL, node, child,
8859 "The attribute 'type' and the <complexType> child are "
8860 "mutually exclusive", NULL);
8861 } else
8862 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8863 child = child->next;
8864 } else if (IS_SCHEMA(child, "simpleType")) {
8866 * 3.3.3 : 3
8867 * "type" and either <simpleType> or <complexType> are
8868 * mutually exclusive
8870 if (decl->namedType != NULL) {
8871 xmlSchemaPContentErr(ctxt,
8872 XML_SCHEMAP_SRC_ELEMENT_3,
8873 NULL, node, child,
8874 "The attribute 'type' and the <simpleType> child are "
8875 "mutually exclusive", NULL);
8876 } else
8877 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8878 child = child->next;
8880 while ((IS_SCHEMA(child, "unique")) ||
8881 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8882 if (IS_SCHEMA(child, "unique")) {
8883 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8884 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8885 } else if (IS_SCHEMA(child, "key")) {
8886 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8887 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8888 } else if (IS_SCHEMA(child, "keyref")) {
8889 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8890 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8892 if (lastIDC != NULL)
8893 lastIDC->next = curIDC;
8894 else
8895 decl->idcs = (void *) curIDC;
8896 lastIDC = curIDC;
8897 child = child->next;
8899 if (child != NULL) {
8900 xmlSchemaPContentErr(ctxt,
8901 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8902 NULL, node, child,
8903 NULL, "(annotation?, ((simpleType | complexType)?, "
8904 "(unique | key | keyref)*))");
8906 decl->annot = annot;
8909 * NOTE: Element Declaration Representation OK 4. will be checked at a
8910 * different layer.
8912 FREE_AND_NULL(des)
8913 if (topLevel)
8914 return ((xmlSchemaBasicItemPtr) decl);
8915 else {
8916 particle->children = (xmlSchemaTreeItemPtr) decl;
8917 return ((xmlSchemaBasicItemPtr) particle);
8920 return_null:
8921 FREE_AND_NULL(des);
8922 if (annot != NULL) {
8923 if (particle != NULL)
8924 particle->annot = NULL;
8925 if (decl != NULL)
8926 decl->annot = NULL;
8927 xmlSchemaFreeAnnot(annot);
8929 return (NULL);
8933 * xmlSchemaParseUnion:
8934 * @ctxt: a schema validation context
8935 * @schema: the schema being built
8936 * @node: a subtree containing XML Schema information
8938 * parse a XML schema Union definition
8939 * *WARNING* this interface is highly subject to change
8941 * Returns -1 in case of internal error, 0 in case of success and a positive
8942 * error code otherwise.
8944 static int
8945 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8946 xmlNodePtr node)
8948 xmlSchemaTypePtr type;
8949 xmlNodePtr child = NULL;
8950 xmlAttrPtr attr;
8951 const xmlChar *cur = NULL;
8953 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8954 return (-1);
8955 /* Not a component, don't create it. */
8956 type = ctxt->ctxtType;
8958 * Mark the simple type as being of variety "union".
8960 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8962 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8963 * then the `simple ur-type definition`."
8965 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8967 * Check for illegal attributes.
8969 attr = node->properties;
8970 while (attr != NULL) {
8971 if (attr->ns == NULL) {
8972 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8973 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8974 xmlSchemaPIllegalAttrErr(ctxt,
8975 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8977 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8978 xmlSchemaPIllegalAttrErr(ctxt,
8979 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8981 attr = attr->next;
8983 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8985 * Attribute "memberTypes". This is a list of QNames.
8986 * TODO: Check the value to contain anything.
8988 attr = xmlSchemaGetPropNode(node, "memberTypes");
8989 if (attr != NULL) {
8990 const xmlChar *end;
8991 xmlChar *tmp;
8992 const xmlChar *localName, *nsName;
8993 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8994 xmlSchemaQNameRefPtr ref;
8996 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8997 type->base = cur;
8998 do {
8999 while (IS_BLANK_CH(*cur))
9000 cur++;
9001 end = cur;
9002 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9003 end++;
9004 if (end == cur)
9005 break;
9006 tmp = xmlStrndup(cur, end - cur);
9007 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
9008 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
9010 * Create the member type link.
9012 link = (xmlSchemaTypeLinkPtr)
9013 xmlMalloc(sizeof(xmlSchemaTypeLink));
9014 if (link == NULL) {
9015 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
9016 "allocating a type link", NULL);
9017 return (-1);
9019 link->type = NULL;
9020 link->next = NULL;
9021 if (lastLink == NULL)
9022 type->memberTypes = link;
9023 else
9024 lastLink->next = link;
9025 lastLink = link;
9027 * Create a reference item.
9029 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
9030 localName, nsName);
9031 if (ref == NULL) {
9032 FREE_AND_NULL(tmp)
9033 return (-1);
9036 * Assign the reference to the link, it will be resolved
9037 * later during fixup of the union simple type.
9039 link->type = (xmlSchemaTypePtr) ref;
9041 FREE_AND_NULL(tmp)
9042 cur = end;
9043 } while (*cur != 0);
9047 * And now for the children...
9049 child = node->children;
9050 if (IS_SCHEMA(child, "annotation")) {
9052 * Add the annotation to the simple type ancestor.
9054 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9055 xmlSchemaParseAnnotation(ctxt, child, 1));
9056 child = child->next;
9058 if (IS_SCHEMA(child, "simpleType")) {
9059 xmlSchemaTypePtr subtype, last = NULL;
9062 * Anchor the member types in the "subtypes" field of the
9063 * simple type.
9065 while (IS_SCHEMA(child, "simpleType")) {
9066 subtype = (xmlSchemaTypePtr)
9067 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9068 if (subtype != NULL) {
9069 if (last == NULL) {
9070 type->subtypes = subtype;
9071 last = subtype;
9072 } else {
9073 last->next = subtype;
9074 last = subtype;
9076 last->next = NULL;
9078 child = child->next;
9081 if (child != NULL) {
9082 xmlSchemaPContentErr(ctxt,
9083 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9084 NULL, node, child, NULL, "(annotation?, simpleType*)");
9086 if ((attr == NULL) && (type->subtypes == NULL)) {
9088 * src-union-memberTypes-or-simpleTypes
9089 * Either the memberTypes [attribute] of the <union> element must
9090 * be non-empty or there must be at least one simpleType [child].
9092 xmlSchemaPCustomErr(ctxt,
9093 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9094 NULL, node,
9095 "Either the attribute 'memberTypes' or "
9096 "at least one <simpleType> child must be present", NULL);
9098 return (0);
9102 * xmlSchemaParseList:
9103 * @ctxt: a schema validation context
9104 * @schema: the schema being built
9105 * @node: a subtree containing XML Schema information
9107 * parse a XML schema List definition
9108 * *WARNING* this interface is highly subject to change
9110 * Returns -1 in case of error, 0 if the declaration is improper and
9111 * 1 in case of success.
9113 static xmlSchemaTypePtr
9114 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9115 xmlNodePtr node)
9117 xmlSchemaTypePtr type;
9118 xmlNodePtr child = NULL;
9119 xmlAttrPtr attr;
9121 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9122 return (NULL);
9123 /* Not a component, don't create it. */
9124 type = ctxt->ctxtType;
9126 * Mark the type as being of variety "list".
9128 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9130 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9131 * then the `simple ur-type definition`."
9133 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9135 * Check for illegal attributes.
9137 attr = node->properties;
9138 while (attr != NULL) {
9139 if (attr->ns == NULL) {
9140 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9141 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9142 xmlSchemaPIllegalAttrErr(ctxt,
9143 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9145 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9146 xmlSchemaPIllegalAttrErr(ctxt,
9147 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9149 attr = attr->next;
9152 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9155 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9156 * fields for holding the reference to the itemType.
9158 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9159 * the "ref" fields.
9161 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9162 node, "itemType", &(type->baseNs), &(type->base));
9164 * And now for the children...
9166 child = node->children;
9167 if (IS_SCHEMA(child, "annotation")) {
9168 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9169 xmlSchemaParseAnnotation(ctxt, child, 1));
9170 child = child->next;
9172 if (IS_SCHEMA(child, "simpleType")) {
9174 * src-list-itemType-or-simpleType
9175 * Either the itemType [attribute] or the <simpleType> [child] of
9176 * the <list> element must be present, but not both.
9178 if (type->base != NULL) {
9179 xmlSchemaPCustomErr(ctxt,
9180 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9181 NULL, node,
9182 "The attribute 'itemType' and the <simpleType> child "
9183 "are mutually exclusive", NULL);
9184 } else {
9185 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9187 child = child->next;
9188 } else if (type->base == NULL) {
9189 xmlSchemaPCustomErr(ctxt,
9190 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9191 NULL, node,
9192 "Either the attribute 'itemType' or the <simpleType> child "
9193 "must be present", NULL);
9195 if (child != NULL) {
9196 xmlSchemaPContentErr(ctxt,
9197 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9198 NULL, node, child, NULL, "(annotation?, simpleType?)");
9200 if ((type->base == NULL) &&
9201 (type->subtypes == NULL) &&
9202 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9203 xmlSchemaPCustomErr(ctxt,
9204 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9205 NULL, node,
9206 "Either the attribute 'itemType' or the <simpleType> child "
9207 "must be present", NULL);
9209 return (NULL);
9213 * xmlSchemaParseSimpleType:
9214 * @ctxt: a schema validation context
9215 * @schema: the schema being built
9216 * @node: a subtree containing XML Schema information
9218 * parse a XML schema Simple Type definition
9219 * *WARNING* this interface is highly subject to change
9221 * Returns -1 in case of error, 0 if the declaration is improper and
9222 * 1 in case of success.
9224 static xmlSchemaTypePtr
9225 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9226 xmlNodePtr node, int topLevel)
9228 xmlSchemaTypePtr type, oldCtxtType;
9229 xmlNodePtr child = NULL;
9230 const xmlChar *attrValue = NULL;
9231 xmlAttrPtr attr;
9232 int hasRestriction = 0;
9234 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9235 return (NULL);
9237 if (topLevel) {
9238 attr = xmlSchemaGetPropNode(node, "name");
9239 if (attr == NULL) {
9240 xmlSchemaPMissingAttrErr(ctxt,
9241 XML_SCHEMAP_S4S_ATTR_MISSING,
9242 NULL, node,
9243 "name", NULL);
9244 return (NULL);
9245 } else {
9246 if (xmlSchemaPValAttrNode(ctxt,
9247 NULL, attr,
9248 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9249 return (NULL);
9251 * Skip built-in types.
9253 if (ctxt->isS4S) {
9254 xmlSchemaTypePtr biType;
9256 if (ctxt->isRedefine) {
9258 * REDEFINE: Disallow redefinition of built-in-types.
9259 * TODO: It seems that the spec does not say anything
9260 * about this case.
9262 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9263 NULL, node,
9264 "Redefinition of built-in simple types is not "
9265 "supported", NULL);
9266 return(NULL);
9268 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9269 if (biType != NULL)
9270 return (biType);
9275 * TargetNamespace:
9276 * SPEC "The `actual value` of the targetNamespace [attribute]
9277 * of the <schema> ancestor element information item if present,
9278 * otherwise `absent`.
9280 if (topLevel == 0) {
9281 #ifdef ENABLE_NAMED_LOCALS
9282 char buf[40];
9283 #endif
9285 * Parse as local simple type definition.
9287 #ifdef ENABLE_NAMED_LOCALS
9288 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9289 type = xmlSchemaAddType(ctxt, schema,
9290 XML_SCHEMA_TYPE_SIMPLE,
9291 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9292 ctxt->targetNamespace, node, 0);
9293 #else
9294 type = xmlSchemaAddType(ctxt, schema,
9295 XML_SCHEMA_TYPE_SIMPLE,
9296 NULL, ctxt->targetNamespace, node, 0);
9297 #endif
9298 if (type == NULL)
9299 return (NULL);
9300 type->type = XML_SCHEMA_TYPE_SIMPLE;
9301 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9303 * Check for illegal attributes.
9305 attr = node->properties;
9306 while (attr != NULL) {
9307 if (attr->ns == NULL) {
9308 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9309 xmlSchemaPIllegalAttrErr(ctxt,
9310 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9312 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9313 xmlSchemaPIllegalAttrErr(ctxt,
9314 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9316 attr = attr->next;
9318 } else {
9320 * Parse as global simple type definition.
9322 * Note that attrValue is the value of the attribute "name" here.
9324 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9325 attrValue, ctxt->targetNamespace, node, 1);
9326 if (type == NULL)
9327 return (NULL);
9328 type->type = XML_SCHEMA_TYPE_SIMPLE;
9329 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9330 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9332 * Check for illegal attributes.
9334 attr = node->properties;
9335 while (attr != NULL) {
9336 if (attr->ns == NULL) {
9337 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9338 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9339 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9340 xmlSchemaPIllegalAttrErr(ctxt,
9341 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9343 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9344 xmlSchemaPIllegalAttrErr(ctxt,
9345 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9347 attr = attr->next;
9350 * Attribute "final".
9352 attr = xmlSchemaGetPropNode(node, "final");
9353 if (attr == NULL) {
9354 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9355 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9356 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9357 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9358 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9359 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9360 } else {
9361 attrValue = xmlSchemaGetProp(ctxt, node, "final");
9362 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9363 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9364 XML_SCHEMAS_TYPE_FINAL_LIST,
9365 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9367 xmlSchemaPSimpleTypeErr(ctxt,
9368 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9369 WXS_BASIC_CAST type, (xmlNodePtr) attr,
9370 NULL, "(#all | List of (list | union | restriction)",
9371 attrValue, NULL, NULL, NULL);
9375 type->targetNamespace = ctxt->targetNamespace;
9376 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9378 * And now for the children...
9380 oldCtxtType = ctxt->ctxtType;
9382 ctxt->ctxtType = type;
9384 child = node->children;
9385 if (IS_SCHEMA(child, "annotation")) {
9386 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9387 child = child->next;
9389 if (child == NULL) {
9390 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9391 NULL, node, child, NULL,
9392 "(annotation?, (restriction | list | union))");
9393 } else if (IS_SCHEMA(child, "restriction")) {
9394 xmlSchemaParseRestriction(ctxt, schema, child,
9395 XML_SCHEMA_TYPE_SIMPLE);
9396 hasRestriction = 1;
9397 child = child->next;
9398 } else if (IS_SCHEMA(child, "list")) {
9399 xmlSchemaParseList(ctxt, schema, child);
9400 child = child->next;
9401 } else if (IS_SCHEMA(child, "union")) {
9402 xmlSchemaParseUnion(ctxt, schema, child);
9403 child = child->next;
9405 if (child != NULL) {
9406 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9407 NULL, node, child, NULL,
9408 "(annotation?, (restriction | list | union))");
9411 * REDEFINE: SPEC src-redefine (5)
9412 * "Within the [children], each <simpleType> must have a
9413 * <restriction> among its [children] ... the `actual value` of whose
9414 * base [attribute] must be the same as the `actual value` of its own
9415 * name attribute plus target namespace;"
9417 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9418 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9419 NULL, node, "This is a redefinition, thus the "
9420 "<simpleType> must have a <restriction> child", NULL);
9423 ctxt->ctxtType = oldCtxtType;
9424 return (type);
9428 * xmlSchemaParseModelGroupDefRef:
9429 * @ctxt: the parser context
9430 * @schema: the schema being built
9431 * @node: the node
9433 * Parses a reference to a model group definition.
9435 * We will return a particle component with a qname-component or
9436 * NULL in case of an error.
9438 static xmlSchemaTreeItemPtr
9439 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9440 xmlSchemaPtr schema,
9441 xmlNodePtr node)
9443 xmlSchemaParticlePtr item;
9444 xmlNodePtr child = NULL;
9445 xmlAttrPtr attr;
9446 const xmlChar *ref = NULL, *refNs = NULL;
9447 int min, max;
9449 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9450 return (NULL);
9452 attr = xmlSchemaGetPropNode(node, "ref");
9453 if (attr == NULL) {
9454 xmlSchemaPMissingAttrErr(ctxt,
9455 XML_SCHEMAP_S4S_ATTR_MISSING,
9456 NULL, node, "ref", NULL);
9457 return (NULL);
9458 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9459 attr, &refNs, &ref) != 0) {
9460 return (NULL);
9462 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9463 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9464 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9465 "(xs:nonNegativeInteger | unbounded)");
9467 * Check for illegal attributes.
9469 attr = node->properties;
9470 while (attr != NULL) {
9471 if (attr->ns == NULL) {
9472 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9473 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9474 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9475 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9476 xmlSchemaPIllegalAttrErr(ctxt,
9477 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9479 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9480 xmlSchemaPIllegalAttrErr(ctxt,
9481 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9483 attr = attr->next;
9485 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9486 item = xmlSchemaAddParticle(ctxt, node, min, max);
9487 if (item == NULL)
9488 return (NULL);
9490 * Create a qname-reference and set as the term; it will be substituted
9491 * for the model group after the reference has been resolved.
9493 item->children = (xmlSchemaTreeItemPtr)
9494 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9495 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9497 * And now for the children...
9499 child = node->children;
9500 /* TODO: Is annotation even allowed for a model group reference? */
9501 if (IS_SCHEMA(child, "annotation")) {
9503 * TODO: What to do exactly with the annotation?
9505 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9506 child = child->next;
9508 if (child != NULL) {
9509 xmlSchemaPContentErr(ctxt,
9510 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9511 NULL, node, child, NULL,
9512 "(annotation?)");
9515 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9517 if ((min == 0) && (max == 0))
9518 return (NULL);
9520 return ((xmlSchemaTreeItemPtr) item);
9524 * xmlSchemaParseModelGroupDefinition:
9525 * @ctxt: a schema validation context
9526 * @schema: the schema being built
9527 * @node: a subtree containing XML Schema information
9529 * Parses a XML schema model group definition.
9531 * Note that the constraint src-redefine (6.2) can't be applied until
9532 * references have been resolved. So we will do this at the
9533 * component fixup level.
9535 * *WARNING* this interface is highly subject to change
9537 * Returns -1 in case of error, 0 if the declaration is improper and
9538 * 1 in case of success.
9540 static xmlSchemaModelGroupDefPtr
9541 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9542 xmlSchemaPtr schema,
9543 xmlNodePtr node)
9545 xmlSchemaModelGroupDefPtr item;
9546 xmlNodePtr child = NULL;
9547 xmlAttrPtr attr;
9548 const xmlChar *name;
9550 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9551 return (NULL);
9553 attr = xmlSchemaGetPropNode(node, "name");
9554 if (attr == NULL) {
9555 xmlSchemaPMissingAttrErr(ctxt,
9556 XML_SCHEMAP_S4S_ATTR_MISSING,
9557 NULL, node,
9558 "name", NULL);
9559 return (NULL);
9560 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9561 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9562 return (NULL);
9564 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9565 ctxt->targetNamespace, node);
9566 if (item == NULL)
9567 return (NULL);
9569 * Check for illegal attributes.
9571 attr = node->properties;
9572 while (attr != NULL) {
9573 if (attr->ns == NULL) {
9574 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9575 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9576 xmlSchemaPIllegalAttrErr(ctxt,
9577 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9579 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9580 xmlSchemaPIllegalAttrErr(ctxt,
9581 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9583 attr = attr->next;
9585 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9587 * And now for the children...
9589 child = node->children;
9590 if (IS_SCHEMA(child, "annotation")) {
9591 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9592 child = child->next;
9594 if (IS_SCHEMA(child, "all")) {
9595 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9596 XML_SCHEMA_TYPE_ALL, 0);
9597 child = child->next;
9598 } else if (IS_SCHEMA(child, "choice")) {
9599 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9600 XML_SCHEMA_TYPE_CHOICE, 0);
9601 child = child->next;
9602 } else if (IS_SCHEMA(child, "sequence")) {
9603 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9604 XML_SCHEMA_TYPE_SEQUENCE, 0);
9605 child = child->next;
9610 if (child != NULL) {
9611 xmlSchemaPContentErr(ctxt,
9612 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9613 NULL, node, child, NULL,
9614 "(annotation?, (all | choice | sequence)?)");
9616 return (item);
9620 * xmlSchemaCleanupDoc:
9621 * @ctxt: a schema validation context
9622 * @node: the root of the document.
9624 * removes unwanted nodes in a schemas document tree
9626 static void
9627 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9629 xmlNodePtr delete, cur;
9631 if ((ctxt == NULL) || (root == NULL)) return;
9634 * Remove all the blank text nodes
9636 delete = NULL;
9637 cur = root;
9638 while (cur != NULL) {
9639 if (delete != NULL) {
9640 xmlUnlinkNode(delete);
9641 xmlFreeNode(delete);
9642 delete = NULL;
9644 if (cur->type == XML_TEXT_NODE) {
9645 if (IS_BLANK_NODE(cur)) {
9646 if (xmlNodeGetSpacePreserve(cur) != 1) {
9647 delete = cur;
9650 } else if ((cur->type != XML_ELEMENT_NODE) &&
9651 (cur->type != XML_CDATA_SECTION_NODE)) {
9652 delete = cur;
9653 goto skip_children;
9657 * Skip to next node
9659 if (cur->children != NULL) {
9660 if ((cur->children->type != XML_ENTITY_DECL) &&
9661 (cur->children->type != XML_ENTITY_REF_NODE) &&
9662 (cur->children->type != XML_ENTITY_NODE)) {
9663 cur = cur->children;
9664 continue;
9667 skip_children:
9668 if (cur->next != NULL) {
9669 cur = cur->next;
9670 continue;
9673 do {
9674 cur = cur->parent;
9675 if (cur == NULL)
9676 break;
9677 if (cur == root) {
9678 cur = NULL;
9679 break;
9681 if (cur->next != NULL) {
9682 cur = cur->next;
9683 break;
9685 } while (cur != NULL);
9687 if (delete != NULL) {
9688 xmlUnlinkNode(delete);
9689 xmlFreeNode(delete);
9690 delete = NULL;
9695 static void
9696 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9698 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9699 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9701 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9702 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9704 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9705 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9706 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9707 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9708 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9709 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9710 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9711 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9713 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9714 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9715 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9716 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9717 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9718 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9721 static int
9722 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9723 xmlSchemaPtr schema,
9724 xmlNodePtr node)
9726 xmlAttrPtr attr;
9727 const xmlChar *val;
9728 int res = 0, oldErrs = ctxt->nberrors;
9731 * Those flags should be moved to the parser context flags,
9732 * since they are not visible at the component level. I.e.
9733 * they are used if processing schema *documents* only.
9735 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9736 HFAILURE;
9739 * Since the version is of type xs:token, we won't bother to
9740 * check it.
9742 /* REMOVED:
9743 attr = xmlSchemaGetPropNode(node, "version");
9744 if (attr != NULL) {
9745 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9746 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9747 HFAILURE;
9750 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9751 if (attr != NULL) {
9752 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9753 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9754 HFAILURE;
9755 if (res != 0) {
9756 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9757 goto exit;
9760 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9761 if (attr != NULL) {
9762 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9763 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9764 XML_SCHEMAS_QUALIF_ELEM);
9765 HFAILURE;
9766 if (res != 0) {
9767 xmlSchemaPSimpleTypeErr(ctxt,
9768 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9769 NULL, (xmlNodePtr) attr, NULL,
9770 "(qualified | unqualified)", val, NULL, NULL, NULL);
9773 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9774 if (attr != NULL) {
9775 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9776 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9777 XML_SCHEMAS_QUALIF_ATTR);
9778 HFAILURE;
9779 if (res != 0) {
9780 xmlSchemaPSimpleTypeErr(ctxt,
9781 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9782 NULL, (xmlNodePtr) attr, NULL,
9783 "(qualified | unqualified)", val, NULL, NULL, NULL);
9786 attr = xmlSchemaGetPropNode(node, "finalDefault");
9787 if (attr != NULL) {
9788 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9789 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9790 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9791 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9793 XML_SCHEMAS_FINAL_DEFAULT_LIST,
9794 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9795 HFAILURE;
9796 if (res != 0) {
9797 xmlSchemaPSimpleTypeErr(ctxt,
9798 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9799 NULL, (xmlNodePtr) attr, NULL,
9800 "(#all | List of (extension | restriction | list | union))",
9801 val, NULL, NULL, NULL);
9804 attr = xmlSchemaGetPropNode(node, "blockDefault");
9805 if (attr != NULL) {
9806 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9807 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9808 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9809 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9810 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9811 HFAILURE;
9812 if (res != 0) {
9813 xmlSchemaPSimpleTypeErr(ctxt,
9814 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9815 NULL, (xmlNodePtr) attr, NULL,
9816 "(#all | List of (extension | restriction | substitution))",
9817 val, NULL, NULL, NULL);
9821 exit:
9822 if (oldErrs != ctxt->nberrors)
9823 res = ctxt->err;
9824 return(res);
9825 exit_failure:
9826 return(-1);
9830 * xmlSchemaParseSchemaTopLevel:
9831 * @ctxt: a schema validation context
9832 * @schema: the schemas
9833 * @nodes: the list of top level nodes
9835 * Returns the internal XML Schema structure built from the resource or
9836 * NULL in case of error
9838 static int
9839 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9840 xmlSchemaPtr schema, xmlNodePtr nodes)
9842 xmlNodePtr child;
9843 xmlSchemaAnnotPtr annot;
9844 int res = 0, oldErrs, tmpOldErrs;
9846 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9847 return(-1);
9849 oldErrs = ctxt->nberrors;
9850 child = nodes;
9851 while ((IS_SCHEMA(child, "include")) ||
9852 (IS_SCHEMA(child, "import")) ||
9853 (IS_SCHEMA(child, "redefine")) ||
9854 (IS_SCHEMA(child, "annotation"))) {
9855 if (IS_SCHEMA(child, "annotation")) {
9856 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9857 if (schema->annot == NULL)
9858 schema->annot = annot;
9859 else
9860 xmlSchemaFreeAnnot(annot);
9861 } else if (IS_SCHEMA(child, "import")) {
9862 tmpOldErrs = ctxt->nberrors;
9863 res = xmlSchemaParseImport(ctxt, schema, child);
9864 HFAILURE;
9865 HSTOP(ctxt);
9866 if (tmpOldErrs != ctxt->nberrors)
9867 goto exit;
9868 } else if (IS_SCHEMA(child, "include")) {
9869 tmpOldErrs = ctxt->nberrors;
9870 res = xmlSchemaParseInclude(ctxt, schema, child);
9871 HFAILURE;
9872 HSTOP(ctxt);
9873 if (tmpOldErrs != ctxt->nberrors)
9874 goto exit;
9875 } else if (IS_SCHEMA(child, "redefine")) {
9876 tmpOldErrs = ctxt->nberrors;
9877 res = xmlSchemaParseRedefine(ctxt, schema, child);
9878 HFAILURE;
9879 HSTOP(ctxt);
9880 if (tmpOldErrs != ctxt->nberrors)
9881 goto exit;
9883 child = child->next;
9886 * URGENT TODO: Change the functions to return int results.
9887 * We need especially to catch internal errors.
9889 while (child != NULL) {
9890 if (IS_SCHEMA(child, "complexType")) {
9891 xmlSchemaParseComplexType(ctxt, schema, child, 1);
9892 child = child->next;
9893 } else if (IS_SCHEMA(child, "simpleType")) {
9894 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9895 child = child->next;
9896 } else if (IS_SCHEMA(child, "element")) {
9897 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9898 child = child->next;
9899 } else if (IS_SCHEMA(child, "attribute")) {
9900 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9901 child = child->next;
9902 } else if (IS_SCHEMA(child, "attributeGroup")) {
9903 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9904 child = child->next;
9905 } else if (IS_SCHEMA(child, "group")) {
9906 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9907 child = child->next;
9908 } else if (IS_SCHEMA(child, "notation")) {
9909 xmlSchemaParseNotation(ctxt, schema, child);
9910 child = child->next;
9911 } else {
9912 xmlSchemaPContentErr(ctxt,
9913 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9914 NULL, child->parent, child,
9915 NULL, "((include | import | redefine | annotation)*, "
9916 "(((simpleType | complexType | group | attributeGroup) "
9917 "| element | attribute | notation), annotation*)*)");
9918 child = child->next;
9920 while (IS_SCHEMA(child, "annotation")) {
9922 * TODO: We should add all annotations.
9924 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9925 if (schema->annot == NULL)
9926 schema->annot = annot;
9927 else
9928 xmlSchemaFreeAnnot(annot);
9929 child = child->next;
9932 exit:
9933 ctxt->ctxtType = NULL;
9934 if (oldErrs != ctxt->nberrors)
9935 res = ctxt->err;
9936 return(res);
9937 exit_failure:
9938 return(-1);
9941 static xmlSchemaSchemaRelationPtr
9942 xmlSchemaSchemaRelationCreate(void)
9944 xmlSchemaSchemaRelationPtr ret;
9946 ret = (xmlSchemaSchemaRelationPtr)
9947 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9948 if (ret == NULL) {
9949 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9950 return(NULL);
9952 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9953 return(ret);
9956 #if 0
9957 static void
9958 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9960 xmlFree(rel);
9962 #endif
9964 static void
9965 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9967 xmlSchemaRedefPtr prev;
9969 while (redef != NULL) {
9970 prev = redef;
9971 redef = redef->next;
9972 xmlFree(prev);
9976 static void
9977 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9980 * After the construction context has been freed, there will be
9981 * no schema graph available any more. Only the schema buckets
9982 * will stay alive, which are put into the "schemasImports" and
9983 * "includes" slots of the xmlSchema.
9985 if (con->buckets != NULL)
9986 xmlSchemaItemListFree(con->buckets);
9987 if (con->pending != NULL)
9988 xmlSchemaItemListFree(con->pending);
9989 if (con->substGroups != NULL)
9990 xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
9991 if (con->redefs != NULL)
9992 xmlSchemaRedefListFree(con->redefs);
9993 if (con->dict != NULL)
9994 xmlDictFree(con->dict);
9995 xmlFree(con);
9998 static xmlSchemaConstructionCtxtPtr
9999 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
10001 xmlSchemaConstructionCtxtPtr ret;
10003 ret = (xmlSchemaConstructionCtxtPtr)
10004 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
10005 if (ret == NULL) {
10006 xmlSchemaPErrMemory(NULL,
10007 "allocating schema construction context", NULL);
10008 return (NULL);
10010 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
10012 ret->buckets = xmlSchemaItemListCreate();
10013 if (ret->buckets == NULL) {
10014 xmlSchemaPErrMemory(NULL,
10015 "allocating list of schema buckets", NULL);
10016 xmlFree(ret);
10017 return (NULL);
10019 ret->pending = xmlSchemaItemListCreate();
10020 if (ret->pending == NULL) {
10021 xmlSchemaPErrMemory(NULL,
10022 "allocating list of pending global components", NULL);
10023 xmlSchemaConstructionCtxtFree(ret);
10024 return (NULL);
10026 ret->dict = dict;
10027 xmlDictReference(dict);
10028 return(ret);
10031 static xmlSchemaParserCtxtPtr
10032 xmlSchemaParserCtxtCreate(void)
10034 xmlSchemaParserCtxtPtr ret;
10036 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10037 if (ret == NULL) {
10038 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10039 NULL);
10040 return (NULL);
10042 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10043 ret->type = XML_SCHEMA_CTXT_PARSER;
10044 ret->attrProhibs = xmlSchemaItemListCreate();
10045 if (ret->attrProhibs == NULL) {
10046 xmlFree(ret);
10047 return(NULL);
10049 return(ret);
10053 * xmlSchemaNewParserCtxtUseDict:
10054 * @URL: the location of the schema
10055 * @dict: the dictionary to be used
10057 * Create an XML Schemas parse context for that file/resource expected
10058 * to contain an XML Schemas file.
10060 * Returns the parser context or NULL in case of error
10062 static xmlSchemaParserCtxtPtr
10063 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10065 xmlSchemaParserCtxtPtr ret;
10067 ret = xmlSchemaParserCtxtCreate();
10068 if (ret == NULL)
10069 return (NULL);
10070 ret->dict = dict;
10071 xmlDictReference(dict);
10072 if (URL != NULL)
10073 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
10074 return (ret);
10077 static int
10078 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
10080 if (vctxt->pctxt == NULL) {
10081 if (vctxt->schema != NULL)
10082 vctxt->pctxt =
10083 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
10084 else
10085 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
10086 if (vctxt->pctxt == NULL) {
10087 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
10088 "failed to create a temp. parser context");
10089 return (-1);
10091 /* TODO: Pass user data. */
10092 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10093 vctxt->warning, vctxt->errCtxt);
10094 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10095 vctxt->errCtxt);
10097 return (0);
10101 * xmlSchemaGetSchemaBucket:
10102 * @pctxt: the schema parser context
10103 * @schemaLocation: the URI of the schema document
10105 * Returns a schema bucket if it was already parsed.
10107 * Returns a schema bucket if it was already parsed from
10108 * @schemaLocation, NULL otherwise.
10110 static xmlSchemaBucketPtr
10111 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10112 const xmlChar *schemaLocation)
10114 xmlSchemaBucketPtr cur;
10115 xmlSchemaItemListPtr list;
10117 list = pctxt->constructor->buckets;
10118 if (list->nbItems == 0)
10119 return(NULL);
10120 else {
10121 int i;
10122 for (i = 0; i < list->nbItems; i++) {
10123 cur = (xmlSchemaBucketPtr) list->items[i];
10124 /* Pointer comparison! */
10125 if (cur->schemaLocation == schemaLocation)
10126 return(cur);
10129 return(NULL);
10132 static xmlSchemaBucketPtr
10133 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10134 const xmlChar *schemaLocation,
10135 const xmlChar *targetNamespace)
10137 xmlSchemaBucketPtr cur;
10138 xmlSchemaItemListPtr list;
10140 list = pctxt->constructor->buckets;
10141 if (list->nbItems == 0)
10142 return(NULL);
10143 else {
10144 int i;
10145 for (i = 0; i < list->nbItems; i++) {
10146 cur = (xmlSchemaBucketPtr) list->items[i];
10147 /* Pointer comparison! */
10148 if ((cur->origTargetNamespace == NULL) &&
10149 (cur->schemaLocation == schemaLocation) &&
10150 (cur->targetNamespace == targetNamespace))
10151 return(cur);
10154 return(NULL);
10158 #define IS_BAD_SCHEMA_DOC(b) \
10159 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10161 static xmlSchemaBucketPtr
10162 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10163 const xmlChar *targetNamespace,
10164 int imported)
10166 xmlSchemaBucketPtr cur;
10167 xmlSchemaItemListPtr list;
10169 list = pctxt->constructor->buckets;
10170 if (list->nbItems == 0)
10171 return(NULL);
10172 else {
10173 int i;
10174 for (i = 0; i < list->nbItems; i++) {
10175 cur = (xmlSchemaBucketPtr) list->items[i];
10176 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10177 (cur->origTargetNamespace == targetNamespace) &&
10178 ((imported && cur->imported) ||
10179 ((!imported) && (!cur->imported))))
10180 return(cur);
10183 return(NULL);
10186 static int
10187 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10188 xmlSchemaPtr schema,
10189 xmlSchemaBucketPtr bucket)
10191 int oldFlags;
10192 xmlDocPtr oldDoc;
10193 xmlNodePtr node;
10194 int ret, oldErrs;
10195 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10198 * Save old values; reset the *main* schema.
10199 * URGENT TODO: This is not good; move the per-document information
10200 * to the parser. Get rid of passing the main schema to the
10201 * parsing functions.
10203 oldFlags = schema->flags;
10204 oldDoc = schema->doc;
10205 if (schema->flags != 0)
10206 xmlSchemaClearSchemaDefaults(schema);
10207 schema->doc = bucket->doc;
10208 pctxt->schema = schema;
10210 * Keep the current target namespace on the parser *not* on the
10211 * main schema.
10213 pctxt->targetNamespace = bucket->targetNamespace;
10214 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10216 if ((bucket->targetNamespace != NULL) &&
10217 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10219 * We are parsing the schema for schemas!
10221 pctxt->isS4S = 1;
10223 /* Mark it as parsed, even if parsing fails. */
10224 bucket->parsed++;
10225 /* Compile the schema doc. */
10226 node = xmlDocGetRootElement(bucket->doc);
10227 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10228 if (ret != 0)
10229 goto exit;
10230 /* An empty schema; just get out. */
10231 if (node->children == NULL)
10232 goto exit;
10233 oldErrs = pctxt->nberrors;
10234 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10235 if (ret != 0)
10236 goto exit;
10238 * TODO: Not nice, but I'm not 100% sure we will get always an error
10239 * as a result of the above functions; so better rely on pctxt->err
10240 * as well.
10242 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10243 ret = pctxt->err;
10244 goto exit;
10247 exit:
10248 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10249 /* Restore schema values. */
10250 schema->doc = oldDoc;
10251 schema->flags = oldFlags;
10252 return(ret);
10255 static int
10256 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10257 xmlSchemaPtr schema,
10258 xmlSchemaBucketPtr bucket)
10260 xmlSchemaParserCtxtPtr newpctxt;
10261 int res = 0;
10263 if (bucket == NULL)
10264 return(0);
10265 if (bucket->parsed) {
10266 PERROR_INT("xmlSchemaParseNewDoc",
10267 "reparsing a schema doc");
10268 return(-1);
10270 if (bucket->doc == NULL) {
10271 PERROR_INT("xmlSchemaParseNewDoc",
10272 "parsing a schema doc, but there's no doc");
10273 return(-1);
10275 if (pctxt->constructor == NULL) {
10276 PERROR_INT("xmlSchemaParseNewDoc",
10277 "no constructor");
10278 return(-1);
10280 /* Create and init the temporary parser context. */
10281 newpctxt = xmlSchemaNewParserCtxtUseDict(
10282 (const char *) bucket->schemaLocation, pctxt->dict);
10283 if (newpctxt == NULL)
10284 return(-1);
10285 newpctxt->constructor = pctxt->constructor;
10287 * TODO: Can we avoid that the parser knows about the main schema?
10288 * It would be better if he knows about the current schema bucket
10289 * only.
10291 newpctxt->schema = schema;
10292 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10293 pctxt->errCtxt);
10294 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10295 pctxt->errCtxt);
10296 newpctxt->counter = pctxt->counter;
10299 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10301 /* Channel back errors and cleanup the temporary parser context. */
10302 if (res != 0)
10303 pctxt->err = res;
10304 pctxt->nberrors += newpctxt->nberrors;
10305 pctxt->counter = newpctxt->counter;
10306 newpctxt->constructor = NULL;
10307 /* Free the parser context. */
10308 xmlSchemaFreeParserCtxt(newpctxt);
10309 return(res);
10312 static void
10313 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10314 xmlSchemaSchemaRelationPtr rel)
10316 xmlSchemaSchemaRelationPtr cur = bucket->relations;
10318 if (cur == NULL) {
10319 bucket->relations = rel;
10320 return;
10322 while (cur->next != NULL)
10323 cur = cur->next;
10324 cur->next = rel;
10328 static const xmlChar *
10329 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10330 xmlNodePtr ctxtNode)
10333 * Build an absolute location URI.
10335 if (location != NULL) {
10336 if (ctxtNode == NULL)
10337 return(location);
10338 else {
10339 xmlChar *base, *URI;
10340 const xmlChar *ret = NULL;
10342 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10343 if (base == NULL) {
10344 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10345 } else {
10346 URI = xmlBuildURI(location, base);
10347 xmlFree(base);
10349 if (URI != NULL) {
10350 ret = xmlDictLookup(dict, URI, -1);
10351 xmlFree(URI);
10352 return(ret);
10356 return(NULL);
10362 * xmlSchemaAddSchemaDoc:
10363 * @pctxt: a schema validation context
10364 * @schema: the schema being built
10365 * @node: a subtree containing XML Schema information
10367 * Parse an included (and to-be-redefined) XML schema document.
10369 * Returns 0 on success, a positive error code on errors and
10370 * -1 in case of an internal or API error.
10373 static int
10374 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10375 int type, /* import or include or redefine */
10376 const xmlChar *schemaLocation,
10377 xmlDocPtr schemaDoc,
10378 const char *schemaBuffer,
10379 int schemaBufferLen,
10380 xmlNodePtr invokingNode,
10381 const xmlChar *sourceTargetNamespace,
10382 const xmlChar *importNamespace,
10383 xmlSchemaBucketPtr *bucket)
10385 const xmlChar *targetNamespace = NULL;
10386 xmlSchemaSchemaRelationPtr relation = NULL;
10387 xmlDocPtr doc = NULL;
10388 int res = 0, err = 0, located = 0, preserveDoc = 0;
10389 xmlSchemaBucketPtr bkt = NULL;
10391 if (bucket != NULL)
10392 *bucket = NULL;
10394 switch (type) {
10395 case XML_SCHEMA_SCHEMA_IMPORT:
10396 case XML_SCHEMA_SCHEMA_MAIN:
10397 err = XML_SCHEMAP_SRC_IMPORT;
10398 break;
10399 case XML_SCHEMA_SCHEMA_INCLUDE:
10400 err = XML_SCHEMAP_SRC_INCLUDE;
10401 break;
10402 case XML_SCHEMA_SCHEMA_REDEFINE:
10403 err = XML_SCHEMAP_SRC_REDEFINE;
10404 break;
10408 /* Special handling for the main schema:
10409 * skip the location and relation logic and just parse the doc.
10410 * We need just a bucket to be returned in this case.
10412 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10413 goto doc_load;
10415 /* Note that we expect the location to be an absolute URI. */
10416 if (schemaLocation != NULL) {
10417 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10418 if ((bkt != NULL) &&
10419 (pctxt->constructor->bucket == bkt)) {
10420 /* Report self-imports/inclusions/redefinitions. */
10422 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10423 invokingNode, NULL,
10424 "The schema must not import/include/redefine itself",
10425 NULL, NULL);
10426 goto exit;
10430 * Create a relation for the graph of schemas.
10432 relation = xmlSchemaSchemaRelationCreate();
10433 if (relation == NULL)
10434 return(-1);
10435 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10436 relation);
10437 relation->type = type;
10440 * Save the namespace import information.
10442 if (WXS_IS_BUCKET_IMPMAIN(type)) {
10443 relation->importNamespace = importNamespace;
10444 if (schemaLocation == NULL) {
10446 * No location; this is just an import of the namespace.
10447 * Note that we don't assign a bucket to the relation
10448 * in this case.
10450 goto exit;
10452 targetNamespace = importNamespace;
10455 /* Did we already fetch the doc? */
10456 if (bkt != NULL) {
10457 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10459 * We included/redefined and then try to import a schema,
10460 * but the new location provided for import was different.
10462 if (schemaLocation == NULL)
10463 schemaLocation = BAD_CAST "in_memory_buffer";
10464 if (!xmlStrEqual(schemaLocation,
10465 bkt->schemaLocation)) {
10466 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10467 invokingNode, NULL,
10468 "The schema document '%s' cannot be imported, since "
10469 "it was already included or redefined",
10470 schemaLocation, NULL);
10471 goto exit;
10473 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10475 * We imported and then try to include/redefine a schema,
10476 * but the new location provided for the include/redefine
10477 * was different.
10479 if (schemaLocation == NULL)
10480 schemaLocation = BAD_CAST "in_memory_buffer";
10481 if (!xmlStrEqual(schemaLocation,
10482 bkt->schemaLocation)) {
10483 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10484 invokingNode, NULL,
10485 "The schema document '%s' cannot be included or "
10486 "redefined, since it was already imported",
10487 schemaLocation, NULL);
10488 goto exit;
10493 if (WXS_IS_BUCKET_IMPMAIN(type)) {
10495 * Given that the schemaLocation [attribute] is only a hint, it is open
10496 * to applications to ignore all but the first <import> for a given
10497 * namespace, regardless of the `actual value` of schemaLocation, but
10498 * such a strategy risks missing useful information when new
10499 * schemaLocations are offered.
10501 * We will use the first <import> that comes with a location.
10502 * Further <import>s *with* a location, will result in an error.
10503 * TODO: Better would be to just report a warning here, but
10504 * we'll try it this way until someone complains.
10506 * Schema Document Location Strategy:
10507 * 3 Based on the namespace name, identify an existing schema document,
10508 * either as a resource which is an XML document or a <schema> element
10509 * information item, in some local schema repository;
10510 * 5 Attempt to resolve the namespace name to locate such a resource.
10512 * NOTE: (3) and (5) are not supported.
10514 if (bkt != NULL) {
10515 relation->bucket = bkt;
10516 goto exit;
10518 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10519 importNamespace, 1);
10521 if (bkt != NULL) {
10522 relation->bucket = bkt;
10523 if (bkt->schemaLocation == NULL) {
10524 /* First given location of the schema; load the doc. */
10525 bkt->schemaLocation = schemaLocation;
10526 } else {
10527 if (!xmlStrEqual(schemaLocation,
10528 bkt->schemaLocation)) {
10530 * Additional location given; just skip it.
10531 * URGENT TODO: We should report a warning here.
10532 * res = XML_SCHEMAP_SRC_IMPORT;
10534 if (schemaLocation == NULL)
10535 schemaLocation = BAD_CAST "in_memory_buffer";
10537 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10538 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10539 invokingNode, NULL,
10540 "Skipping import of schema located at '%s' for the "
10541 "namespace '%s', since this namespace was already "
10542 "imported with the schema located at '%s'",
10543 schemaLocation, importNamespace, bkt->schemaLocation);
10545 goto exit;
10549 * No bucket + first location: load the doc and create a
10550 * bucket.
10552 } else {
10553 /* <include> and <redefine> */
10554 if (bkt != NULL) {
10556 if ((bkt->origTargetNamespace == NULL) &&
10557 (bkt->targetNamespace != sourceTargetNamespace)) {
10558 xmlSchemaBucketPtr chamel;
10561 * Chameleon include/redefine: skip loading only if it was
10562 * already build for the targetNamespace of the including
10563 * schema.
10566 * URGENT TODO: If the schema is a chameleon-include then copy
10567 * the components into the including schema and modify the
10568 * targetNamespace of those components, do nothing otherwise.
10569 * NOTE: This is currently worked-around by compiling the
10570 * chameleon for every distinct including targetNamespace; thus
10571 * not performant at the moment.
10572 * TODO: Check when the namespace in wildcards for chameleons
10573 * needs to be converted: before we built wildcard intersections
10574 * or after.
10575 * Answer: after!
10577 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10578 schemaLocation, sourceTargetNamespace);
10579 if (chamel != NULL) {
10580 /* A fitting chameleon was already parsed; NOP. */
10581 relation->bucket = chamel;
10582 goto exit;
10585 * We need to parse the chameleon again for a different
10586 * targetNamespace.
10587 * CHAMELEON TODO: Optimize this by only parsing the
10588 * chameleon once, and then copying the components to
10589 * the new targetNamespace.
10591 bkt = NULL;
10592 } else {
10593 relation->bucket = bkt;
10594 goto exit;
10598 if ((bkt != NULL) && (bkt->doc != NULL)) {
10599 PERROR_INT("xmlSchemaAddSchemaDoc",
10600 "trying to load a schema doc, but a doc is already "
10601 "assigned to the schema bucket");
10602 goto exit_failure;
10605 doc_load:
10607 * Load the document.
10609 if (schemaDoc != NULL) {
10610 doc = schemaDoc;
10611 /* Don' free this one, since it was provided by the caller. */
10612 preserveDoc = 1;
10613 /* TODO: Does the context or the doc hold the location? */
10614 if (schemaDoc->URL != NULL)
10615 schemaLocation = xmlDictLookup(pctxt->dict,
10616 schemaDoc->URL, -1);
10617 else
10618 schemaLocation = BAD_CAST "in_memory_buffer";
10619 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10620 xmlParserCtxtPtr parserCtxt;
10622 parserCtxt = xmlNewParserCtxt();
10623 if (parserCtxt == NULL) {
10624 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10625 "allocating a parser context", NULL);
10626 goto exit_failure;
10628 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10630 * TODO: Do we have to burden the schema parser dict with all
10631 * the content of the schema doc?
10633 xmlDictFree(parserCtxt->dict);
10634 parserCtxt->dict = pctxt->dict;
10635 xmlDictReference(parserCtxt->dict);
10637 if (schemaLocation != NULL) {
10638 /* Parse from file. */
10639 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10640 NULL, SCHEMAS_PARSE_OPTIONS);
10641 } else if (schemaBuffer != NULL) {
10642 /* Parse from memory buffer. */
10643 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10644 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10645 schemaLocation = BAD_CAST "in_memory_buffer";
10646 if (doc != NULL)
10647 doc->URL = xmlStrdup(schemaLocation);
10650 * For <import>:
10651 * 2.1 The referent is (a fragment of) a resource which is an
10652 * XML document (see clause 1.1), which in turn corresponds to
10653 * a <schema> element information item in a well-formed information
10654 * set, which in turn corresponds to a valid schema.
10655 * TODO: (2.1) fragments of XML documents are not supported.
10657 * 2.2 The referent is a <schema> element information item in
10658 * a well-formed information set, which in turn corresponds
10659 * to a valid schema.
10660 * TODO: (2.2) is not supported.
10662 if (doc == NULL) {
10663 xmlErrorPtr lerr;
10664 lerr = xmlGetLastError();
10666 * Check if this a parser error, or if the document could
10667 * just not be located.
10668 * TODO: Try to find specific error codes to react only on
10669 * localisation failures.
10671 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10673 * We assume a parser error here.
10675 located = 1;
10676 /* TODO: Error code ?? */
10677 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10678 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10679 invokingNode, NULL,
10680 "Failed to parse the XML resource '%s'",
10681 schemaLocation, NULL);
10684 xmlFreeParserCtxt(parserCtxt);
10685 if ((doc == NULL) && located)
10686 goto exit_error;
10687 } else {
10688 xmlSchemaPErr(pctxt, NULL,
10689 XML_SCHEMAP_NOTHING_TO_PARSE,
10690 "No information for parsing was provided with the "
10691 "given schema parser context.\n",
10692 NULL, NULL);
10693 goto exit_failure;
10696 * Preprocess the document.
10698 if (doc != NULL) {
10699 xmlNodePtr docElem = NULL;
10701 located = 1;
10702 docElem = xmlDocGetRootElement(doc);
10703 if (docElem == NULL) {
10704 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10705 invokingNode, NULL,
10706 "The document '%s' has no document element",
10707 schemaLocation, NULL);
10708 goto exit_error;
10711 * Remove all the blank text nodes.
10713 xmlSchemaCleanupDoc(pctxt, docElem);
10715 * Check the schema's top level element.
10717 if (!IS_SCHEMA(docElem, "schema")) {
10718 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10719 invokingNode, NULL,
10720 "The XML document '%s' is not a schema document",
10721 schemaLocation, NULL);
10722 goto exit_error;
10725 * Note that we don't apply a type check for the
10726 * targetNamespace value here.
10728 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10729 "targetNamespace");
10732 /* after_doc_loading: */
10733 if ((bkt == NULL) && located) {
10734 /* Only create a bucket if the schema was located. */
10735 bkt = xmlSchemaBucketCreate(pctxt, type,
10736 targetNamespace);
10737 if (bkt == NULL)
10738 goto exit_failure;
10740 if (bkt != NULL) {
10741 bkt->schemaLocation = schemaLocation;
10742 bkt->located = located;
10743 if (doc != NULL) {
10744 bkt->doc = doc;
10745 bkt->targetNamespace = targetNamespace;
10746 bkt->origTargetNamespace = targetNamespace;
10747 if (preserveDoc)
10748 bkt->preserveDoc = 1;
10750 if (WXS_IS_BUCKET_IMPMAIN(type))
10751 bkt->imported++;
10753 * Add it to the graph of schemas.
10755 if (relation != NULL)
10756 relation->bucket = bkt;
10759 exit:
10761 * Return the bucket explicitly; this is needed for the
10762 * main schema.
10764 if (bucket != NULL)
10765 *bucket = bkt;
10766 return (0);
10768 exit_error:
10769 if ((doc != NULL) && (! preserveDoc)) {
10770 xmlFreeDoc(doc);
10771 if (bkt != NULL)
10772 bkt->doc = NULL;
10774 return(pctxt->err);
10776 exit_failure:
10777 if ((doc != NULL) && (! preserveDoc)) {
10778 xmlFreeDoc(doc);
10779 if (bkt != NULL)
10780 bkt->doc = NULL;
10782 return (-1);
10786 * xmlSchemaParseImport:
10787 * @ctxt: a schema validation context
10788 * @schema: the schema being built
10789 * @node: a subtree containing XML Schema information
10791 * parse a XML schema Import definition
10792 * *WARNING* this interface is highly subject to change
10794 * Returns 0 in case of success, a positive error code if
10795 * not valid and -1 in case of an internal error.
10797 static int
10798 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10799 xmlNodePtr node)
10801 xmlNodePtr child;
10802 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10803 const xmlChar *thisTargetNamespace;
10804 xmlAttrPtr attr;
10805 int ret = 0;
10806 xmlSchemaBucketPtr bucket = NULL;
10808 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10809 return (-1);
10812 * Check for illegal attributes.
10814 attr = node->properties;
10815 while (attr != NULL) {
10816 if (attr->ns == NULL) {
10817 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10818 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10819 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10820 xmlSchemaPIllegalAttrErr(pctxt,
10821 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10823 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10824 xmlSchemaPIllegalAttrErr(pctxt,
10825 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10827 attr = attr->next;
10830 * Extract and validate attributes.
10832 if (xmlSchemaPValAttr(pctxt, NULL, node,
10833 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10834 &namespaceName) != 0) {
10835 xmlSchemaPSimpleTypeErr(pctxt,
10836 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10837 NULL, node,
10838 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10839 NULL, namespaceName, NULL, NULL, NULL);
10840 return (pctxt->err);
10843 if (xmlSchemaPValAttr(pctxt, NULL, node,
10844 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10845 &schemaLocation) != 0) {
10846 xmlSchemaPSimpleTypeErr(pctxt,
10847 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10848 NULL, node,
10849 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10850 NULL, schemaLocation, NULL, NULL, NULL);
10851 return (pctxt->err);
10854 * And now for the children...
10856 child = node->children;
10857 if (IS_SCHEMA(child, "annotation")) {
10859 * the annotation here is simply discarded ...
10860 * TODO: really?
10862 child = child->next;
10864 if (child != NULL) {
10865 xmlSchemaPContentErr(pctxt,
10866 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10867 NULL, node, child, NULL,
10868 "(annotation?)");
10871 * Apply additional constraints.
10873 * Note that it is important to use the original @targetNamespace
10874 * (or none at all), to rule out imports of schemas _with_ a
10875 * @targetNamespace if the importing schema is a chameleon schema
10876 * (with no @targetNamespace).
10878 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10879 if (namespaceName != NULL) {
10881 * 1.1 If the namespace [attribute] is present, then its `actual value`
10882 * must not match the `actual value` of the enclosing <schema>'s
10883 * targetNamespace [attribute].
10885 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10886 xmlSchemaPCustomErr(pctxt,
10887 XML_SCHEMAP_SRC_IMPORT_1_1,
10888 NULL, node,
10889 "The value of the attribute 'namespace' must not match "
10890 "the target namespace '%s' of the importing schema",
10891 thisTargetNamespace);
10892 return (pctxt->err);
10894 } else {
10896 * 1.2 If the namespace [attribute] is not present, then the enclosing
10897 * <schema> must have a targetNamespace [attribute].
10899 if (thisTargetNamespace == NULL) {
10900 xmlSchemaPCustomErr(pctxt,
10901 XML_SCHEMAP_SRC_IMPORT_1_2,
10902 NULL, node,
10903 "The attribute 'namespace' must be existent if "
10904 "the importing schema has no target namespace",
10905 NULL);
10906 return (pctxt->err);
10910 * Locate and acquire the schema document.
10912 if (schemaLocation != NULL)
10913 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10914 schemaLocation, node);
10915 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10916 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10917 namespaceName, &bucket);
10919 if (ret != 0)
10920 return(ret);
10923 * For <import>: "It is *not* an error for the application
10924 * schema reference strategy to fail."
10925 * So just don't parse if no schema document was found.
10926 * Note that we will get no bucket if the schema could not be
10927 * located or if there was no schemaLocation.
10929 if ((bucket == NULL) && (schemaLocation != NULL)) {
10930 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10931 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10932 node, NULL,
10933 "Failed to locate a schema at location '%s'. "
10934 "Skipping the import", schemaLocation, NULL, NULL);
10937 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10938 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10941 return (ret);
10944 static int
10945 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10946 xmlSchemaPtr schema,
10947 xmlNodePtr node,
10948 xmlChar **schemaLocation,
10949 int type)
10951 xmlAttrPtr attr;
10953 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10954 (schemaLocation == NULL))
10955 return (-1);
10957 *schemaLocation = NULL;
10959 * Check for illegal attributes.
10960 * Applies for both <include> and <redefine>.
10962 attr = node->properties;
10963 while (attr != NULL) {
10964 if (attr->ns == NULL) {
10965 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10966 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10967 xmlSchemaPIllegalAttrErr(pctxt,
10968 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10970 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10971 xmlSchemaPIllegalAttrErr(pctxt,
10972 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10974 attr = attr->next;
10976 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10978 * Preliminary step, extract the URI-Reference and make an URI
10979 * from the base.
10982 * Attribute "schemaLocation" is mandatory.
10984 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10985 if (attr != NULL) {
10986 xmlChar *base = NULL;
10987 xmlChar *uri = NULL;
10989 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10990 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10991 (const xmlChar **) schemaLocation) != 0)
10992 goto exit_error;
10993 base = xmlNodeGetBase(node->doc, node);
10994 if (base == NULL) {
10995 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10996 } else {
10997 uri = xmlBuildURI(*schemaLocation, base);
10998 xmlFree(base);
11000 if (uri == NULL) {
11001 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
11002 "could not build an URI from the schemaLocation")
11003 goto exit_failure;
11005 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
11006 xmlFree(uri);
11007 } else {
11008 xmlSchemaPMissingAttrErr(pctxt,
11009 XML_SCHEMAP_S4S_ATTR_MISSING,
11010 NULL, node, "schemaLocation", NULL);
11011 goto exit_error;
11014 * Report self-inclusion and self-redefinition.
11016 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
11017 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11018 xmlSchemaPCustomErr(pctxt,
11019 XML_SCHEMAP_SRC_REDEFINE,
11020 NULL, node,
11021 "The schema document '%s' cannot redefine itself.",
11022 *schemaLocation);
11023 } else {
11024 xmlSchemaPCustomErr(pctxt,
11025 XML_SCHEMAP_SRC_INCLUDE,
11026 NULL, node,
11027 "The schema document '%s' cannot include itself.",
11028 *schemaLocation);
11030 goto exit_error;
11033 return(0);
11034 exit_error:
11035 return(pctxt->err);
11036 exit_failure:
11037 return(-1);
11040 static int
11041 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
11042 xmlSchemaPtr schema,
11043 xmlNodePtr node,
11044 int type)
11046 xmlNodePtr child = NULL;
11047 const xmlChar *schemaLocation = NULL;
11048 int res = 0; /* hasRedefinitions = 0 */
11049 int isChameleon = 0, wasChameleon = 0;
11050 xmlSchemaBucketPtr bucket = NULL;
11052 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
11053 return (-1);
11056 * Parse attributes. Note that the returned schemaLocation will
11057 * be already converted to an absolute URI.
11059 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
11060 node, (xmlChar **) (&schemaLocation), type);
11061 if (res != 0)
11062 return(res);
11064 * Load and add the schema document.
11066 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
11067 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
11068 if (res != 0)
11069 return(res);
11071 * If we get no schema bucket back, then this means that the schema
11072 * document could not be located or was broken XML or was not
11073 * a schema document.
11075 if ((bucket == NULL) || (bucket->doc == NULL)) {
11076 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
11078 * WARNING for <include>:
11079 * We will raise an error if the schema cannot be located
11080 * for inclusions, since the that was the feedback from the
11081 * schema people. I.e. the following spec piece will *not* be
11082 * satisfied:
11083 * SPEC src-include: "It is not an error for the `actual value` of the
11084 * schemaLocation [attribute] to fail to resolve it all, in which
11085 * case no corresponding inclusion is performed.
11086 * So do we need a warning report here?"
11088 res = XML_SCHEMAP_SRC_INCLUDE;
11089 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11090 node, NULL,
11091 "Failed to load the document '%s' for inclusion",
11092 schemaLocation, NULL);
11093 } else {
11095 * NOTE: This was changed to raise an error even if no redefinitions
11096 * are specified.
11098 * SPEC src-redefine (1)
11099 * "If there are any element information items among the [children]
11100 * other than <annotation> then the `actual value` of the
11101 * schemaLocation [attribute] must successfully resolve."
11102 * TODO: Ask the WG if a the location has always to resolve
11103 * here as well!
11105 res = XML_SCHEMAP_SRC_REDEFINE;
11106 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11107 node, NULL,
11108 "Failed to load the document '%s' for redefinition",
11109 schemaLocation, NULL);
11111 } else {
11113 * Check targetNamespace sanity before parsing the new schema.
11114 * TODO: Note that we won't check further content if the
11115 * targetNamespace was bad.
11117 if (bucket->origTargetNamespace != NULL) {
11119 * SPEC src-include (2.1)
11120 * "SII has a targetNamespace [attribute], and its `actual
11121 * value` is identical to the `actual value` of the targetNamespace
11122 * [attribute] of SII' (which must have such an [attribute])."
11124 if (pctxt->targetNamespace == NULL) {
11125 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11126 XML_SCHEMAP_SRC_INCLUDE,
11127 node, NULL,
11128 "The target namespace of the included/redefined schema "
11129 "'%s' has to be absent, since the including/redefining "
11130 "schema has no target namespace",
11131 schemaLocation, NULL);
11132 goto exit_error;
11133 } else if (!xmlStrEqual(bucket->origTargetNamespace,
11134 pctxt->targetNamespace)) {
11135 /* TODO: Change error function. */
11136 xmlSchemaPCustomErrExt(pctxt,
11137 XML_SCHEMAP_SRC_INCLUDE,
11138 NULL, node,
11139 "The target namespace '%s' of the included/redefined "
11140 "schema '%s' differs from '%s' of the "
11141 "including/redefining schema",
11142 bucket->origTargetNamespace, schemaLocation,
11143 pctxt->targetNamespace);
11144 goto exit_error;
11146 } else if (pctxt->targetNamespace != NULL) {
11148 * Chameleons: the original target namespace will
11149 * differ from the resulting namespace.
11151 isChameleon = 1;
11152 if (bucket->parsed &&
11153 bucket->origTargetNamespace != NULL) {
11154 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11155 XML_SCHEMAP_SRC_INCLUDE,
11156 node, NULL,
11157 "The target namespace of the included/redefined schema "
11158 "'%s' has to be absent or the same as the "
11159 "including/redefining schema's target namespace",
11160 schemaLocation, NULL);
11161 goto exit_error;
11163 bucket->targetNamespace = pctxt->targetNamespace;
11167 * Parse the schema.
11169 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11170 if (isChameleon) {
11171 /* TODO: Get rid of this flag on the schema itself. */
11172 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11173 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11174 } else
11175 wasChameleon = 1;
11177 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11178 /* Restore chameleon flag. */
11179 if (isChameleon && (!wasChameleon))
11180 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11183 * And now for the children...
11185 child = node->children;
11186 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11188 * Parse (simpleType | complexType | group | attributeGroup))*
11190 pctxt->redefined = bucket;
11192 * How to proceed if the redefined schema was not located?
11194 pctxt->isRedefine = 1;
11195 while (IS_SCHEMA(child, "annotation") ||
11196 IS_SCHEMA(child, "simpleType") ||
11197 IS_SCHEMA(child, "complexType") ||
11198 IS_SCHEMA(child, "group") ||
11199 IS_SCHEMA(child, "attributeGroup")) {
11200 if (IS_SCHEMA(child, "annotation")) {
11202 * TODO: discard or not?
11204 } else if (IS_SCHEMA(child, "simpleType")) {
11205 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11206 } else if (IS_SCHEMA(child, "complexType")) {
11207 xmlSchemaParseComplexType(pctxt, schema, child, 1);
11208 /* hasRedefinitions = 1; */
11209 } else if (IS_SCHEMA(child, "group")) {
11210 /* hasRedefinitions = 1; */
11211 xmlSchemaParseModelGroupDefinition(pctxt,
11212 schema, child);
11213 } else if (IS_SCHEMA(child, "attributeGroup")) {
11214 /* hasRedefinitions = 1; */
11215 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11216 child);
11218 child = child->next;
11220 pctxt->redefined = NULL;
11221 pctxt->isRedefine = 0;
11222 } else {
11223 if (IS_SCHEMA(child, "annotation")) {
11225 * TODO: discard or not?
11227 child = child->next;
11230 if (child != NULL) {
11231 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11232 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11233 xmlSchemaPContentErr(pctxt, res,
11234 NULL, node, child, NULL,
11235 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11236 } else {
11237 xmlSchemaPContentErr(pctxt, res,
11238 NULL, node, child, NULL,
11239 "(annotation?)");
11242 return(res);
11244 exit_error:
11245 return(pctxt->err);
11248 static int
11249 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11250 xmlNodePtr node)
11252 int res;
11253 #ifndef ENABLE_REDEFINE
11254 TODO
11255 return(0);
11256 #endif
11257 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11258 XML_SCHEMA_SCHEMA_REDEFINE);
11259 if (res != 0)
11260 return(res);
11261 return(0);
11264 static int
11265 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11266 xmlNodePtr node)
11268 int res;
11270 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11271 XML_SCHEMA_SCHEMA_INCLUDE);
11272 if (res != 0)
11273 return(res);
11274 return(0);
11278 * xmlSchemaParseModelGroup:
11279 * @ctxt: a schema validation context
11280 * @schema: the schema being built
11281 * @node: a subtree containing XML Schema information
11282 * @type: the "compositor" type
11283 * @particleNeeded: if a a model group with a particle
11285 * parse a XML schema Sequence definition.
11286 * Applies parts of:
11287 * Schema Representation Constraint:
11288 * Redefinition Constraints and Semantics (src-redefine)
11289 * (6.1), (6.1.1), (6.1.2)
11291 * Schema Component Constraint:
11292 * All Group Limited (cos-all-limited) (2)
11293 * TODO: Actually this should go to component-level checks,
11294 * but is done here due to performance. Move it to an other layer
11295 * is schema construction via an API is implemented.
11297 * *WARNING* this interface is highly subject to change
11299 * Returns -1 in case of error, 0 if the declaration is improper and
11300 * 1 in case of success.
11302 static xmlSchemaTreeItemPtr
11303 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11304 xmlNodePtr node, xmlSchemaTypeType type,
11305 int withParticle)
11307 xmlSchemaModelGroupPtr item;
11308 xmlSchemaParticlePtr particle = NULL;
11309 xmlNodePtr child = NULL;
11310 xmlAttrPtr attr;
11311 int min = 1, max = 1, isElemRef, hasRefs = 0;
11313 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11314 return (NULL);
11316 * Create a model group with the given compositor.
11318 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11319 if (item == NULL)
11320 return (NULL);
11322 if (withParticle) {
11323 if (type == XML_SCHEMA_TYPE_ALL) {
11324 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11325 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11326 } else {
11327 /* choice + sequence */
11328 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11329 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11330 "(xs:nonNegativeInteger | unbounded)");
11332 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11334 * Create a particle
11336 particle = xmlSchemaAddParticle(ctxt, node, min, max);
11337 if (particle == NULL)
11338 return (NULL);
11339 particle->children = (xmlSchemaTreeItemPtr) item;
11341 * Check for illegal attributes.
11343 attr = node->properties;
11344 while (attr != NULL) {
11345 if (attr->ns == NULL) {
11346 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11347 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11348 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11349 xmlSchemaPIllegalAttrErr(ctxt,
11350 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11352 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11353 xmlSchemaPIllegalAttrErr(ctxt,
11354 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11356 attr = attr->next;
11358 } else {
11360 * Check for illegal attributes.
11362 attr = node->properties;
11363 while (attr != NULL) {
11364 if (attr->ns == NULL) {
11365 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11366 xmlSchemaPIllegalAttrErr(ctxt,
11367 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11369 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11370 xmlSchemaPIllegalAttrErr(ctxt,
11371 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11373 attr = attr->next;
11378 * Extract and validate attributes.
11380 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11382 * And now for the children...
11384 child = node->children;
11385 if (IS_SCHEMA(child, "annotation")) {
11386 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11387 child = child->next;
11389 if (type == XML_SCHEMA_TYPE_ALL) {
11390 xmlSchemaParticlePtr part, last = NULL;
11392 while (IS_SCHEMA(child, "element")) {
11393 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11394 schema, child, &isElemRef, 0);
11396 * SPEC cos-all-limited (2)
11397 * "The {max occurs} of all the particles in the {particles}
11398 * of the ('all') group must be 0 or 1.
11400 if (part != NULL) {
11401 if (isElemRef)
11402 hasRefs++;
11403 if (part->minOccurs > 1) {
11404 xmlSchemaPCustomErr(ctxt,
11405 XML_SCHEMAP_COS_ALL_LIMITED,
11406 NULL, child,
11407 "Invalid value for minOccurs (must be 0 or 1)",
11408 NULL);
11409 /* Reset to 1. */
11410 part->minOccurs = 1;
11412 if (part->maxOccurs > 1) {
11413 xmlSchemaPCustomErr(ctxt,
11414 XML_SCHEMAP_COS_ALL_LIMITED,
11415 NULL, child,
11416 "Invalid value for maxOccurs (must be 0 or 1)",
11417 NULL);
11418 /* Reset to 1. */
11419 part->maxOccurs = 1;
11421 if (last == NULL)
11422 item->children = (xmlSchemaTreeItemPtr) part;
11423 else
11424 last->next = (xmlSchemaTreeItemPtr) part;
11425 last = part;
11427 child = child->next;
11429 if (child != NULL) {
11430 xmlSchemaPContentErr(ctxt,
11431 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11432 NULL, node, child, NULL,
11433 "(annotation?, (annotation?, element*)");
11435 } else {
11436 /* choice + sequence */
11437 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11439 while ((IS_SCHEMA(child, "element")) ||
11440 (IS_SCHEMA(child, "group")) ||
11441 (IS_SCHEMA(child, "any")) ||
11442 (IS_SCHEMA(child, "choice")) ||
11443 (IS_SCHEMA(child, "sequence"))) {
11445 if (IS_SCHEMA(child, "element")) {
11446 part = (xmlSchemaTreeItemPtr)
11447 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11448 if (part && isElemRef)
11449 hasRefs++;
11450 } else if (IS_SCHEMA(child, "group")) {
11451 part =
11452 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11453 if (part != NULL)
11454 hasRefs++;
11456 * Handle redefinitions.
11458 if (ctxt->isRedefine && ctxt->redef &&
11459 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11460 part && part->children)
11462 if ((xmlSchemaGetQNameRefName(part->children) ==
11463 ctxt->redef->refName) &&
11464 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11465 ctxt->redef->refTargetNs))
11468 * SPEC src-redefine:
11469 * (6.1) "If it has a <group> among its contents at
11470 * some level the `actual value` of whose ref
11471 * [attribute] is the same as the `actual value` of
11472 * its own name attribute plus target namespace, then
11473 * all of the following must be true:"
11474 * (6.1.1) "It must have exactly one such group."
11476 if (ctxt->redefCounter != 0) {
11477 xmlChar *str = NULL;
11479 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11480 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11481 "The redefining model group definition "
11482 "'%s' must not contain more than one "
11483 "reference to the redefined definition",
11484 xmlSchemaFormatQName(&str,
11485 ctxt->redef->refTargetNs,
11486 ctxt->redef->refName),
11487 NULL);
11488 FREE_AND_NULL(str)
11489 part = NULL;
11490 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11491 ((WXS_PARTICLE(part))->maxOccurs != 1))
11493 xmlChar *str = NULL;
11495 * SPEC src-redefine:
11496 * (6.1.2) "The `actual value` of both that
11497 * group's minOccurs and maxOccurs [attribute]
11498 * must be 1 (or `absent`).
11500 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11501 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11502 "The redefining model group definition "
11503 "'%s' must not contain a reference to the "
11504 "redefined definition with a "
11505 "maxOccurs/minOccurs other than 1",
11506 xmlSchemaFormatQName(&str,
11507 ctxt->redef->refTargetNs,
11508 ctxt->redef->refName),
11509 NULL);
11510 FREE_AND_NULL(str)
11511 part = NULL;
11513 ctxt->redef->reference = WXS_BASIC_CAST part;
11514 ctxt->redefCounter++;
11517 } else if (IS_SCHEMA(child, "any")) {
11518 part = (xmlSchemaTreeItemPtr)
11519 xmlSchemaParseAny(ctxt, schema, child);
11520 } else if (IS_SCHEMA(child, "choice")) {
11521 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11522 XML_SCHEMA_TYPE_CHOICE, 1);
11523 } else if (IS_SCHEMA(child, "sequence")) {
11524 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11525 XML_SCHEMA_TYPE_SEQUENCE, 1);
11527 if (part != NULL) {
11528 if (last == NULL)
11529 item->children = part;
11530 else
11531 last->next = part;
11532 last = part;
11534 child = child->next;
11536 if (child != NULL) {
11537 xmlSchemaPContentErr(ctxt,
11538 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11539 NULL, node, child, NULL,
11540 "(annotation?, (element | group | choice | sequence | any)*)");
11543 if ((max == 0) && (min == 0))
11544 return (NULL);
11545 if (hasRefs) {
11547 * We need to resolve references.
11549 WXS_ADD_PENDING(ctxt, item);
11551 if (withParticle)
11552 return ((xmlSchemaTreeItemPtr) particle);
11553 else
11554 return ((xmlSchemaTreeItemPtr) item);
11558 * xmlSchemaParseRestriction:
11559 * @ctxt: a schema validation context
11560 * @schema: the schema being built
11561 * @node: a subtree containing XML Schema information
11563 * parse a XML schema Restriction definition
11564 * *WARNING* this interface is highly subject to change
11566 * Returns the type definition or NULL in case of error
11568 static xmlSchemaTypePtr
11569 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11570 xmlNodePtr node, xmlSchemaTypeType parentType)
11572 xmlSchemaTypePtr type;
11573 xmlNodePtr child = NULL;
11574 xmlAttrPtr attr;
11576 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11577 return (NULL);
11578 /* Not a component, don't create it. */
11579 type = ctxt->ctxtType;
11580 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11583 * Check for illegal attributes.
11585 attr = node->properties;
11586 while (attr != NULL) {
11587 if (attr->ns == NULL) {
11588 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11589 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11590 xmlSchemaPIllegalAttrErr(ctxt,
11591 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11593 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11594 xmlSchemaPIllegalAttrErr(ctxt,
11595 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11597 attr = attr->next;
11600 * Extract and validate attributes.
11602 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11604 * Attribute
11607 * Extract the base type. The "base" attribute is mandatory if inside
11608 * a complex type or if redefining.
11610 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11611 * among its [children]), the simple type definition which is
11612 * the {content type} of the type definition `resolved` to by
11613 * the `actual value` of the base [attribute]"
11615 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11616 &(type->baseNs), &(type->base)) == 0)
11618 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11619 xmlSchemaPMissingAttrErr(ctxt,
11620 XML_SCHEMAP_S4S_ATTR_MISSING,
11621 NULL, node, "base", NULL);
11622 } else if ((ctxt->isRedefine) &&
11623 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11625 if (type->base == NULL) {
11626 xmlSchemaPMissingAttrErr(ctxt,
11627 XML_SCHEMAP_S4S_ATTR_MISSING,
11628 NULL, node, "base", NULL);
11629 } else if ((! xmlStrEqual(type->base, type->name)) ||
11630 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11632 xmlChar *str1 = NULL, *str2 = NULL;
11634 * REDEFINE: SPEC src-redefine (5)
11635 * "Within the [children], each <simpleType> must have a
11636 * <restriction> among its [children] ... the `actual value` of
11637 * whose base [attribute] must be the same as the `actual value`
11638 * of its own name attribute plus target namespace;"
11640 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11641 NULL, node, "This is a redefinition, but the QName "
11642 "value '%s' of the 'base' attribute does not match the "
11643 "type's designation '%s'",
11644 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11645 xmlSchemaFormatQName(&str2, type->targetNamespace,
11646 type->name), NULL);
11647 FREE_AND_NULL(str1);
11648 FREE_AND_NULL(str2);
11649 /* Avoid confusion and erase the values. */
11650 type->base = NULL;
11651 type->baseNs = NULL;
11656 * And now for the children...
11658 child = node->children;
11659 if (IS_SCHEMA(child, "annotation")) {
11661 * Add the annotation to the simple type ancestor.
11663 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11664 xmlSchemaParseAnnotation(ctxt, child, 1));
11665 child = child->next;
11667 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11669 * Corresponds to <simpleType><restriction><simpleType>.
11671 if (IS_SCHEMA(child, "simpleType")) {
11672 if (type->base != NULL) {
11674 * src-restriction-base-or-simpleType
11675 * Either the base [attribute] or the simpleType [child] of the
11676 * <restriction> element must be present, but not both.
11678 xmlSchemaPContentErr(ctxt,
11679 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11680 NULL, node, child,
11681 "The attribute 'base' and the <simpleType> child are "
11682 "mutually exclusive", NULL);
11683 } else {
11684 type->baseType = (xmlSchemaTypePtr)
11685 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11687 child = child->next;
11688 } else if (type->base == NULL) {
11689 xmlSchemaPContentErr(ctxt,
11690 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11691 NULL, node, child,
11692 "Either the attribute 'base' or a <simpleType> child "
11693 "must be present", NULL);
11695 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11697 * Corresponds to <complexType><complexContent><restriction>...
11698 * followed by:
11700 * Model groups <all>, <choice> and <sequence>.
11702 if (IS_SCHEMA(child, "all")) {
11703 type->subtypes = (xmlSchemaTypePtr)
11704 xmlSchemaParseModelGroup(ctxt, schema, child,
11705 XML_SCHEMA_TYPE_ALL, 1);
11706 child = child->next;
11707 } else if (IS_SCHEMA(child, "choice")) {
11708 type->subtypes = (xmlSchemaTypePtr)
11709 xmlSchemaParseModelGroup(ctxt,
11710 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11711 child = child->next;
11712 } else if (IS_SCHEMA(child, "sequence")) {
11713 type->subtypes = (xmlSchemaTypePtr)
11714 xmlSchemaParseModelGroup(ctxt, schema, child,
11715 XML_SCHEMA_TYPE_SEQUENCE, 1);
11716 child = child->next;
11718 * Model group reference <group>.
11720 } else if (IS_SCHEMA(child, "group")) {
11721 type->subtypes = (xmlSchemaTypePtr)
11722 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11724 * Note that the reference will be resolved in
11725 * xmlSchemaResolveTypeReferences();
11727 child = child->next;
11729 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11731 * Corresponds to <complexType><simpleContent><restriction>...
11733 * "1.1 the simple type definition corresponding to the <simpleType>
11734 * among the [children] of <restriction> if there is one;"
11736 if (IS_SCHEMA(child, "simpleType")) {
11738 * We will store the to-be-restricted simple type in
11739 * type->contentTypeDef *temporarily*.
11741 type->contentTypeDef = (xmlSchemaTypePtr)
11742 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11743 if ( type->contentTypeDef == NULL)
11744 return (NULL);
11745 child = child->next;
11749 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11750 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11751 xmlSchemaFacetPtr facet, lastfacet = NULL;
11753 * Corresponds to <complexType><simpleContent><restriction>...
11754 * <simpleType><restriction>...
11758 * Add the facets to the simple type ancestor.
11761 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11762 * Simple Type Definition Schema Representation Constraint:
11763 * *Single Facet Value*
11765 while ((IS_SCHEMA(child, "minInclusive")) ||
11766 (IS_SCHEMA(child, "minExclusive")) ||
11767 (IS_SCHEMA(child, "maxInclusive")) ||
11768 (IS_SCHEMA(child, "maxExclusive")) ||
11769 (IS_SCHEMA(child, "totalDigits")) ||
11770 (IS_SCHEMA(child, "fractionDigits")) ||
11771 (IS_SCHEMA(child, "pattern")) ||
11772 (IS_SCHEMA(child, "enumeration")) ||
11773 (IS_SCHEMA(child, "whiteSpace")) ||
11774 (IS_SCHEMA(child, "length")) ||
11775 (IS_SCHEMA(child, "maxLength")) ||
11776 (IS_SCHEMA(child, "minLength"))) {
11777 facet = xmlSchemaParseFacet(ctxt, schema, child);
11778 if (facet != NULL) {
11779 if (lastfacet == NULL)
11780 type->facets = facet;
11781 else
11782 lastfacet->next = facet;
11783 lastfacet = facet;
11784 lastfacet->next = NULL;
11786 child = child->next;
11789 * Create links for derivation and validation.
11791 if (type->facets != NULL) {
11792 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11794 facet = type->facets;
11795 do {
11796 facetLink = (xmlSchemaFacetLinkPtr)
11797 xmlMalloc(sizeof(xmlSchemaFacetLink));
11798 if (facetLink == NULL) {
11799 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11800 xmlFree(facetLink);
11801 return (NULL);
11803 facetLink->facet = facet;
11804 facetLink->next = NULL;
11805 if (lastFacetLink == NULL)
11806 type->facetSet = facetLink;
11807 else
11808 lastFacetLink->next = facetLink;
11809 lastFacetLink = facetLink;
11810 facet = facet->next;
11811 } while (facet != NULL);
11814 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11816 * Attribute uses/declarations.
11818 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11819 (xmlSchemaItemListPtr *) &(type->attrUses),
11820 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11821 return(NULL);
11823 * Attribute wildcard.
11825 if (IS_SCHEMA(child, "anyAttribute")) {
11826 type->attributeWildcard =
11827 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11828 child = child->next;
11831 if (child != NULL) {
11832 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11833 xmlSchemaPContentErr(ctxt,
11834 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11835 NULL, node, child, NULL,
11836 "annotation?, (group | all | choice | sequence)?, "
11837 "((attribute | attributeGroup)*, anyAttribute?))");
11838 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11839 xmlSchemaPContentErr(ctxt,
11840 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11841 NULL, node, child, NULL,
11842 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11843 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11844 "length | minLength | maxLength | enumeration | whiteSpace | "
11845 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11846 } else {
11847 /* Simple type */
11848 xmlSchemaPContentErr(ctxt,
11849 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11850 NULL, node, child, NULL,
11851 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11852 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11853 "length | minLength | maxLength | enumeration | whiteSpace | "
11854 "pattern)*))");
11857 return (NULL);
11861 * xmlSchemaParseExtension:
11862 * @ctxt: a schema validation context
11863 * @schema: the schema being built
11864 * @node: a subtree containing XML Schema information
11866 * Parses an <extension>, which is found inside a
11867 * <simpleContent> or <complexContent>.
11868 * *WARNING* this interface is highly subject to change.
11870 * TODO: Returns the type definition or NULL in case of error
11872 static xmlSchemaTypePtr
11873 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11874 xmlNodePtr node, xmlSchemaTypeType parentType)
11876 xmlSchemaTypePtr type;
11877 xmlNodePtr child = NULL;
11878 xmlAttrPtr attr;
11880 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11881 return (NULL);
11882 /* Not a component, don't create it. */
11883 type = ctxt->ctxtType;
11884 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11887 * Check for illegal attributes.
11889 attr = node->properties;
11890 while (attr != NULL) {
11891 if (attr->ns == NULL) {
11892 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11893 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11894 xmlSchemaPIllegalAttrErr(ctxt,
11895 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11897 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11898 xmlSchemaPIllegalAttrErr(ctxt,
11899 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11901 attr = attr->next;
11904 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11907 * Attribute "base" - mandatory.
11909 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11910 "base", &(type->baseNs), &(type->base)) == 0) &&
11911 (type->base == NULL)) {
11912 xmlSchemaPMissingAttrErr(ctxt,
11913 XML_SCHEMAP_S4S_ATTR_MISSING,
11914 NULL, node, "base", NULL);
11917 * And now for the children...
11919 child = node->children;
11920 if (IS_SCHEMA(child, "annotation")) {
11922 * Add the annotation to the type ancestor.
11924 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11925 xmlSchemaParseAnnotation(ctxt, child, 1));
11926 child = child->next;
11928 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11930 * Corresponds to <complexType><complexContent><extension>... and:
11932 * Model groups <all>, <choice>, <sequence> and <group>.
11934 if (IS_SCHEMA(child, "all")) {
11935 type->subtypes = (xmlSchemaTypePtr)
11936 xmlSchemaParseModelGroup(ctxt, schema,
11937 child, XML_SCHEMA_TYPE_ALL, 1);
11938 child = child->next;
11939 } else if (IS_SCHEMA(child, "choice")) {
11940 type->subtypes = (xmlSchemaTypePtr)
11941 xmlSchemaParseModelGroup(ctxt, schema,
11942 child, XML_SCHEMA_TYPE_CHOICE, 1);
11943 child = child->next;
11944 } else if (IS_SCHEMA(child, "sequence")) {
11945 type->subtypes = (xmlSchemaTypePtr)
11946 xmlSchemaParseModelGroup(ctxt, schema,
11947 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11948 child = child->next;
11949 } else if (IS_SCHEMA(child, "group")) {
11950 type->subtypes = (xmlSchemaTypePtr)
11951 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11953 * Note that the reference will be resolved in
11954 * xmlSchemaResolveTypeReferences();
11956 child = child->next;
11959 if (child != NULL) {
11961 * Attribute uses/declarations.
11963 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11964 (xmlSchemaItemListPtr *) &(type->attrUses),
11965 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11966 return(NULL);
11968 * Attribute wildcard.
11970 if (IS_SCHEMA(child, "anyAttribute")) {
11971 ctxt->ctxtType->attributeWildcard =
11972 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11973 child = child->next;
11976 if (child != NULL) {
11977 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11978 /* Complex content extension. */
11979 xmlSchemaPContentErr(ctxt,
11980 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11981 NULL, node, child, NULL,
11982 "(annotation?, ((group | all | choice | sequence)?, "
11983 "((attribute | attributeGroup)*, anyAttribute?)))");
11984 } else {
11985 /* Simple content extension. */
11986 xmlSchemaPContentErr(ctxt,
11987 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11988 NULL, node, child, NULL,
11989 "(annotation?, ((attribute | attributeGroup)*, "
11990 "anyAttribute?))");
11993 return (NULL);
11997 * xmlSchemaParseSimpleContent:
11998 * @ctxt: a schema validation context
11999 * @schema: the schema being built
12000 * @node: a subtree containing XML Schema information
12002 * parse a XML schema SimpleContent definition
12003 * *WARNING* this interface is highly subject to change
12005 * Returns the type definition or NULL in case of error
12007 static int
12008 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
12009 xmlSchemaPtr schema, xmlNodePtr node,
12010 int *hasRestrictionOrExtension)
12012 xmlSchemaTypePtr type;
12013 xmlNodePtr child = NULL;
12014 xmlAttrPtr attr;
12016 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12017 (hasRestrictionOrExtension == NULL))
12018 return (-1);
12019 *hasRestrictionOrExtension = 0;
12020 /* Not a component, don't create it. */
12021 type = ctxt->ctxtType;
12022 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12024 * Check for illegal attributes.
12026 attr = node->properties;
12027 while (attr != NULL) {
12028 if (attr->ns == NULL) {
12029 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
12030 xmlSchemaPIllegalAttrErr(ctxt,
12031 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12033 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12034 xmlSchemaPIllegalAttrErr(ctxt,
12035 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12037 attr = attr->next;
12040 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12043 * And now for the children...
12045 child = node->children;
12046 if (IS_SCHEMA(child, "annotation")) {
12048 * Add the annotation to the complex type ancestor.
12050 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12051 xmlSchemaParseAnnotation(ctxt, child, 1));
12052 child = child->next;
12054 if (child == NULL) {
12055 xmlSchemaPContentErr(ctxt,
12056 XML_SCHEMAP_S4S_ELEM_MISSING,
12057 NULL, node, NULL, NULL,
12058 "(annotation?, (restriction | extension))");
12060 if (child == NULL) {
12061 xmlSchemaPContentErr(ctxt,
12062 XML_SCHEMAP_S4S_ELEM_MISSING,
12063 NULL, node, NULL, NULL,
12064 "(annotation?, (restriction | extension))");
12066 if (IS_SCHEMA(child, "restriction")) {
12067 xmlSchemaParseRestriction(ctxt, schema, child,
12068 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12069 (*hasRestrictionOrExtension) = 1;
12070 child = child->next;
12071 } else if (IS_SCHEMA(child, "extension")) {
12072 xmlSchemaParseExtension(ctxt, schema, child,
12073 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12074 (*hasRestrictionOrExtension) = 1;
12075 child = child->next;
12077 if (child != NULL) {
12078 xmlSchemaPContentErr(ctxt,
12079 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12080 NULL, node, child, NULL,
12081 "(annotation?, (restriction | extension))");
12083 return (0);
12087 * xmlSchemaParseComplexContent:
12088 * @ctxt: a schema validation context
12089 * @schema: the schema being built
12090 * @node: a subtree containing XML Schema information
12092 * parse a XML schema ComplexContent definition
12093 * *WARNING* this interface is highly subject to change
12095 * Returns the type definition or NULL in case of error
12097 static int
12098 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12099 xmlSchemaPtr schema, xmlNodePtr node,
12100 int *hasRestrictionOrExtension)
12102 xmlSchemaTypePtr type;
12103 xmlNodePtr child = NULL;
12104 xmlAttrPtr attr;
12106 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12107 (hasRestrictionOrExtension == NULL))
12108 return (-1);
12109 *hasRestrictionOrExtension = 0;
12110 /* Not a component, don't create it. */
12111 type = ctxt->ctxtType;
12113 * Check for illegal attributes.
12115 attr = node->properties;
12116 while (attr != NULL) {
12117 if (attr->ns == NULL) {
12118 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12119 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12121 xmlSchemaPIllegalAttrErr(ctxt,
12122 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12124 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12125 xmlSchemaPIllegalAttrErr(ctxt,
12126 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12128 attr = attr->next;
12131 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12134 * Set the 'mixed' on the complex type ancestor.
12136 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
12137 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12138 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12140 child = node->children;
12141 if (IS_SCHEMA(child, "annotation")) {
12143 * Add the annotation to the complex type ancestor.
12145 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12146 xmlSchemaParseAnnotation(ctxt, child, 1));
12147 child = child->next;
12149 if (child == NULL) {
12150 xmlSchemaPContentErr(ctxt,
12151 XML_SCHEMAP_S4S_ELEM_MISSING,
12152 NULL, node, NULL,
12153 NULL, "(annotation?, (restriction | extension))");
12155 if (child == NULL) {
12156 xmlSchemaPContentErr(ctxt,
12157 XML_SCHEMAP_S4S_ELEM_MISSING,
12158 NULL, node, NULL,
12159 NULL, "(annotation?, (restriction | extension))");
12161 if (IS_SCHEMA(child, "restriction")) {
12162 xmlSchemaParseRestriction(ctxt, schema, child,
12163 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12164 (*hasRestrictionOrExtension) = 1;
12165 child = child->next;
12166 } else if (IS_SCHEMA(child, "extension")) {
12167 xmlSchemaParseExtension(ctxt, schema, child,
12168 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12169 (*hasRestrictionOrExtension) = 1;
12170 child = child->next;
12172 if (child != NULL) {
12173 xmlSchemaPContentErr(ctxt,
12174 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12175 NULL, node, child,
12176 NULL, "(annotation?, (restriction | extension))");
12178 return (0);
12182 * xmlSchemaParseComplexType:
12183 * @ctxt: a schema validation context
12184 * @schema: the schema being built
12185 * @node: a subtree containing XML Schema information
12187 * parse a XML schema Complex Type definition
12188 * *WARNING* this interface is highly subject to change
12190 * Returns the type definition or NULL in case of error
12192 static xmlSchemaTypePtr
12193 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12194 xmlNodePtr node, int topLevel)
12196 xmlSchemaTypePtr type, ctxtType;
12197 xmlNodePtr child = NULL;
12198 const xmlChar *name = NULL;
12199 xmlAttrPtr attr;
12200 const xmlChar *attrValue;
12201 #ifdef ENABLE_NAMED_LOCALS
12202 char buf[40];
12203 #endif
12204 int final = 0, block = 0, hasRestrictionOrExtension = 0;
12207 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12208 return (NULL);
12210 ctxtType = ctxt->ctxtType;
12212 if (topLevel) {
12213 attr = xmlSchemaGetPropNode(node, "name");
12214 if (attr == NULL) {
12215 xmlSchemaPMissingAttrErr(ctxt,
12216 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12217 return (NULL);
12218 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12219 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12220 return (NULL);
12224 if (topLevel == 0) {
12226 * Parse as local complex type definition.
12228 #ifdef ENABLE_NAMED_LOCALS
12229 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12230 type = xmlSchemaAddType(ctxt, schema,
12231 XML_SCHEMA_TYPE_COMPLEX,
12232 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12233 ctxt->targetNamespace, node, 0);
12234 #else
12235 type = xmlSchemaAddType(ctxt, schema,
12236 XML_SCHEMA_TYPE_COMPLEX,
12237 NULL, ctxt->targetNamespace, node, 0);
12238 #endif
12239 if (type == NULL)
12240 return (NULL);
12241 name = type->name;
12242 type->node = node;
12243 type->type = XML_SCHEMA_TYPE_COMPLEX;
12245 * TODO: We need the target namespace.
12247 } else {
12249 * Parse as global complex type definition.
12251 type = xmlSchemaAddType(ctxt, schema,
12252 XML_SCHEMA_TYPE_COMPLEX,
12253 name, ctxt->targetNamespace, node, 1);
12254 if (type == NULL)
12255 return (NULL);
12256 type->node = node;
12257 type->type = XML_SCHEMA_TYPE_COMPLEX;
12258 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12260 type->targetNamespace = ctxt->targetNamespace;
12262 * Handle attributes.
12264 attr = node->properties;
12265 while (attr != NULL) {
12266 if (attr->ns == NULL) {
12267 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12269 * Attribute "id".
12271 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12272 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12274 * Attribute "mixed".
12276 if (xmlSchemaPGetBoolNodeValue(ctxt,
12277 NULL, (xmlNodePtr) attr))
12278 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12279 } else if (topLevel) {
12281 * Attributes of global complex type definitions.
12283 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12284 /* Pass. */
12285 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12287 * Attribute "abstract".
12289 if (xmlSchemaPGetBoolNodeValue(ctxt,
12290 NULL, (xmlNodePtr) attr))
12291 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12292 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12294 * Attribute "final".
12296 attrValue = xmlSchemaGetNodeContent(ctxt,
12297 (xmlNodePtr) attr);
12298 if (xmlSchemaPValAttrBlockFinal(attrValue,
12299 &(type->flags),
12301 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12302 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12303 -1, -1, -1) != 0)
12305 xmlSchemaPSimpleTypeErr(ctxt,
12306 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12307 NULL, (xmlNodePtr) attr, NULL,
12308 "(#all | List of (extension | restriction))",
12309 attrValue, NULL, NULL, NULL);
12310 } else
12311 final = 1;
12312 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12314 * Attribute "block".
12316 attrValue = xmlSchemaGetNodeContent(ctxt,
12317 (xmlNodePtr) attr);
12318 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12320 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12321 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12322 -1, -1, -1) != 0) {
12323 xmlSchemaPSimpleTypeErr(ctxt,
12324 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12325 NULL, (xmlNodePtr) attr, NULL,
12326 "(#all | List of (extension | restriction)) ",
12327 attrValue, NULL, NULL, NULL);
12328 } else
12329 block = 1;
12330 } else {
12331 xmlSchemaPIllegalAttrErr(ctxt,
12332 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12334 } else {
12335 xmlSchemaPIllegalAttrErr(ctxt,
12336 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12338 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12339 xmlSchemaPIllegalAttrErr(ctxt,
12340 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12342 attr = attr->next;
12344 if (! block) {
12346 * Apply default "block" values.
12348 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12349 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12350 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12351 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12353 if (! final) {
12355 * Apply default "block" values.
12357 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12358 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12359 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12360 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12363 * And now for the children...
12365 child = node->children;
12366 if (IS_SCHEMA(child, "annotation")) {
12367 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12368 child = child->next;
12370 ctxt->ctxtType = type;
12371 if (IS_SCHEMA(child, "simpleContent")) {
12373 * <complexType><simpleContent>...
12374 * 3.4.3 : 2.2
12375 * Specifying mixed='true' when the <simpleContent>
12376 * alternative is chosen has no effect
12378 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12379 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12380 xmlSchemaParseSimpleContent(ctxt, schema, child,
12381 &hasRestrictionOrExtension);
12382 child = child->next;
12383 } else if (IS_SCHEMA(child, "complexContent")) {
12385 * <complexType><complexContent>...
12387 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12388 xmlSchemaParseComplexContent(ctxt, schema, child,
12389 &hasRestrictionOrExtension);
12390 child = child->next;
12391 } else {
12393 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12395 * SPEC
12396 * "...the third alternative (neither <simpleContent> nor
12397 * <complexContent>) is chosen. This case is understood as shorthand
12398 * for complex content restricting the `ur-type definition`, and the
12399 * details of the mappings should be modified as necessary.
12401 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12402 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12404 * Parse model groups.
12406 if (IS_SCHEMA(child, "all")) {
12407 type->subtypes = (xmlSchemaTypePtr)
12408 xmlSchemaParseModelGroup(ctxt, schema, child,
12409 XML_SCHEMA_TYPE_ALL, 1);
12410 child = child->next;
12411 } else if (IS_SCHEMA(child, "choice")) {
12412 type->subtypes = (xmlSchemaTypePtr)
12413 xmlSchemaParseModelGroup(ctxt, schema, child,
12414 XML_SCHEMA_TYPE_CHOICE, 1);
12415 child = child->next;
12416 } else if (IS_SCHEMA(child, "sequence")) {
12417 type->subtypes = (xmlSchemaTypePtr)
12418 xmlSchemaParseModelGroup(ctxt, schema, child,
12419 XML_SCHEMA_TYPE_SEQUENCE, 1);
12420 child = child->next;
12421 } else if (IS_SCHEMA(child, "group")) {
12422 type->subtypes = (xmlSchemaTypePtr)
12423 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12425 * Note that the reference will be resolved in
12426 * xmlSchemaResolveTypeReferences();
12428 child = child->next;
12431 * Parse attribute decls/refs.
12433 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12434 (xmlSchemaItemListPtr *) &(type->attrUses),
12435 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12436 return(NULL);
12438 * Parse attribute wildcard.
12440 if (IS_SCHEMA(child, "anyAttribute")) {
12441 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12442 child = child->next;
12445 if (child != NULL) {
12446 xmlSchemaPContentErr(ctxt,
12447 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12448 NULL, node, child,
12449 NULL, "(annotation?, (simpleContent | complexContent | "
12450 "((group | all | choice | sequence)?, ((attribute | "
12451 "attributeGroup)*, anyAttribute?))))");
12454 * REDEFINE: SPEC src-redefine (5)
12456 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12457 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12458 NULL, node, "This is a redefinition, thus the "
12459 "<complexType> must have a <restriction> or <extension> "
12460 "grand-child", NULL);
12462 ctxt->ctxtType = ctxtType;
12463 return (type);
12466 /************************************************************************
12468 * Validating using Schemas *
12470 ************************************************************************/
12472 /************************************************************************
12474 * Reading/Writing Schemas *
12476 ************************************************************************/
12478 #if 0 /* Will be enabled if it is clear what options are needed. */
12480 * xmlSchemaParserCtxtSetOptions:
12481 * @ctxt: a schema parser context
12482 * @options: a combination of xmlSchemaParserOption
12484 * Sets the options to be used during the parse.
12486 * Returns 0 in case of success, -1 in case of an
12487 * API error.
12489 static int
12490 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12491 int options)
12494 int i;
12496 if (ctxt == NULL)
12497 return (-1);
12499 * WARNING: Change the start value if adding to the
12500 * xmlSchemaParseOption.
12502 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12503 if (options & 1<<i) {
12504 return (-1);
12507 ctxt->options = options;
12508 return (0);
12512 * xmlSchemaValidCtxtGetOptions:
12513 * @ctxt: a schema parser context
12515 * Returns the option combination of the parser context.
12517 static int
12518 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12521 if (ctxt == NULL)
12522 return (-1);
12523 else
12524 return (ctxt->options);
12526 #endif
12529 * xmlSchemaNewParserCtxt:
12530 * @URL: the location of the schema
12532 * Create an XML Schemas parse context for that file/resource expected
12533 * to contain an XML Schemas file.
12535 * Returns the parser context or NULL in case of error
12537 xmlSchemaParserCtxtPtr
12538 xmlSchemaNewParserCtxt(const char *URL)
12540 xmlSchemaParserCtxtPtr ret;
12542 if (URL == NULL)
12543 return (NULL);
12545 ret = xmlSchemaParserCtxtCreate();
12546 if (ret == NULL)
12547 return(NULL);
12548 ret->dict = xmlDictCreate();
12549 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12550 return (ret);
12554 * xmlSchemaNewMemParserCtxt:
12555 * @buffer: a pointer to a char array containing the schemas
12556 * @size: the size of the array
12558 * Create an XML Schemas parse context for that memory buffer expected
12559 * to contain an XML Schemas file.
12561 * Returns the parser context or NULL in case of error
12563 xmlSchemaParserCtxtPtr
12564 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12566 xmlSchemaParserCtxtPtr ret;
12568 if ((buffer == NULL) || (size <= 0))
12569 return (NULL);
12570 ret = xmlSchemaParserCtxtCreate();
12571 if (ret == NULL)
12572 return(NULL);
12573 ret->buffer = buffer;
12574 ret->size = size;
12575 ret->dict = xmlDictCreate();
12576 return (ret);
12580 * xmlSchemaNewDocParserCtxt:
12581 * @doc: a preparsed document tree
12583 * Create an XML Schemas parse context for that document.
12584 * NB. The document may be modified during the parsing process.
12586 * Returns the parser context or NULL in case of error
12588 xmlSchemaParserCtxtPtr
12589 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12591 xmlSchemaParserCtxtPtr ret;
12593 if (doc == NULL)
12594 return (NULL);
12595 ret = xmlSchemaParserCtxtCreate();
12596 if (ret == NULL)
12597 return(NULL);
12598 ret->doc = doc;
12599 ret->dict = xmlDictCreate();
12600 /* The application has responsibility for the document */
12601 ret->preserve = 1;
12603 return (ret);
12607 * xmlSchemaFreeParserCtxt:
12608 * @ctxt: the schema parser context
12610 * Free the resources associated to the schema parser context
12612 void
12613 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12615 if (ctxt == NULL)
12616 return;
12617 if (ctxt->doc != NULL && !ctxt->preserve)
12618 xmlFreeDoc(ctxt->doc);
12619 if (ctxt->vctxt != NULL) {
12620 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12622 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12623 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12624 ctxt->constructor = NULL;
12625 ctxt->ownsConstructor = 0;
12627 if (ctxt->attrProhibs != NULL)
12628 xmlSchemaItemListFree(ctxt->attrProhibs);
12629 xmlDictFree(ctxt->dict);
12630 xmlFree(ctxt);
12633 /************************************************************************
12635 * Building the content models *
12637 ************************************************************************/
12640 * xmlSchemaBuildContentModelForSubstGroup:
12642 * Returns 1 if nillable, 0 otherwise
12644 static int
12645 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12646 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12648 xmlAutomataStatePtr start, tmp;
12649 xmlSchemaElementPtr elemDecl, member;
12650 xmlSchemaSubstGroupPtr substGroup;
12651 int i;
12652 int ret = 0;
12654 elemDecl = (xmlSchemaElementPtr) particle->children;
12656 * Wrap the substitution group with a CHOICE.
12658 start = pctxt->state;
12659 if (end == NULL)
12660 end = xmlAutomataNewState(pctxt->am);
12661 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12662 if (substGroup == NULL) {
12663 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12664 XML_SCHEMAP_INTERNAL,
12665 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12666 "declaration is marked having a subst. group but none "
12667 "available.\n", elemDecl->name, NULL);
12668 return(0);
12670 if (counter >= 0) {
12672 * NOTE that we put the declaration in, even if it's abstract.
12673 * However, an error will be raised during *validation* if an element
12674 * information item shall be validated against an abstract element
12675 * declaration.
12677 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12678 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12679 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12681 * Add subst. group members.
12683 for (i = 0; i < substGroup->members->nbItems; i++) {
12684 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12685 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12686 member->name, member->targetNamespace, member);
12688 } else if (particle->maxOccurs == 1) {
12690 * NOTE that we put the declaration in, even if it's abstract,
12692 xmlAutomataNewEpsilon(pctxt->am,
12693 xmlAutomataNewTransition2(pctxt->am,
12694 start, NULL,
12695 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12697 * Add subst. group members.
12699 for (i = 0; i < substGroup->members->nbItems; i++) {
12700 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12702 * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12703 * was incorrectly used instead of xmlAutomataNewTransition2()
12704 * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12705 * section in xmlSchemaBuildAContentModel() ).
12706 * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12707 * intended for the above "counter" section originally. I.e.,
12708 * check xs:all with subst-groups.
12710 * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12711 * member->name, member->targetNamespace,
12712 * 1, 1, member);
12714 tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12715 member->name, member->targetNamespace, member);
12716 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12718 } else {
12719 xmlAutomataStatePtr hop;
12720 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12721 UNBOUNDED : particle->maxOccurs - 1;
12722 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12724 counter =
12725 xmlAutomataNewCounter(pctxt->am, minOccurs,
12726 maxOccurs);
12727 hop = xmlAutomataNewState(pctxt->am);
12729 xmlAutomataNewEpsilon(pctxt->am,
12730 xmlAutomataNewTransition2(pctxt->am,
12731 start, NULL,
12732 elemDecl->name, elemDecl->targetNamespace, elemDecl),
12733 hop);
12735 * Add subst. group members.
12737 for (i = 0; i < substGroup->members->nbItems; i++) {
12738 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12739 xmlAutomataNewEpsilon(pctxt->am,
12740 xmlAutomataNewTransition2(pctxt->am,
12741 start, NULL,
12742 member->name, member->targetNamespace, member),
12743 hop);
12745 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12746 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12748 if (particle->minOccurs == 0) {
12749 xmlAutomataNewEpsilon(pctxt->am, start, end);
12750 ret = 1;
12752 pctxt->state = end;
12753 return(ret);
12757 * xmlSchemaBuildContentModelForElement:
12759 * Returns 1 if nillable, 0 otherwise
12761 static int
12762 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12763 xmlSchemaParticlePtr particle)
12765 int ret = 0;
12767 if (((xmlSchemaElementPtr) particle->children)->flags &
12768 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12770 * Substitution groups.
12772 ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12773 } else {
12774 xmlSchemaElementPtr elemDecl;
12775 xmlAutomataStatePtr start;
12777 elemDecl = (xmlSchemaElementPtr) particle->children;
12779 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12780 return(0);
12781 if (particle->maxOccurs == 1) {
12782 start = ctxt->state;
12783 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12784 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12785 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12786 (particle->minOccurs < 2)) {
12787 /* Special case. */
12788 start = ctxt->state;
12789 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12790 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12791 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12792 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12793 } else {
12794 int counter;
12795 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12796 UNBOUNDED : particle->maxOccurs - 1;
12797 int minOccurs = particle->minOccurs < 1 ?
12798 0 : particle->minOccurs - 1;
12800 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12801 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12802 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12803 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12804 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12805 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12806 NULL, counter);
12808 if (particle->minOccurs == 0) {
12809 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12810 ret = 1;
12813 return(ret);
12817 * xmlSchemaBuildAContentModel:
12818 * @ctxt: the schema parser context
12819 * @particle: the particle component
12820 * @name: the complex type's name whose content is being built
12822 * Create the automaton for the {content type} of a complex type.
12824 * Returns 1 if the content is nillable, 0 otherwise
12826 static int
12827 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12828 xmlSchemaParticlePtr particle)
12830 int ret = 0, tmp2;
12832 if (particle == NULL) {
12833 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12834 return(1);
12836 if (particle->children == NULL) {
12838 * Just return in this case. A missing "term" of the particle
12839 * might arise due to an invalid "term" component.
12841 return(1);
12844 switch (particle->children->type) {
12845 case XML_SCHEMA_TYPE_ANY: {
12846 xmlAutomataStatePtr start, end;
12847 xmlSchemaWildcardPtr wild;
12848 xmlSchemaWildcardNsPtr ns;
12850 wild = (xmlSchemaWildcardPtr) particle->children;
12852 start = pctxt->state;
12853 end = xmlAutomataNewState(pctxt->am);
12855 if (particle->maxOccurs == 1) {
12856 if (wild->any == 1) {
12858 * We need to add both transitions:
12860 * 1. the {"*", "*"} for elements in a namespace.
12862 pctxt->state =
12863 xmlAutomataNewTransition2(pctxt->am,
12864 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12865 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12867 * 2. the {"*"} for elements in no namespace.
12869 pctxt->state =
12870 xmlAutomataNewTransition2(pctxt->am,
12871 start, NULL, BAD_CAST "*", NULL, wild);
12872 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12874 } else if (wild->nsSet != NULL) {
12875 ns = wild->nsSet;
12876 do {
12877 pctxt->state = start;
12878 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12879 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12880 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12881 ns = ns->next;
12882 } while (ns != NULL);
12884 } else if (wild->negNsSet != NULL) {
12885 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12886 start, end, BAD_CAST "*", wild->negNsSet->value,
12887 wild);
12889 } else {
12890 int counter;
12891 xmlAutomataStatePtr hop;
12892 int maxOccurs =
12893 particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12894 particle->maxOccurs - 1;
12895 int minOccurs =
12896 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12898 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12899 hop = xmlAutomataNewState(pctxt->am);
12900 if (wild->any == 1) {
12901 pctxt->state =
12902 xmlAutomataNewTransition2(pctxt->am,
12903 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12904 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12905 pctxt->state =
12906 xmlAutomataNewTransition2(pctxt->am,
12907 start, NULL, BAD_CAST "*", NULL, wild);
12908 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12909 } else if (wild->nsSet != NULL) {
12910 ns = wild->nsSet;
12911 do {
12912 pctxt->state =
12913 xmlAutomataNewTransition2(pctxt->am,
12914 start, NULL, BAD_CAST "*", ns->value, wild);
12915 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12916 ns = ns->next;
12917 } while (ns != NULL);
12919 } else if (wild->negNsSet != NULL) {
12920 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12921 start, hop, BAD_CAST "*", wild->negNsSet->value,
12922 wild);
12924 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12925 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12927 if (particle->minOccurs == 0) {
12928 xmlAutomataNewEpsilon(pctxt->am, start, end);
12929 ret = 1;
12931 pctxt->state = end;
12932 break;
12934 case XML_SCHEMA_TYPE_ELEMENT:
12935 ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12936 break;
12937 case XML_SCHEMA_TYPE_SEQUENCE:{
12938 xmlSchemaTreeItemPtr sub;
12940 ret = 1;
12942 * If max and min occurrences are default (1) then
12943 * simply iterate over the particles of the <sequence>.
12945 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12946 sub = particle->children->children;
12948 while (sub != NULL) {
12949 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12950 (xmlSchemaParticlePtr) sub);
12951 if (tmp2 != 1) ret = 0;
12952 sub = sub->next;
12954 } else {
12955 xmlAutomataStatePtr oldstate = pctxt->state;
12957 if (particle->maxOccurs >= UNBOUNDED) {
12958 if (particle->minOccurs > 1) {
12959 xmlAutomataStatePtr tmp;
12960 int counter;
12962 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12963 oldstate, NULL);
12964 oldstate = pctxt->state;
12966 counter = xmlAutomataNewCounter(pctxt->am,
12967 particle->minOccurs - 1, UNBOUNDED);
12969 sub = particle->children->children;
12970 while (sub != NULL) {
12971 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12972 (xmlSchemaParticlePtr) sub);
12973 if (tmp2 != 1) ret = 0;
12974 sub = sub->next;
12976 tmp = pctxt->state;
12977 xmlAutomataNewCountedTrans(pctxt->am, tmp,
12978 oldstate, counter);
12979 pctxt->state =
12980 xmlAutomataNewCounterTrans(pctxt->am, tmp,
12981 NULL, counter);
12982 if (ret == 1)
12983 xmlAutomataNewEpsilon(pctxt->am,
12984 oldstate, pctxt->state);
12986 } else {
12987 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12988 oldstate, NULL);
12989 oldstate = pctxt->state;
12991 sub = particle->children->children;
12992 while (sub != NULL) {
12993 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12994 (xmlSchemaParticlePtr) sub);
12995 if (tmp2 != 1) ret = 0;
12996 sub = sub->next;
12998 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12999 oldstate);
13001 * epsilon needed to block previous trans from
13002 * being allowed to enter back from another
13003 * construct
13005 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13006 pctxt->state, NULL);
13007 if (particle->minOccurs == 0) {
13008 xmlAutomataNewEpsilon(pctxt->am,
13009 oldstate, pctxt->state);
13010 ret = 1;
13013 } else if ((particle->maxOccurs > 1)
13014 || (particle->minOccurs > 1)) {
13015 xmlAutomataStatePtr tmp;
13016 int counter;
13018 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13019 oldstate, NULL);
13020 oldstate = pctxt->state;
13022 counter = xmlAutomataNewCounter(pctxt->am,
13023 particle->minOccurs - 1,
13024 particle->maxOccurs - 1);
13026 sub = particle->children->children;
13027 while (sub != NULL) {
13028 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13029 (xmlSchemaParticlePtr) sub);
13030 if (tmp2 != 1) ret = 0;
13031 sub = sub->next;
13033 tmp = pctxt->state;
13034 xmlAutomataNewCountedTrans(pctxt->am,
13035 tmp, oldstate, counter);
13036 pctxt->state =
13037 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
13038 counter);
13039 if ((particle->minOccurs == 0) || (ret == 1)) {
13040 xmlAutomataNewEpsilon(pctxt->am,
13041 oldstate, pctxt->state);
13042 ret = 1;
13044 } else {
13045 sub = particle->children->children;
13046 while (sub != NULL) {
13047 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13048 (xmlSchemaParticlePtr) sub);
13049 if (tmp2 != 1) ret = 0;
13050 sub = sub->next;
13054 * epsilon needed to block previous trans from
13055 * being allowed to enter back from another
13056 * construct
13058 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13059 pctxt->state, NULL);
13061 if (particle->minOccurs == 0) {
13062 xmlAutomataNewEpsilon(pctxt->am, oldstate,
13063 pctxt->state);
13064 ret = 1;
13068 break;
13070 case XML_SCHEMA_TYPE_CHOICE:{
13071 xmlSchemaTreeItemPtr sub;
13072 xmlAutomataStatePtr start, end;
13074 ret = 0;
13075 start = pctxt->state;
13076 end = xmlAutomataNewState(pctxt->am);
13079 * iterate over the subtypes and remerge the end with an
13080 * epsilon transition
13082 if (particle->maxOccurs == 1) {
13083 sub = particle->children->children;
13084 while (sub != NULL) {
13085 pctxt->state = start;
13086 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13087 (xmlSchemaParticlePtr) sub);
13088 if (tmp2 == 1) ret = 1;
13089 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13090 sub = sub->next;
13092 } else {
13093 int counter;
13094 xmlAutomataStatePtr hop, base;
13095 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13096 UNBOUNDED : particle->maxOccurs - 1;
13097 int minOccurs =
13098 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13101 * use a counter to keep track of the number of transitions
13102 * which went through the choice.
13104 counter =
13105 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13106 hop = xmlAutomataNewState(pctxt->am);
13107 base = xmlAutomataNewState(pctxt->am);
13109 sub = particle->children->children;
13110 while (sub != NULL) {
13111 pctxt->state = base;
13112 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13113 (xmlSchemaParticlePtr) sub);
13114 if (tmp2 == 1) ret = 1;
13115 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13116 sub = sub->next;
13118 xmlAutomataNewEpsilon(pctxt->am, start, base);
13119 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13120 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13121 if (ret == 1)
13122 xmlAutomataNewEpsilon(pctxt->am, base, end);
13124 if (particle->minOccurs == 0) {
13125 xmlAutomataNewEpsilon(pctxt->am, start, end);
13126 ret = 1;
13128 pctxt->state = end;
13129 break;
13131 case XML_SCHEMA_TYPE_ALL:{
13132 xmlAutomataStatePtr start, tmp;
13133 xmlSchemaParticlePtr sub;
13134 xmlSchemaElementPtr elemDecl;
13136 ret = 1;
13138 sub = (xmlSchemaParticlePtr) particle->children->children;
13139 if (sub == NULL)
13140 break;
13142 ret = 0;
13144 start = pctxt->state;
13145 tmp = xmlAutomataNewState(pctxt->am);
13146 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13147 pctxt->state = tmp;
13148 while (sub != NULL) {
13149 pctxt->state = tmp;
13151 elemDecl = (xmlSchemaElementPtr) sub->children;
13152 if (elemDecl == NULL) {
13153 PERROR_INT("xmlSchemaBuildAContentModel",
13154 "<element> particle has no term");
13155 return(ret);
13158 * NOTE: The {max occurs} of all the particles in the
13159 * {particles} of the group must be 0 or 1; this is
13160 * already ensured during the parse of the content of
13161 * <all>.
13163 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13164 int counter;
13167 * This is an abstract group, we need to share
13168 * the same counter for all the element transitions
13169 * derived from the group
13171 counter = xmlAutomataNewCounter(pctxt->am,
13172 sub->minOccurs, sub->maxOccurs);
13173 xmlSchemaBuildContentModelForSubstGroup(pctxt,
13174 sub, counter, pctxt->state);
13175 } else {
13176 if ((sub->minOccurs == 1) &&
13177 (sub->maxOccurs == 1)) {
13178 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13179 pctxt->state,
13180 elemDecl->name,
13181 elemDecl->targetNamespace,
13182 1, 1, elemDecl);
13183 } else if ((sub->minOccurs == 0) &&
13184 (sub->maxOccurs == 1)) {
13186 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13187 pctxt->state,
13188 elemDecl->name,
13189 elemDecl->targetNamespace,
13192 elemDecl);
13195 sub = (xmlSchemaParticlePtr) sub->next;
13197 pctxt->state =
13198 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13199 if (particle->minOccurs == 0) {
13200 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13201 ret = 1;
13203 break;
13205 case XML_SCHEMA_TYPE_GROUP:
13207 * If we hit a model group definition, then this means that
13208 * it was empty, thus was not substituted for the containing
13209 * model group. Just do nothing in this case.
13210 * TODO: But the group should be substituted and not occur at
13211 * all in the content model at this point. Fix this.
13213 ret = 1;
13214 break;
13215 default:
13216 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13217 "xmlSchemaBuildAContentModel",
13218 "found unexpected term of type '%s' in content model",
13219 WXS_ITEM_TYPE_NAME(particle->children), NULL);
13220 return(ret);
13222 return(ret);
13226 * xmlSchemaBuildContentModel:
13227 * @ctxt: the schema parser context
13228 * @type: the complex type definition
13229 * @name: the element name
13231 * Builds the content model of the complex type.
13233 static void
13234 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13235 xmlSchemaParserCtxtPtr ctxt)
13237 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13238 (type->contModel != NULL) ||
13239 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13240 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13241 return;
13243 #ifdef DEBUG_CONTENT
13244 xmlGenericError(xmlGenericErrorContext,
13245 "Building content model for %s\n", name);
13246 #endif
13247 ctxt->am = NULL;
13248 ctxt->am = xmlNewAutomata();
13249 if (ctxt->am == NULL) {
13250 xmlGenericError(xmlGenericErrorContext,
13251 "Cannot create automata for complex type %s\n", type->name);
13252 return;
13254 ctxt->state = xmlAutomataGetInitState(ctxt->am);
13256 * Build the automaton.
13258 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13259 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13260 type->contModel = xmlAutomataCompile(ctxt->am);
13261 if (type->contModel == NULL) {
13262 xmlSchemaPCustomErr(ctxt,
13263 XML_SCHEMAP_INTERNAL,
13264 WXS_BASIC_CAST type, type->node,
13265 "Failed to compile the content model", NULL);
13266 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13267 xmlSchemaPCustomErr(ctxt,
13268 XML_SCHEMAP_NOT_DETERMINISTIC,
13269 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13270 WXS_BASIC_CAST type, type->node,
13271 "The content model is not determinist", NULL);
13272 } else {
13273 #ifdef DEBUG_CONTENT_REGEXP
13274 xmlGenericError(xmlGenericErrorContext,
13275 "Content model of %s:\n", type->name);
13276 xmlRegexpPrint(stderr, type->contModel);
13277 #endif
13279 ctxt->state = NULL;
13280 xmlFreeAutomata(ctxt->am);
13281 ctxt->am = NULL;
13285 * xmlSchemaResolveElementReferences:
13286 * @elem: the schema element context
13287 * @ctxt: the schema parser context
13289 * Resolves the references of an element declaration
13290 * or particle, which has an element declaration as it's
13291 * term.
13293 static void
13294 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13295 xmlSchemaParserCtxtPtr ctxt)
13297 if ((ctxt == NULL) || (elemDecl == NULL) ||
13298 ((elemDecl != NULL) &&
13299 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13300 return;
13301 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13303 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13304 xmlSchemaTypePtr type;
13306 /* (type definition) ... otherwise the type definition `resolved`
13307 * to by the `actual value` of the type [attribute] ...
13309 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13310 elemDecl->namedTypeNs);
13311 if (type == NULL) {
13312 xmlSchemaPResCompAttrErr(ctxt,
13313 XML_SCHEMAP_SRC_RESOLVE,
13314 WXS_BASIC_CAST elemDecl, elemDecl->node,
13315 "type", elemDecl->namedType, elemDecl->namedTypeNs,
13316 XML_SCHEMA_TYPE_BASIC, "type definition");
13317 } else
13318 elemDecl->subtypes = type;
13320 if (elemDecl->substGroup != NULL) {
13321 xmlSchemaElementPtr substHead;
13324 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13325 * substitutionGroup?
13327 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13328 elemDecl->substGroupNs);
13329 if (substHead == NULL) {
13330 xmlSchemaPResCompAttrErr(ctxt,
13331 XML_SCHEMAP_SRC_RESOLVE,
13332 WXS_BASIC_CAST elemDecl, NULL,
13333 "substitutionGroup", elemDecl->substGroup,
13334 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13335 } else {
13336 xmlSchemaResolveElementReferences(substHead, ctxt);
13338 * Set the "substitution group affiliation".
13339 * NOTE that now we use the "refDecl" field for this.
13341 WXS_SUBST_HEAD(elemDecl) = substHead;
13343 * The type definitions is set to:
13344 * SPEC "...the {type definition} of the element
13345 * declaration `resolved` to by the `actual value`
13346 * of the substitutionGroup [attribute], if present"
13348 if (elemDecl->subtypes == NULL)
13349 elemDecl->subtypes = substHead->subtypes;
13353 * SPEC "The definition of anyType serves as the default type definition
13354 * for element declarations whose XML representation does not specify one."
13356 if ((elemDecl->subtypes == NULL) &&
13357 (elemDecl->namedType == NULL) &&
13358 (elemDecl->substGroup == NULL))
13359 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13363 * xmlSchemaResolveUnionMemberTypes:
13364 * @ctxt: the schema parser context
13365 * @type: the schema simple type definition
13367 * Checks and builds the "member type definitions" property of the union
13368 * simple type. This handles part (1), part (2) is done in
13369 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13371 * Returns -1 in case of an internal error, 0 otherwise.
13373 static int
13374 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13375 xmlSchemaTypePtr type)
13378 xmlSchemaTypeLinkPtr link, lastLink, newLink;
13379 xmlSchemaTypePtr memberType;
13382 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13383 * define the explicit members as the type definitions `resolved`
13384 * to by the items in the `actual value` of the memberTypes [attribute],
13385 * if any, followed by the type definitions corresponding to the
13386 * <simpleType>s among the [children] of <union>, if any."
13389 * Resolve references.
13391 link = type->memberTypes;
13392 lastLink = NULL;
13393 while (link != NULL) {
13394 const xmlChar *name, *nsName;
13396 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13397 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13399 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13400 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13401 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13402 WXS_BASIC_CAST type, type->node, "memberTypes",
13403 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13405 * Remove the member type link.
13407 if (lastLink == NULL)
13408 type->memberTypes = link->next;
13409 else
13410 lastLink->next = link->next;
13411 newLink = link;
13412 link = link->next;
13413 xmlFree(newLink);
13414 } else {
13415 link->type = memberType;
13416 lastLink = link;
13417 link = link->next;
13421 * Add local simple types,
13423 memberType = type->subtypes;
13424 while (memberType != NULL) {
13425 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13426 if (link == NULL) {
13427 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13428 return (-1);
13430 link->type = memberType;
13431 link->next = NULL;
13432 if (lastLink == NULL)
13433 type->memberTypes = link;
13434 else
13435 lastLink->next = link;
13436 lastLink = link;
13437 memberType = memberType->next;
13439 return (0);
13443 * xmlSchemaIsDerivedFromBuiltInType:
13444 * @ctxt: the schema parser context
13445 * @type: the type definition
13446 * @valType: the value type
13449 * Returns 1 if the type has the given value type, or
13450 * is derived from such a type.
13452 static int
13453 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13455 if (type == NULL)
13456 return (0);
13457 if (WXS_IS_COMPLEX(type))
13458 return (0);
13459 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13460 if (type->builtInType == valType)
13461 return(1);
13462 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13463 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13464 return (0);
13465 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13467 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13470 #if 0
13472 * xmlSchemaIsDerivedFromBuiltInType:
13473 * @ctxt: the schema parser context
13474 * @type: the type definition
13475 * @valType: the value type
13478 * Returns 1 if the type has the given value type, or
13479 * is derived from such a type.
13481 static int
13482 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13484 if (type == NULL)
13485 return (0);
13486 if (WXS_IS_COMPLEX(type))
13487 return (0);
13488 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13489 if (type->builtInType == valType)
13490 return(1);
13491 return (0);
13492 } else
13493 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13495 return (0);
13498 static xmlSchemaTypePtr
13499 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13501 if (type == NULL)
13502 return (NULL);
13503 if (WXS_IS_COMPLEX(type))
13504 return (NULL);
13505 if (type->type == XML_SCHEMA_TYPE_BASIC)
13506 return(type);
13507 return(xmlSchemaQueryBuiltInType(type->subtypes));
13509 #endif
13512 * xmlSchemaGetPrimitiveType:
13513 * @type: the simpleType definition
13515 * Returns the primitive type of the given type or
13516 * NULL in case of error.
13518 static xmlSchemaTypePtr
13519 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13522 while (type != NULL) {
13524 * Note that anySimpleType is actually not a primitive type
13525 * but we need that here.
13527 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13528 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13529 return (type);
13530 type = type->baseType;
13533 return (NULL);
13536 #if 0
13538 * xmlSchemaGetBuiltInTypeAncestor:
13539 * @type: the simpleType definition
13541 * Returns the primitive type of the given type or
13542 * NULL in case of error.
13544 static xmlSchemaTypePtr
13545 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13547 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13548 return (0);
13549 while (type != NULL) {
13550 if (type->type == XML_SCHEMA_TYPE_BASIC)
13551 return (type);
13552 type = type->baseType;
13555 return (NULL);
13557 #endif
13560 * xmlSchemaCloneWildcardNsConstraints:
13561 * @ctxt: the schema parser context
13562 * @dest: the destination wildcard
13563 * @source: the source wildcard
13565 * Clones the namespace constraints of source
13566 * and assigns them to dest.
13567 * Returns -1 on internal error, 0 otherwise.
13569 static int
13570 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13571 xmlSchemaWildcardPtr dest,
13572 xmlSchemaWildcardPtr source)
13574 xmlSchemaWildcardNsPtr cur, tmp, last;
13576 if ((source == NULL) || (dest == NULL))
13577 return(-1);
13578 dest->any = source->any;
13579 cur = source->nsSet;
13580 last = NULL;
13581 while (cur != NULL) {
13582 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13583 if (tmp == NULL)
13584 return(-1);
13585 tmp->value = cur->value;
13586 if (last == NULL)
13587 dest->nsSet = tmp;
13588 else
13589 last->next = tmp;
13590 last = tmp;
13591 cur = cur->next;
13593 if (dest->negNsSet != NULL)
13594 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13595 if (source->negNsSet != NULL) {
13596 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13597 if (dest->negNsSet == NULL)
13598 return(-1);
13599 dest->negNsSet->value = source->negNsSet->value;
13600 } else
13601 dest->negNsSet = NULL;
13602 return(0);
13606 * xmlSchemaUnionWildcards:
13607 * @ctxt: the schema parser context
13608 * @completeWild: the first wildcard
13609 * @curWild: the second wildcard
13611 * Unions the namespace constraints of the given wildcards.
13612 * @completeWild will hold the resulting union.
13613 * Returns a positive error code on failure, -1 in case of an
13614 * internal error, 0 otherwise.
13616 static int
13617 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13618 xmlSchemaWildcardPtr completeWild,
13619 xmlSchemaWildcardPtr curWild)
13621 xmlSchemaWildcardNsPtr cur, curB, tmp;
13624 * 1 If O1 and O2 are the same value, then that value must be the
13625 * value.
13627 if ((completeWild->any == curWild->any) &&
13628 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13629 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13631 if ((completeWild->negNsSet == NULL) ||
13632 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13634 if (completeWild->nsSet != NULL) {
13635 int found = 0;
13638 * Check equality of sets.
13640 cur = completeWild->nsSet;
13641 while (cur != NULL) {
13642 found = 0;
13643 curB = curWild->nsSet;
13644 while (curB != NULL) {
13645 if (cur->value == curB->value) {
13646 found = 1;
13647 break;
13649 curB = curB->next;
13651 if (!found)
13652 break;
13653 cur = cur->next;
13655 if (found)
13656 return(0);
13657 } else
13658 return(0);
13662 * 2 If either O1 or O2 is any, then any must be the value
13664 if (completeWild->any != curWild->any) {
13665 if (completeWild->any == 0) {
13666 completeWild->any = 1;
13667 if (completeWild->nsSet != NULL) {
13668 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13669 completeWild->nsSet = NULL;
13671 if (completeWild->negNsSet != NULL) {
13672 xmlFree(completeWild->negNsSet);
13673 completeWild->negNsSet = NULL;
13676 return (0);
13679 * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13680 * then the union of those sets must be the value.
13682 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13683 int found;
13684 xmlSchemaWildcardNsPtr start;
13686 cur = curWild->nsSet;
13687 start = completeWild->nsSet;
13688 while (cur != NULL) {
13689 found = 0;
13690 curB = start;
13691 while (curB != NULL) {
13692 if (cur->value == curB->value) {
13693 found = 1;
13694 break;
13696 curB = curB->next;
13698 if (!found) {
13699 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13700 if (tmp == NULL)
13701 return (-1);
13702 tmp->value = cur->value;
13703 tmp->next = completeWild->nsSet;
13704 completeWild->nsSet = tmp;
13706 cur = cur->next;
13709 return(0);
13712 * 4 If the two are negations of different values (namespace names
13713 * or `absent`), then a pair of not and `absent` must be the value.
13715 if ((completeWild->negNsSet != NULL) &&
13716 (curWild->negNsSet != NULL) &&
13717 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13718 completeWild->negNsSet->value = NULL;
13720 return(0);
13723 * 5.
13725 if (((completeWild->negNsSet != NULL) &&
13726 (completeWild->negNsSet->value != NULL) &&
13727 (curWild->nsSet != NULL)) ||
13728 ((curWild->negNsSet != NULL) &&
13729 (curWild->negNsSet->value != NULL) &&
13730 (completeWild->nsSet != NULL))) {
13732 int nsFound, absentFound = 0;
13734 if (completeWild->nsSet != NULL) {
13735 cur = completeWild->nsSet;
13736 curB = curWild->negNsSet;
13737 } else {
13738 cur = curWild->nsSet;
13739 curB = completeWild->negNsSet;
13741 nsFound = 0;
13742 while (cur != NULL) {
13743 if (cur->value == NULL)
13744 absentFound = 1;
13745 else if (cur->value == curB->value)
13746 nsFound = 1;
13747 if (nsFound && absentFound)
13748 break;
13749 cur = cur->next;
13752 if (nsFound && absentFound) {
13754 * 5.1 If the set S includes both the negated namespace
13755 * name and `absent`, then any must be the value.
13757 completeWild->any = 1;
13758 if (completeWild->nsSet != NULL) {
13759 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13760 completeWild->nsSet = NULL;
13762 if (completeWild->negNsSet != NULL) {
13763 xmlFree(completeWild->negNsSet);
13764 completeWild->negNsSet = NULL;
13766 } else if (nsFound && (!absentFound)) {
13768 * 5.2 If the set S includes the negated namespace name
13769 * but not `absent`, then a pair of not and `absent` must
13770 * be the value.
13772 if (completeWild->nsSet != NULL) {
13773 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13774 completeWild->nsSet = NULL;
13776 if (completeWild->negNsSet == NULL) {
13777 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13778 if (completeWild->negNsSet == NULL)
13779 return (-1);
13781 completeWild->negNsSet->value = NULL;
13782 } else if ((!nsFound) && absentFound) {
13784 * 5.3 If the set S includes `absent` but not the negated
13785 * namespace name, then the union is not expressible.
13787 xmlSchemaPErr(ctxt, completeWild->node,
13788 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13789 "The union of the wildcard is not expressible.\n",
13790 NULL, NULL);
13791 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13792 } else if ((!nsFound) && (!absentFound)) {
13794 * 5.4 If the set S does not include either the negated namespace
13795 * name or `absent`, then whichever of O1 or O2 is a pair of not
13796 * and a namespace name must be the value.
13798 if (completeWild->negNsSet == NULL) {
13799 if (completeWild->nsSet != NULL) {
13800 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13801 completeWild->nsSet = NULL;
13803 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13804 if (completeWild->negNsSet == NULL)
13805 return (-1);
13806 completeWild->negNsSet->value = curWild->negNsSet->value;
13809 return (0);
13812 * 6.
13814 if (((completeWild->negNsSet != NULL) &&
13815 (completeWild->negNsSet->value == NULL) &&
13816 (curWild->nsSet != NULL)) ||
13817 ((curWild->negNsSet != NULL) &&
13818 (curWild->negNsSet->value == NULL) &&
13819 (completeWild->nsSet != NULL))) {
13821 if (completeWild->nsSet != NULL) {
13822 cur = completeWild->nsSet;
13823 } else {
13824 cur = curWild->nsSet;
13826 while (cur != NULL) {
13827 if (cur->value == NULL) {
13829 * 6.1 If the set S includes `absent`, then any must be the
13830 * value.
13832 completeWild->any = 1;
13833 if (completeWild->nsSet != NULL) {
13834 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13835 completeWild->nsSet = NULL;
13837 if (completeWild->negNsSet != NULL) {
13838 xmlFree(completeWild->negNsSet);
13839 completeWild->negNsSet = NULL;
13841 return (0);
13843 cur = cur->next;
13845 if (completeWild->negNsSet == NULL) {
13847 * 6.2 If the set S does not include `absent`, then a pair of not
13848 * and `absent` must be the value.
13850 if (completeWild->nsSet != NULL) {
13851 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13852 completeWild->nsSet = NULL;
13854 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13855 if (completeWild->negNsSet == NULL)
13856 return (-1);
13857 completeWild->negNsSet->value = NULL;
13859 return (0);
13861 return (0);
13866 * xmlSchemaIntersectWildcards:
13867 * @ctxt: the schema parser context
13868 * @completeWild: the first wildcard
13869 * @curWild: the second wildcard
13871 * Intersects the namespace constraints of the given wildcards.
13872 * @completeWild will hold the resulting intersection.
13873 * Returns a positive error code on failure, -1 in case of an
13874 * internal error, 0 otherwise.
13876 static int
13877 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13878 xmlSchemaWildcardPtr completeWild,
13879 xmlSchemaWildcardPtr curWild)
13881 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
13884 * 1 If O1 and O2 are the same value, then that value must be the
13885 * value.
13887 if ((completeWild->any == curWild->any) &&
13888 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13889 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13891 if ((completeWild->negNsSet == NULL) ||
13892 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13894 if (completeWild->nsSet != NULL) {
13895 int found = 0;
13898 * Check equality of sets.
13900 cur = completeWild->nsSet;
13901 while (cur != NULL) {
13902 found = 0;
13903 curB = curWild->nsSet;
13904 while (curB != NULL) {
13905 if (cur->value == curB->value) {
13906 found = 1;
13907 break;
13909 curB = curB->next;
13911 if (!found)
13912 break;
13913 cur = cur->next;
13915 if (found)
13916 return(0);
13917 } else
13918 return(0);
13922 * 2 If either O1 or O2 is any, then the other must be the value.
13924 if ((completeWild->any != curWild->any) && (completeWild->any)) {
13925 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13926 return(-1);
13927 return(0);
13930 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13931 * name or `absent`) and the other is a set of (namespace names or
13932 * `absent`), then that set, minus the negated value if it was in
13933 * the set, minus `absent` if it was in the set, must be the value.
13935 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13936 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13937 const xmlChar *neg;
13939 if (completeWild->nsSet == NULL) {
13940 neg = completeWild->negNsSet->value;
13941 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13942 return(-1);
13943 } else
13944 neg = curWild->negNsSet->value;
13946 * Remove absent and negated.
13948 prev = NULL;
13949 cur = completeWild->nsSet;
13950 while (cur != NULL) {
13951 if (cur->value == NULL) {
13952 if (prev == NULL)
13953 completeWild->nsSet = cur->next;
13954 else
13955 prev->next = cur->next;
13956 xmlFree(cur);
13957 break;
13959 prev = cur;
13960 cur = cur->next;
13962 if (neg != NULL) {
13963 prev = NULL;
13964 cur = completeWild->nsSet;
13965 while (cur != NULL) {
13966 if (cur->value == neg) {
13967 if (prev == NULL)
13968 completeWild->nsSet = cur->next;
13969 else
13970 prev->next = cur->next;
13971 xmlFree(cur);
13972 break;
13974 prev = cur;
13975 cur = cur->next;
13979 return(0);
13982 * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13983 * then the intersection of those sets must be the value.
13985 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13986 int found;
13988 cur = completeWild->nsSet;
13989 prev = NULL;
13990 while (cur != NULL) {
13991 found = 0;
13992 curB = curWild->nsSet;
13993 while (curB != NULL) {
13994 if (cur->value == curB->value) {
13995 found = 1;
13996 break;
13998 curB = curB->next;
14000 if (!found) {
14001 if (prev == NULL)
14002 completeWild->nsSet = cur->next;
14003 else
14004 prev->next = cur->next;
14005 tmp = cur->next;
14006 xmlFree(cur);
14007 cur = tmp;
14008 continue;
14010 prev = cur;
14011 cur = cur->next;
14014 return(0);
14016 /* 5 If the two are negations of different namespace names,
14017 * then the intersection is not expressible
14019 if ((completeWild->negNsSet != NULL) &&
14020 (curWild->negNsSet != NULL) &&
14021 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
14022 (completeWild->negNsSet->value != NULL) &&
14023 (curWild->negNsSet->value != NULL)) {
14025 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
14026 "The intersection of the wildcard is not expressible.\n",
14027 NULL, NULL);
14028 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
14031 * 6 If the one is a negation of a namespace name and the other
14032 * is a negation of `absent`, then the one which is the negation
14033 * of a namespace name must be the value.
14035 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
14036 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
14037 (completeWild->negNsSet->value == NULL)) {
14038 completeWild->negNsSet->value = curWild->negNsSet->value;
14040 return(0);
14044 * xmlSchemaIsWildcardNsConstraintSubset:
14045 * @ctxt: the schema parser context
14046 * @sub: the first wildcard
14047 * @super: the second wildcard
14049 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
14051 * Returns 0 if the namespace constraint of @sub is an intensional
14052 * subset of @super, 1 otherwise.
14054 static int
14055 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
14056 xmlSchemaWildcardPtr super)
14059 * 1 super must be any.
14061 if (super->any)
14062 return (0);
14064 * 2.1 sub must be a pair of not and a namespace name or `absent`.
14065 * 2.2 super must be a pair of not and the same value.
14067 if ((sub->negNsSet != NULL) &&
14068 (super->negNsSet != NULL) &&
14069 (sub->negNsSet->value == super->negNsSet->value))
14070 return (0);
14072 * 3.1 sub must be a set whose members are either namespace names or `absent`.
14074 if (sub->nsSet != NULL) {
14076 * 3.2.1 super must be the same set or a superset thereof.
14078 if (super->nsSet != NULL) {
14079 xmlSchemaWildcardNsPtr cur, curB;
14080 int found = 0;
14082 cur = sub->nsSet;
14083 while (cur != NULL) {
14084 found = 0;
14085 curB = super->nsSet;
14086 while (curB != NULL) {
14087 if (cur->value == curB->value) {
14088 found = 1;
14089 break;
14091 curB = curB->next;
14093 if (!found)
14094 return (1);
14095 cur = cur->next;
14097 if (found)
14098 return (0);
14099 } else if (super->negNsSet != NULL) {
14100 xmlSchemaWildcardNsPtr cur;
14102 * 3.2.2 super must be a pair of not and a namespace name or
14103 * `absent` and that value must not be in sub's set.
14105 cur = sub->nsSet;
14106 while (cur != NULL) {
14107 if (cur->value == super->negNsSet->value)
14108 return (1);
14109 cur = cur->next;
14111 return (0);
14114 return (1);
14117 static int
14118 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14119 int *fixed,
14120 const xmlChar **value,
14121 xmlSchemaValPtr *val)
14123 *fixed = 0;
14124 *value = NULL;
14125 if (val != 0)
14126 *val = NULL;
14128 if (attruse->defValue != NULL) {
14129 *value = attruse->defValue;
14130 if (val != NULL)
14131 *val = attruse->defVal;
14132 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14133 *fixed = 1;
14134 return(1);
14135 } else if ((attruse->attrDecl != NULL) &&
14136 (attruse->attrDecl->defValue != NULL)) {
14137 *value = attruse->attrDecl->defValue;
14138 if (val != NULL)
14139 *val = attruse->attrDecl->defVal;
14140 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14141 *fixed = 1;
14142 return(1);
14144 return(0);
14147 * xmlSchemaCheckCVCWildcardNamespace:
14148 * @wild: the wildcard
14149 * @ns: the namespace
14151 * Validation Rule: Wildcard allows Namespace Name
14152 * (cvc-wildcard-namespace)
14154 * Returns 0 if the given namespace matches the wildcard,
14155 * 1 otherwise and -1 on API errors.
14157 static int
14158 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14159 const xmlChar* ns)
14161 if (wild == NULL)
14162 return(-1);
14164 if (wild->any)
14165 return(0);
14166 else if (wild->nsSet != NULL) {
14167 xmlSchemaWildcardNsPtr cur;
14169 cur = wild->nsSet;
14170 while (cur != NULL) {
14171 if (xmlStrEqual(cur->value, ns))
14172 return(0);
14173 cur = cur->next;
14175 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14176 (!xmlStrEqual(wild->negNsSet->value, ns)))
14177 return(0);
14179 return(1);
14182 #define XML_SCHEMA_ACTION_DERIVE 0
14183 #define XML_SCHEMA_ACTION_REDEFINE 1
14185 #define WXS_ACTION_STR(a) \
14186 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14189 * Schema Component Constraint:
14190 * Derivation Valid (Restriction, Complex)
14191 * derivation-ok-restriction (2) - (4)
14193 * ATTENTION:
14194 * In XML Schema 1.1 this will be:
14195 * Validation Rule:
14196 * Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14199 static int
14200 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14201 int action,
14202 xmlSchemaBasicItemPtr item,
14203 xmlSchemaBasicItemPtr baseItem,
14204 xmlSchemaItemListPtr uses,
14205 xmlSchemaItemListPtr baseUses,
14206 xmlSchemaWildcardPtr wild,
14207 xmlSchemaWildcardPtr baseWild)
14209 xmlSchemaAttributeUsePtr cur = NULL, bcur;
14210 int i, j, found; /* err = 0; */
14211 const xmlChar *bEffValue;
14212 int effFixed;
14214 if (uses != NULL) {
14215 for (i = 0; i < uses->nbItems; i++) {
14216 cur = uses->items[i];
14217 found = 0;
14218 if (baseUses == NULL)
14219 goto not_found;
14220 for (j = 0; j < baseUses->nbItems; j++) {
14221 bcur = baseUses->items[j];
14222 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14223 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14224 (WXS_ATTRUSE_DECL_TNS(cur) ==
14225 WXS_ATTRUSE_DECL_TNS(bcur)))
14228 * (2.1) "If there is an attribute use in the {attribute
14229 * uses} of the {base type definition} (call this B) whose
14230 * {attribute declaration} has the same {name} and {target
14231 * namespace}, then all of the following must be true:"
14233 found = 1;
14235 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14236 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14238 xmlChar *str = NULL;
14240 * (2.1.1) "one of the following must be true:"
14241 * (2.1.1.1) "B's {required} is false."
14242 * (2.1.1.2) "R's {required} is true."
14244 xmlSchemaPAttrUseErr4(pctxt,
14245 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14246 WXS_ITEM_NODE(item), item, cur,
14247 "The 'optional' attribute use is inconsistent "
14248 "with the corresponding 'required' attribute use of "
14249 "the %s %s",
14250 WXS_ACTION_STR(action),
14251 xmlSchemaGetComponentDesignation(&str, baseItem),
14252 NULL, NULL);
14253 FREE_AND_NULL(str);
14254 /* err = pctxt->err; */
14255 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14256 WXS_ATTRUSE_TYPEDEF(cur),
14257 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14259 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14262 * SPEC (2.1.2) "R's {attribute declaration}'s
14263 * {type definition} must be validly derived from
14264 * B's {type definition} given the empty set as
14265 * defined in Type Derivation OK (Simple) ($3.14.6)."
14267 xmlSchemaPAttrUseErr4(pctxt,
14268 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14269 WXS_ITEM_NODE(item), item, cur,
14270 "The attribute declaration's %s "
14271 "is not validly derived from "
14272 "the corresponding %s of the "
14273 "attribute declaration in the %s %s",
14274 xmlSchemaGetComponentDesignation(&strA,
14275 WXS_ATTRUSE_TYPEDEF(cur)),
14276 xmlSchemaGetComponentDesignation(&strB,
14277 WXS_ATTRUSE_TYPEDEF(bcur)),
14278 WXS_ACTION_STR(action),
14279 xmlSchemaGetComponentDesignation(&strC, baseItem));
14280 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14281 FREE_AND_NULL(strA);
14282 FREE_AND_NULL(strB);
14283 FREE_AND_NULL(strC);
14284 /* err = pctxt->err; */
14285 } else {
14287 * 2.1.3 [Definition:] Let the effective value
14288 * constraint of an attribute use be its {value
14289 * constraint}, if present, otherwise its {attribute
14290 * declaration}'s {value constraint} .
14292 xmlSchemaGetEffectiveValueConstraint(bcur,
14293 &effFixed, &bEffValue, NULL);
14295 * 2.1.3 ... one of the following must be true
14297 * 2.1.3.1 B's `effective value constraint` is
14298 * `absent` or default.
14300 if ((bEffValue != NULL) &&
14301 (effFixed == 1)) {
14302 const xmlChar *rEffValue = NULL;
14304 xmlSchemaGetEffectiveValueConstraint(bcur,
14305 &effFixed, &rEffValue, NULL);
14307 * 2.1.3.2 R's `effective value constraint` is
14308 * fixed with the same string as B's.
14309 * MAYBE TODO: Compare the computed values.
14310 * Hmm, it says "same string" so
14311 * string-equality might really be sufficient.
14313 if ((effFixed == 0) ||
14314 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14316 xmlChar *str = NULL;
14318 xmlSchemaPAttrUseErr4(pctxt,
14319 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14320 WXS_ITEM_NODE(item), item, cur,
14321 "The effective value constraint of the "
14322 "attribute use is inconsistent with "
14323 "its correspondent in the %s %s",
14324 WXS_ACTION_STR(action),
14325 xmlSchemaGetComponentDesignation(&str,
14326 baseItem),
14327 NULL, NULL);
14328 FREE_AND_NULL(str);
14329 /* err = pctxt->err; */
14333 break;
14336 not_found:
14337 if (!found) {
14339 * (2.2) "otherwise the {base type definition} must have an
14340 * {attribute wildcard} and the {target namespace} of the
14341 * R's {attribute declaration} must be `valid` with respect
14342 * to that wildcard, as defined in Wildcard allows Namespace
14343 * Name ($3.10.4)."
14345 if ((baseWild == NULL) ||
14346 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14347 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14349 xmlChar *str = NULL;
14351 xmlSchemaPAttrUseErr4(pctxt,
14352 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14353 WXS_ITEM_NODE(item), item, cur,
14354 "Neither a matching attribute use, "
14355 "nor a matching wildcard exists in the %s %s",
14356 WXS_ACTION_STR(action),
14357 xmlSchemaGetComponentDesignation(&str, baseItem),
14358 NULL, NULL);
14359 FREE_AND_NULL(str);
14360 /* err = pctxt->err; */
14366 * SPEC derivation-ok-restriction (3):
14367 * (3) "For each attribute use in the {attribute uses} of the {base type
14368 * definition} whose {required} is true, there must be an attribute
14369 * use with an {attribute declaration} with the same {name} and
14370 * {target namespace} as its {attribute declaration} in the {attribute
14371 * uses} of the complex type definition itself whose {required} is true.
14373 if (baseUses != NULL) {
14374 for (j = 0; j < baseUses->nbItems; j++) {
14375 bcur = baseUses->items[j];
14376 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14377 continue;
14378 found = 0;
14379 if (uses != NULL) {
14380 for (i = 0; i < uses->nbItems; i++) {
14381 cur = uses->items[i];
14382 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14383 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14384 (WXS_ATTRUSE_DECL_TNS(cur) ==
14385 WXS_ATTRUSE_DECL_TNS(bcur))) {
14386 found = 1;
14387 break;
14391 if (!found) {
14392 xmlChar *strA = NULL, *strB = NULL;
14394 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14395 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14396 NULL, item,
14397 "A matching attribute use for the "
14398 "'required' %s of the %s %s is missing",
14399 xmlSchemaGetComponentDesignation(&strA, bcur),
14400 WXS_ACTION_STR(action),
14401 xmlSchemaGetComponentDesignation(&strB, baseItem),
14402 NULL);
14403 FREE_AND_NULL(strA);
14404 FREE_AND_NULL(strB);
14409 * derivation-ok-restriction (4)
14411 if (wild != NULL) {
14413 * (4) "If there is an {attribute wildcard}, all of the
14414 * following must be true:"
14416 if (baseWild == NULL) {
14417 xmlChar *str = NULL;
14420 * (4.1) "The {base type definition} must also have one."
14422 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14423 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14424 NULL, item,
14425 "The %s has an attribute wildcard, "
14426 "but the %s %s '%s' does not have one",
14427 WXS_ITEM_TYPE_NAME(item),
14428 WXS_ACTION_STR(action),
14429 WXS_ITEM_TYPE_NAME(baseItem),
14430 xmlSchemaGetComponentQName(&str, baseItem));
14431 FREE_AND_NULL(str);
14432 return(pctxt->err);
14433 } else if ((baseWild->any == 0) &&
14434 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14436 xmlChar *str = NULL;
14438 * (4.2) "The complex type definition's {attribute wildcard}'s
14439 * {namespace constraint} must be a subset of the {base type
14440 * definition}'s {attribute wildcard}'s {namespace constraint},
14441 * as defined by Wildcard Subset ($3.10.6)."
14443 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14444 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14445 NULL, item,
14446 "The attribute wildcard is not a valid "
14447 "subset of the wildcard in the %s %s '%s'",
14448 WXS_ACTION_STR(action),
14449 WXS_ITEM_TYPE_NAME(baseItem),
14450 xmlSchemaGetComponentQName(&str, baseItem),
14451 NULL);
14452 FREE_AND_NULL(str);
14453 return(pctxt->err);
14455 /* 4.3 Unless the {base type definition} is the `ur-type
14456 * definition`, the complex type definition's {attribute
14457 * wildcard}'s {process contents} must be identical to or
14458 * stronger than the {base type definition}'s {attribute
14459 * wildcard}'s {process contents}, where strict is stronger
14460 * than lax is stronger than skip.
14462 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14463 (wild->processContents < baseWild->processContents)) {
14464 xmlChar *str = NULL;
14465 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14466 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14467 NULL, baseItem,
14468 "The {process contents} of the attribute wildcard is "
14469 "weaker than the one 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);
14478 return(0);
14482 static int
14483 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14484 xmlSchemaBasicItemPtr item,
14485 xmlSchemaWildcardPtr *completeWild,
14486 xmlSchemaItemListPtr list,
14487 xmlSchemaItemListPtr prohibs);
14489 * xmlSchemaFixupTypeAttributeUses:
14490 * @ctxt: the schema parser context
14491 * @type: the complex type definition
14494 * Builds the wildcard and the attribute uses on the given complex type.
14495 * Returns -1 if an internal error occurs, 0 otherwise.
14497 * ATTENTION TODO: Experimentally this uses pointer comparisons for
14498 * strings, so recheck this if we start to hardcode some schemata, since
14499 * they might not be in the same dict.
14500 * NOTE: It is allowed to "extend" the xs:anyType type.
14502 static int
14503 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14504 xmlSchemaTypePtr type)
14506 xmlSchemaTypePtr baseType = NULL;
14507 xmlSchemaAttributeUsePtr use;
14508 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14510 if (type->baseType == NULL) {
14511 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14512 "no base type");
14513 return (-1);
14515 baseType = type->baseType;
14516 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14517 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14518 return(-1);
14520 uses = type->attrUses;
14521 baseUses = baseType->attrUses;
14523 * Expand attribute group references. And build the 'complete'
14524 * wildcard, i.e. intersect multiple wildcards.
14525 * Move attribute prohibitions into a separate list.
14527 if (uses != NULL) {
14528 if (WXS_IS_RESTRICTION(type)) {
14530 * This one will transfer all attr. prohibitions
14531 * into pctxt->attrProhibs.
14533 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14534 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14535 pctxt->attrProhibs) == -1)
14537 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14538 "failed to expand attributes");
14540 if (pctxt->attrProhibs->nbItems != 0)
14541 prohibs = pctxt->attrProhibs;
14542 } else {
14543 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14544 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14545 NULL) == -1)
14547 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14548 "failed to expand attributes");
14553 * Inherit the attribute uses of the base type.
14555 if (baseUses != NULL) {
14556 int i, j;
14557 xmlSchemaAttributeUseProhibPtr pro;
14559 if (WXS_IS_RESTRICTION(type)) {
14560 int usesCount;
14561 xmlSchemaAttributeUsePtr tmp;
14563 if (uses != NULL)
14564 usesCount = uses->nbItems;
14565 else
14566 usesCount = 0;
14568 /* Restriction. */
14569 for (i = 0; i < baseUses->nbItems; i++) {
14570 use = baseUses->items[i];
14571 if (prohibs) {
14573 * Filter out prohibited uses.
14575 for (j = 0; j < prohibs->nbItems; j++) {
14576 pro = prohibs->items[j];
14577 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14578 (WXS_ATTRUSE_DECL_TNS(use) ==
14579 pro->targetNamespace))
14581 goto inherit_next;
14585 if (usesCount) {
14587 * Filter out existing uses.
14589 for (j = 0; j < usesCount; j++) {
14590 tmp = uses->items[j];
14591 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14592 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14593 (WXS_ATTRUSE_DECL_TNS(use) ==
14594 WXS_ATTRUSE_DECL_TNS(tmp)))
14596 goto inherit_next;
14600 if (uses == NULL) {
14601 type->attrUses = xmlSchemaItemListCreate();
14602 if (type->attrUses == NULL)
14603 goto exit_failure;
14604 uses = type->attrUses;
14606 xmlSchemaItemListAddSize(uses, 2, use);
14607 inherit_next: {}
14609 } else {
14610 /* Extension. */
14611 for (i = 0; i < baseUses->nbItems; i++) {
14612 use = baseUses->items[i];
14613 if (uses == NULL) {
14614 type->attrUses = xmlSchemaItemListCreate();
14615 if (type->attrUses == NULL)
14616 goto exit_failure;
14617 uses = type->attrUses;
14619 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14624 * Shrink attr. uses.
14626 if (uses) {
14627 if (uses->nbItems == 0) {
14628 xmlSchemaItemListFree(uses);
14629 type->attrUses = NULL;
14632 * TODO: We could shrink the size of the array
14633 * to fit the actual number of items.
14637 * Compute the complete wildcard.
14639 if (WXS_IS_EXTENSION(type)) {
14640 if (baseType->attributeWildcard != NULL) {
14642 * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14643 * the appropriate case among the following:"
14645 if (type->attributeWildcard != NULL) {
14647 * Union the complete wildcard with the base wildcard.
14648 * SPEC {attribute wildcard}
14649 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14650 * and {annotation} are those of the `complete wildcard`,
14651 * and whose {namespace constraint} is the intensional union
14652 * of the {namespace constraint} of the `complete wildcard`
14653 * and of the `base wildcard`, as defined in Attribute
14654 * Wildcard Union ($3.10.6)."
14656 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14657 baseType->attributeWildcard) == -1)
14658 goto exit_failure;
14659 } else {
14661 * (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14662 * then the `base wildcard`."
14664 type->attributeWildcard = baseType->attributeWildcard;
14666 } else {
14668 * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14669 * `complete wildcard`"
14670 * NOOP
14673 } else {
14675 * SPEC {attribute wildcard}
14676 * (3.1) "If the <restriction> alternative is chosen, then the
14677 * `complete wildcard`;"
14678 * NOOP
14682 return (0);
14684 exit_failure:
14685 return(-1);
14689 * xmlSchemaTypeFinalContains:
14690 * @schema: the schema
14691 * @type: the type definition
14692 * @final: the final
14694 * Evaluates if a type definition contains the given "final".
14695 * This does take "finalDefault" into account as well.
14697 * Returns 1 if the type does contain the given "final",
14698 * 0 otherwise.
14700 static int
14701 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14703 if (type == NULL)
14704 return (0);
14705 if (type->flags & final)
14706 return (1);
14707 else
14708 return (0);
14712 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14713 * @type: the Union Simple Type
14715 * Returns a list of member types of @type if existing,
14716 * returns NULL otherwise.
14718 static xmlSchemaTypeLinkPtr
14719 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14721 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14722 if (type->memberTypes != NULL)
14723 return (type->memberTypes);
14724 else
14725 type = type->baseType;
14727 return (NULL);
14730 #if 0
14732 * xmlSchemaGetParticleTotalRangeMin:
14733 * @particle: the particle
14735 * Schema Component Constraint: Effective Total Range
14736 * (all and sequence) + (choice)
14738 * Returns the minimum Effective Total Range.
14740 static int
14741 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14743 if ((particle->children == NULL) ||
14744 (particle->minOccurs == 0))
14745 return (0);
14746 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14747 int min = -1, cur;
14748 xmlSchemaParticlePtr part =
14749 (xmlSchemaParticlePtr) particle->children->children;
14751 if (part == NULL)
14752 return (0);
14753 while (part != NULL) {
14754 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14755 (part->children->type == XML_SCHEMA_TYPE_ANY))
14756 cur = part->minOccurs;
14757 else
14758 cur = xmlSchemaGetParticleTotalRangeMin(part);
14759 if (cur == 0)
14760 return (0);
14761 if ((min > cur) || (min == -1))
14762 min = cur;
14763 part = (xmlSchemaParticlePtr) part->next;
14765 return (particle->minOccurs * min);
14766 } else {
14767 /* <all> and <sequence> */
14768 int sum = 0;
14769 xmlSchemaParticlePtr part =
14770 (xmlSchemaParticlePtr) particle->children->children;
14772 if (part == NULL)
14773 return (0);
14774 do {
14775 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14776 (part->children->type == XML_SCHEMA_TYPE_ANY))
14777 sum += part->minOccurs;
14778 else
14779 sum += xmlSchemaGetParticleTotalRangeMin(part);
14780 part = (xmlSchemaParticlePtr) part->next;
14781 } while (part != NULL);
14782 return (particle->minOccurs * sum);
14787 * xmlSchemaGetParticleTotalRangeMax:
14788 * @particle: the particle
14790 * Schema Component Constraint: Effective Total Range
14791 * (all and sequence) + (choice)
14793 * Returns the maximum Effective Total Range.
14795 static int
14796 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14798 if ((particle->children == NULL) ||
14799 (particle->children->children == NULL))
14800 return (0);
14801 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14802 int max = -1, cur;
14803 xmlSchemaParticlePtr part =
14804 (xmlSchemaParticlePtr) particle->children->children;
14806 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14807 if (part->children == NULL)
14808 continue;
14809 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14810 (part->children->type == XML_SCHEMA_TYPE_ANY))
14811 cur = part->maxOccurs;
14812 else
14813 cur = xmlSchemaGetParticleTotalRangeMax(part);
14814 if (cur == UNBOUNDED)
14815 return (UNBOUNDED);
14816 if ((max < cur) || (max == -1))
14817 max = cur;
14819 /* TODO: Handle overflows? */
14820 return (particle->maxOccurs * max);
14821 } else {
14822 /* <all> and <sequence> */
14823 int sum = 0, cur;
14824 xmlSchemaParticlePtr part =
14825 (xmlSchemaParticlePtr) particle->children->children;
14827 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14828 if (part->children == NULL)
14829 continue;
14830 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14831 (part->children->type == XML_SCHEMA_TYPE_ANY))
14832 cur = part->maxOccurs;
14833 else
14834 cur = xmlSchemaGetParticleTotalRangeMax(part);
14835 if (cur == UNBOUNDED)
14836 return (UNBOUNDED);
14837 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14838 return (UNBOUNDED);
14839 sum += cur;
14841 /* TODO: Handle overflows? */
14842 return (particle->maxOccurs * sum);
14845 #endif
14848 * xmlSchemaGetParticleEmptiable:
14849 * @particle: the particle
14851 * Returns 1 if emptiable, 0 otherwise.
14853 static int
14854 xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
14856 xmlSchemaParticlePtr part;
14857 int emptiable;
14859 if ((particle->children == NULL) || (particle->minOccurs == 0))
14860 return (1);
14862 part = (xmlSchemaParticlePtr) particle->children->children;
14863 if (part == NULL)
14864 return (1);
14866 while (part != NULL) {
14867 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14868 (part->children->type == XML_SCHEMA_TYPE_ANY))
14869 emptiable = (part->minOccurs == 0);
14870 else
14871 emptiable = xmlSchemaGetParticleEmptiable(part);
14872 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14873 if (emptiable)
14874 return (1);
14875 } else {
14876 /* <all> and <sequence> */
14877 if (!emptiable)
14878 return (0);
14880 part = (xmlSchemaParticlePtr) part->next;
14883 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
14884 return (0);
14885 else
14886 return (1);
14890 * xmlSchemaIsParticleEmptiable:
14891 * @particle: the particle
14893 * Schema Component Constraint: Particle Emptiable
14894 * Checks whether the given particle is emptiable.
14896 * Returns 1 if emptiable, 0 otherwise.
14898 static int
14899 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14902 * SPEC (1) "Its {min occurs} is 0."
14904 if ((particle == NULL) || (particle->minOccurs == 0) ||
14905 (particle->children == NULL))
14906 return (1);
14908 * SPEC (2) "Its {term} is a group and the minimum part of the
14909 * effective total range of that group, [...] is 0."
14911 if (WXS_IS_MODEL_GROUP(particle->children))
14912 return (xmlSchemaGetParticleEmptiable(particle));
14913 return (0);
14917 * xmlSchemaCheckCOSSTDerivedOK:
14918 * @actxt: a context
14919 * @type: the derived simple type definition
14920 * @baseType: the base type definition
14921 * @subset: the subset of ('restriction', etc.)
14923 * Schema Component Constraint:
14924 * Type Derivation OK (Simple) (cos-st-derived-OK)
14926 * Checks whether @type can be validly
14927 * derived from @baseType.
14929 * Returns 0 on success, an positive error code otherwise.
14931 static int
14932 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14933 xmlSchemaTypePtr type,
14934 xmlSchemaTypePtr baseType,
14935 int subset)
14938 * 1 They are the same type definition.
14939 * TODO: The identity check might have to be more complex than this.
14941 if (type == baseType)
14942 return (0);
14944 * 2.1 restriction is not in the subset, or in the {final}
14945 * of its own {base type definition};
14947 * NOTE that this will be used also via "xsi:type".
14949 * TODO: Revise this, it looks strange. How can the "type"
14950 * not be fixed or *in* fixing?
14952 if (WXS_IS_TYPE_NOT_FIXED(type))
14953 if (xmlSchemaTypeFixup(type, actxt) == -1)
14954 return(-1);
14955 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14956 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14957 return(-1);
14958 if ((subset & SUBSET_RESTRICTION) ||
14959 (xmlSchemaTypeFinalContains(type->baseType,
14960 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14961 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14963 /* 2.2 */
14964 if (type->baseType == baseType) {
14966 * 2.2.1 D's `base type definition` is B.
14968 return (0);
14971 * 2.2.2 D's `base type definition` is not the `ur-type definition`
14972 * and is validly derived from B given the subset, as defined by this
14973 * constraint.
14975 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14976 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14977 baseType, subset) == 0)) {
14978 return (0);
14981 * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14982 * definition`.
14984 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14985 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14986 return (0);
14989 * 2.2.4 B's {variety} is union and D is validly derived from a type
14990 * definition in B's {member type definitions} given the subset, as
14991 * defined by this constraint.
14993 * NOTE: This seems not to involve built-in types, since there is no
14994 * built-in Union Simple Type.
14996 if (WXS_IS_UNION(baseType)) {
14997 xmlSchemaTypeLinkPtr cur;
14999 cur = baseType->memberTypes;
15000 while (cur != NULL) {
15001 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
15002 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
15003 return(-1);
15004 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
15005 type, cur->type, subset) == 0)
15008 * It just has to be validly derived from at least one
15009 * member-type.
15011 return (0);
15013 cur = cur->next;
15016 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
15020 * xmlSchemaCheckTypeDefCircularInternal:
15021 * @pctxt: the schema parser context
15022 * @ctxtType: the type definition
15023 * @ancestor: an ancestor of @ctxtType
15025 * Checks st-props-correct (2) + ct-props-correct (3).
15026 * Circular type definitions are not allowed.
15028 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
15029 * circular, 0 otherwise.
15031 static int
15032 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
15033 xmlSchemaTypePtr ctxtType,
15034 xmlSchemaTypePtr ancestor)
15036 int ret;
15038 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
15039 return (0);
15041 if (ctxtType == ancestor) {
15042 xmlSchemaPCustomErr(pctxt,
15043 XML_SCHEMAP_ST_PROPS_CORRECT_2,
15044 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
15045 "The definition is circular", NULL);
15046 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
15048 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
15050 * Avoid infinite recursion on circular types not yet checked.
15052 return (0);
15054 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
15055 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
15056 ancestor->baseType);
15057 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
15058 return (ret);
15062 * xmlSchemaCheckTypeDefCircular:
15063 * @item: the complex/simple type definition
15064 * @ctxt: the parser context
15065 * @name: the name
15067 * Checks for circular type definitions.
15069 static void
15070 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
15071 xmlSchemaParserCtxtPtr ctxt)
15073 if ((item == NULL) ||
15074 (item->type == XML_SCHEMA_TYPE_BASIC) ||
15075 (item->baseType == NULL))
15076 return;
15077 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
15078 item->baseType);
15082 * Simple Type Definition Representation OK (src-simple-type) 4
15084 * "4 Circular union type definition is disallowed. That is, if the
15085 * <union> alternative is chosen, there must not be any entries in the
15086 * memberTypes [attribute] at any depth which resolve to the component
15087 * corresponding to the <simpleType>."
15089 * Note that this should work on the *representation* of a component,
15090 * thus assumes any union types in the member types not being yet
15091 * substituted. At this stage we need the variety of the types
15092 * to be already computed.
15094 static int
15095 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
15096 xmlSchemaTypePtr ctxType,
15097 xmlSchemaTypeLinkPtr members)
15099 xmlSchemaTypeLinkPtr member;
15100 xmlSchemaTypePtr memberType;
15102 member = members;
15103 while (member != NULL) {
15104 memberType = member->type;
15105 while ((memberType != NULL) &&
15106 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
15107 if (memberType == ctxType) {
15108 xmlSchemaPCustomErr(pctxt,
15109 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
15110 WXS_BASIC_CAST ctxType, NULL,
15111 "The union type definition is circular", NULL);
15112 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
15114 if ((WXS_IS_UNION(memberType)) &&
15115 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
15117 int res;
15118 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
15119 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15120 ctxType,
15121 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15122 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15123 if (res != 0)
15124 return(res);
15126 memberType = memberType->baseType;
15128 member = member->next;
15130 return(0);
15133 static int
15134 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15135 xmlSchemaTypePtr type)
15137 if (! WXS_IS_UNION(type))
15138 return(0);
15139 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15140 type->memberTypes));
15144 * xmlSchemaResolveTypeReferences:
15145 * @item: the complex/simple type definition
15146 * @ctxt: the parser context
15147 * @name: the name
15149 * Resolves type definition references
15151 static void
15152 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15153 xmlSchemaParserCtxtPtr ctxt)
15155 if (typeDef == NULL)
15156 return;
15159 * Resolve the base type.
15161 if (typeDef->baseType == NULL) {
15162 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15163 typeDef->base, typeDef->baseNs);
15164 if (typeDef->baseType == NULL) {
15165 xmlSchemaPResCompAttrErr(ctxt,
15166 XML_SCHEMAP_SRC_RESOLVE,
15167 WXS_BASIC_CAST typeDef, typeDef->node,
15168 "base", typeDef->base, typeDef->baseNs,
15169 XML_SCHEMA_TYPE_SIMPLE, NULL);
15170 return;
15173 if (WXS_IS_SIMPLE(typeDef)) {
15174 if (WXS_IS_UNION(typeDef)) {
15176 * Resolve the memberTypes.
15178 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15179 return;
15180 } else if (WXS_IS_LIST(typeDef)) {
15182 * Resolve the itemType.
15184 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15186 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15187 typeDef->base, typeDef->baseNs);
15189 if ((typeDef->subtypes == NULL) ||
15190 (! WXS_IS_SIMPLE(typeDef->subtypes)))
15192 typeDef->subtypes = NULL;
15193 xmlSchemaPResCompAttrErr(ctxt,
15194 XML_SCHEMAP_SRC_RESOLVE,
15195 WXS_BASIC_CAST typeDef, typeDef->node,
15196 "itemType", typeDef->base, typeDef->baseNs,
15197 XML_SCHEMA_TYPE_SIMPLE, NULL);
15200 return;
15204 * The ball of letters below means, that if we have a particle
15205 * which has a QName-helper component as its {term}, we want
15206 * to resolve it...
15208 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15209 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15210 XML_SCHEMA_TYPE_PARTICLE) &&
15211 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15212 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15213 XML_SCHEMA_EXTRA_QNAMEREF))
15215 xmlSchemaQNameRefPtr ref =
15216 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15217 xmlSchemaModelGroupDefPtr groupDef;
15220 * URGENT TODO: Test this.
15222 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15224 * Resolve the MG definition reference.
15226 groupDef =
15227 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15228 ref->itemType, ref->name, ref->targetNamespace);
15229 if (groupDef == NULL) {
15230 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15231 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15232 "ref", ref->name, ref->targetNamespace, ref->itemType,
15233 NULL);
15234 /* Remove the particle. */
15235 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15236 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15237 /* Remove the particle. */
15238 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15239 else {
15241 * Assign the MG definition's {model group} to the
15242 * particle's {term}.
15244 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15246 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15248 * SPEC cos-all-limited (1.2)
15249 * "1.2 the {term} property of a particle with
15250 * {max occurs}=1 which is part of a pair which constitutes
15251 * the {content type} of a complex type definition."
15253 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15254 xmlSchemaCustomErr(ACTXT_CAST ctxt,
15255 /* TODO: error code */
15256 XML_SCHEMAP_COS_ALL_LIMITED,
15257 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15258 "The particle's {max occurs} must be 1, since the "
15259 "reference resolves to an 'all' model group",
15260 NULL, NULL);
15270 * xmlSchemaCheckSTPropsCorrect:
15271 * @ctxt: the schema parser context
15272 * @type: the simple type definition
15274 * Checks st-props-correct.
15276 * Returns 0 if the properties are correct,
15277 * if not, a positive error code and -1 on internal
15278 * errors.
15280 static int
15281 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15282 xmlSchemaTypePtr type)
15284 xmlSchemaTypePtr baseType = type->baseType;
15285 xmlChar *str = NULL;
15287 /* STATE: error funcs converted. */
15289 * Schema Component Constraint: Simple Type Definition Properties Correct
15291 * NOTE: This is somehow redundant, since we actually built a simple type
15292 * to have all the needed information; this acts as an self test.
15294 /* Base type: If the datatype has been `derived` by `restriction`
15295 * then the Simple Type Definition component from which it is `derived`,
15296 * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15298 if (baseType == NULL) {
15300 * TODO: Think about: "modulo the impact of Missing
15301 * Sub-components ($5.3)."
15303 xmlSchemaPCustomErr(ctxt,
15304 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15305 WXS_BASIC_CAST type, NULL,
15306 "No base type existent", NULL);
15307 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15310 if (! WXS_IS_SIMPLE(baseType)) {
15311 xmlSchemaPCustomErr(ctxt,
15312 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15313 WXS_BASIC_CAST type, NULL,
15314 "The base type '%s' is not a simple type",
15315 xmlSchemaGetComponentQName(&str, baseType));
15316 FREE_AND_NULL(str)
15317 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15319 if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15320 (WXS_IS_RESTRICTION(type) == 0) &&
15321 ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15322 (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15323 xmlSchemaPCustomErr(ctxt,
15324 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15325 WXS_BASIC_CAST type, NULL,
15326 "A type, derived by list or union, must have "
15327 "the simple ur-type definition as base type, not '%s'",
15328 xmlSchemaGetComponentQName(&str, baseType));
15329 FREE_AND_NULL(str)
15330 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15333 * Variety: One of {atomic, list, union}.
15335 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15336 (! WXS_IS_LIST(type))) {
15337 xmlSchemaPCustomErr(ctxt,
15338 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15339 WXS_BASIC_CAST type, NULL,
15340 "The variety is absent", NULL);
15341 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15343 /* TODO: Finish this. Hmm, is this finished? */
15346 * 3 The {final} of the {base type definition} must not contain restriction.
15348 if (xmlSchemaTypeFinalContains(baseType,
15349 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15350 xmlSchemaPCustomErr(ctxt,
15351 XML_SCHEMAP_ST_PROPS_CORRECT_3,
15352 WXS_BASIC_CAST type, NULL,
15353 "The 'final' of its base type '%s' must not contain "
15354 "'restriction'",
15355 xmlSchemaGetComponentQName(&str, baseType));
15356 FREE_AND_NULL(str)
15357 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15361 * 2 All simple type definitions must be derived ultimately from the `simple
15362 * ur-type definition` (so circular definitions are disallowed). That is, it
15363 * must be possible to reach a built-in primitive datatype or the `simple
15364 * ur-type definition` by repeatedly following the {base type definition}.
15366 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15368 return (0);
15372 * xmlSchemaCheckCOSSTRestricts:
15373 * @ctxt: the schema parser context
15374 * @type: the simple type definition
15376 * Schema Component Constraint:
15377 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15379 * Checks if the given @type (simpleType) is derived validly by restriction.
15380 * STATUS:
15382 * Returns -1 on internal errors, 0 if the type is validly derived,
15383 * a positive error code otherwise.
15385 static int
15386 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15387 xmlSchemaTypePtr type)
15389 xmlChar *str = NULL;
15391 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15392 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15393 "given type is not a user-derived simpleType");
15394 return (-1);
15397 if (WXS_IS_ATOMIC(type)) {
15398 xmlSchemaTypePtr primitive;
15400 * 1.1 The {base type definition} must be an atomic simple
15401 * type definition or a built-in primitive datatype.
15403 if (! WXS_IS_ATOMIC(type->baseType)) {
15404 xmlSchemaPCustomErr(pctxt,
15405 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15406 WXS_BASIC_CAST type, NULL,
15407 "The base type '%s' is not an atomic simple type",
15408 xmlSchemaGetComponentQName(&str, type->baseType));
15409 FREE_AND_NULL(str)
15410 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15412 /* 1.2 The {final} of the {base type definition} must not contain
15413 * restriction.
15415 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15416 if (xmlSchemaTypeFinalContains(type->baseType,
15417 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15418 xmlSchemaPCustomErr(pctxt,
15419 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15420 WXS_BASIC_CAST type, NULL,
15421 "The final of its base type '%s' must not contain 'restriction'",
15422 xmlSchemaGetComponentQName(&str, type->baseType));
15423 FREE_AND_NULL(str)
15424 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15428 * 1.3.1 DF must be an allowed constraining facet for the {primitive
15429 * type definition}, as specified in the appropriate subsection of 3.2
15430 * Primitive datatypes.
15432 if (type->facets != NULL) {
15433 xmlSchemaFacetPtr facet;
15434 int ok = 1;
15436 primitive = xmlSchemaGetPrimitiveType(type);
15437 if (primitive == NULL) {
15438 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15439 "failed to get primitive type");
15440 return (-1);
15442 facet = type->facets;
15443 do {
15444 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15445 ok = 0;
15446 xmlSchemaPIllegalFacetAtomicErr(pctxt,
15447 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15448 type, primitive, facet);
15450 facet = facet->next;
15451 } while (facet != NULL);
15452 if (ok == 0)
15453 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15456 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15457 * of the {base type definition} (call this BF),then the DF's {value}
15458 * must be a valid restriction of BF's {value} as defined in
15459 * [XML Schemas: Datatypes]."
15461 * NOTE (1.3.2) Facet derivation constraints are currently handled in
15462 * xmlSchemaDeriveAndValidateFacets()
15464 } else if (WXS_IS_LIST(type)) {
15465 xmlSchemaTypePtr itemType = NULL;
15467 itemType = type->subtypes;
15468 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15469 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15470 "failed to evaluate the item type");
15471 return (-1);
15473 if (WXS_IS_TYPE_NOT_FIXED(itemType))
15474 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15476 * 2.1 The {item type definition} must have a {variety} of atomic or
15477 * union (in which case all the {member type definitions}
15478 * must be atomic).
15480 if ((! WXS_IS_ATOMIC(itemType)) &&
15481 (! WXS_IS_UNION(itemType))) {
15482 xmlSchemaPCustomErr(pctxt,
15483 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15484 WXS_BASIC_CAST type, NULL,
15485 "The item type '%s' does not have a variety of atomic or union",
15486 xmlSchemaGetComponentQName(&str, itemType));
15487 FREE_AND_NULL(str)
15488 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15489 } else if (WXS_IS_UNION(itemType)) {
15490 xmlSchemaTypeLinkPtr member;
15492 member = itemType->memberTypes;
15493 while (member != NULL) {
15494 if (! WXS_IS_ATOMIC(member->type)) {
15495 xmlSchemaPCustomErr(pctxt,
15496 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15497 WXS_BASIC_CAST type, NULL,
15498 "The item type is a union type, but the "
15499 "member type '%s' of this item type is not atomic",
15500 xmlSchemaGetComponentQName(&str, member->type));
15501 FREE_AND_NULL(str)
15502 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15504 member = member->next;
15508 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15509 xmlSchemaFacetPtr facet;
15511 * This is the case if we have: <simpleType><list ..
15514 * 2.3.1
15515 * 2.3.1.1 The {final} of the {item type definition} must not
15516 * contain list.
15518 if (xmlSchemaTypeFinalContains(itemType,
15519 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15520 xmlSchemaPCustomErr(pctxt,
15521 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15522 WXS_BASIC_CAST type, NULL,
15523 "The final of its item type '%s' must not contain 'list'",
15524 xmlSchemaGetComponentQName(&str, itemType));
15525 FREE_AND_NULL(str)
15526 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15529 * 2.3.1.2 The {facets} must only contain the whiteSpace
15530 * facet component.
15531 * OPTIMIZE TODO: the S4S already disallows any facet
15532 * to be specified.
15534 if (type->facets != NULL) {
15535 facet = type->facets;
15536 do {
15537 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15538 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15539 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15540 type, facet);
15541 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15543 facet = facet->next;
15544 } while (facet != NULL);
15547 * MAYBE TODO: (Hmm, not really) Datatypes states:
15548 * A `list` datatype can be `derived` from an `atomic` datatype
15549 * whose `lexical space` allows space (such as string or anyURI)or
15550 * a `union` datatype any of whose {member type definitions}'s
15551 * `lexical space` allows space.
15553 } else {
15555 * This is the case if we have: <simpleType><restriction ...
15556 * I.e. the variety of "list" is inherited.
15559 * 2.3.2
15560 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15562 if (! WXS_IS_LIST(type->baseType)) {
15563 xmlSchemaPCustomErr(pctxt,
15564 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15565 WXS_BASIC_CAST type, NULL,
15566 "The base type '%s' must be a list type",
15567 xmlSchemaGetComponentQName(&str, type->baseType));
15568 FREE_AND_NULL(str)
15569 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15572 * 2.3.2.2 The {final} of the {base type definition} must not
15573 * contain restriction.
15575 if (xmlSchemaTypeFinalContains(type->baseType,
15576 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15577 xmlSchemaPCustomErr(pctxt,
15578 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15579 WXS_BASIC_CAST type, NULL,
15580 "The 'final' of the base type '%s' must not contain 'restriction'",
15581 xmlSchemaGetComponentQName(&str, type->baseType));
15582 FREE_AND_NULL(str)
15583 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15586 * 2.3.2.3 The {item type definition} must be validly derived
15587 * from the {base type definition}'s {item type definition} given
15588 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15591 xmlSchemaTypePtr baseItemType;
15593 baseItemType = type->baseType->subtypes;
15594 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15595 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15596 "failed to eval the item type of a base type");
15597 return (-1);
15599 if ((itemType != baseItemType) &&
15600 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15601 baseItemType, 0) != 0)) {
15602 xmlChar *strBIT = NULL, *strBT = NULL;
15603 xmlSchemaPCustomErrExt(pctxt,
15604 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15605 WXS_BASIC_CAST type, NULL,
15606 "The item type '%s' is not validly derived from "
15607 "the item type '%s' of the base type '%s'",
15608 xmlSchemaGetComponentQName(&str, itemType),
15609 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15610 xmlSchemaGetComponentQName(&strBT, type->baseType));
15612 FREE_AND_NULL(str)
15613 FREE_AND_NULL(strBIT)
15614 FREE_AND_NULL(strBT)
15615 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15619 if (type->facets != NULL) {
15620 xmlSchemaFacetPtr facet;
15621 int ok = 1;
15623 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15624 * and enumeration facet components are allowed among the {facets}.
15626 facet = type->facets;
15627 do {
15628 switch (facet->type) {
15629 case XML_SCHEMA_FACET_LENGTH:
15630 case XML_SCHEMA_FACET_MINLENGTH:
15631 case XML_SCHEMA_FACET_MAXLENGTH:
15632 case XML_SCHEMA_FACET_WHITESPACE:
15634 * TODO: 2.5.1.2 List datatypes
15635 * The value of `whiteSpace` is fixed to the value collapse.
15637 case XML_SCHEMA_FACET_PATTERN:
15638 case XML_SCHEMA_FACET_ENUMERATION:
15639 break;
15640 default: {
15641 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15642 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15643 type, facet);
15645 * We could return, but it's nicer to report all
15646 * invalid facets.
15648 ok = 0;
15651 facet = facet->next;
15652 } while (facet != NULL);
15653 if (ok == 0)
15654 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15656 * SPEC (2.3.2.5) (same as 1.3.2)
15658 * NOTE (2.3.2.5) This is currently done in
15659 * xmlSchemaDeriveAndValidateFacets()
15663 } else if (WXS_IS_UNION(type)) {
15665 * 3.1 The {member type definitions} must all have {variety} of
15666 * atomic or list.
15668 xmlSchemaTypeLinkPtr member;
15670 member = type->memberTypes;
15671 while (member != NULL) {
15672 if (WXS_IS_TYPE_NOT_FIXED(member->type))
15673 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15675 if ((! WXS_IS_ATOMIC(member->type)) &&
15676 (! WXS_IS_LIST(member->type))) {
15677 xmlSchemaPCustomErr(pctxt,
15678 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15679 WXS_BASIC_CAST type, NULL,
15680 "The member type '%s' is neither an atomic, nor a list type",
15681 xmlSchemaGetComponentQName(&str, member->type));
15682 FREE_AND_NULL(str)
15683 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15685 member = member->next;
15688 * 3.3.1 If the {base type definition} is the `simple ur-type
15689 * definition`
15691 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15693 * 3.3.1.1 All of the {member type definitions} must have a
15694 * {final} which does not contain union.
15696 member = type->memberTypes;
15697 while (member != NULL) {
15698 if (xmlSchemaTypeFinalContains(member->type,
15699 XML_SCHEMAS_TYPE_FINAL_UNION)) {
15700 xmlSchemaPCustomErr(pctxt,
15701 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15702 WXS_BASIC_CAST type, NULL,
15703 "The 'final' of member type '%s' contains 'union'",
15704 xmlSchemaGetComponentQName(&str, member->type));
15705 FREE_AND_NULL(str)
15706 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15708 member = member->next;
15711 * 3.3.1.2 The {facets} must be empty.
15713 if (type->facetSet != NULL) {
15714 xmlSchemaPCustomErr(pctxt,
15715 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15716 WXS_BASIC_CAST type, NULL,
15717 "No facets allowed", NULL);
15718 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15720 } else {
15722 * 3.3.2.1 The {base type definition} must have a {variety} of union.
15723 * I.e. the variety of "list" is inherited.
15725 if (! WXS_IS_UNION(type->baseType)) {
15726 xmlSchemaPCustomErr(pctxt,
15727 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15728 WXS_BASIC_CAST type, NULL,
15729 "The base type '%s' is not a union type",
15730 xmlSchemaGetComponentQName(&str, type->baseType));
15731 FREE_AND_NULL(str)
15732 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15735 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15737 if (xmlSchemaTypeFinalContains(type->baseType,
15738 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15739 xmlSchemaPCustomErr(pctxt,
15740 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15741 WXS_BASIC_CAST type, NULL,
15742 "The 'final' of its base type '%s' must not contain 'restriction'",
15743 xmlSchemaGetComponentQName(&str, type->baseType));
15744 FREE_AND_NULL(str)
15745 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15748 * 3.3.2.3 The {member type definitions}, in order, must be validly
15749 * derived from the corresponding type definitions in the {base
15750 * type definition}'s {member type definitions} given the empty set,
15751 * as defined in Type Derivation OK (Simple) ($3.14.6).
15754 xmlSchemaTypeLinkPtr baseMember;
15757 * OPTIMIZE: if the type is restricting, it has no local defined
15758 * member types and inherits the member types of the base type;
15759 * thus a check for equality can be skipped.
15762 * Even worse: I cannot see a scenario where a restricting
15763 * union simple type can have other member types as the member
15764 * types of it's base type. This check seems not necessary with
15765 * respect to the derivation process in libxml2.
15766 * But necessary if constructing types with an API.
15768 if (type->memberTypes != NULL) {
15769 member = type->memberTypes;
15770 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15771 if ((member == NULL) && (baseMember != NULL)) {
15772 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15773 "different number of member types in base");
15775 while (member != NULL) {
15776 if (baseMember == NULL) {
15777 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15778 "different number of member types in base");
15779 } else if ((member->type != baseMember->type) &&
15780 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15781 member->type, baseMember->type, 0) != 0)) {
15782 xmlChar *strBMT = NULL, *strBT = NULL;
15784 xmlSchemaPCustomErrExt(pctxt,
15785 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15786 WXS_BASIC_CAST type, NULL,
15787 "The member type %s is not validly "
15788 "derived from its corresponding member "
15789 "type %s of the base type %s",
15790 xmlSchemaGetComponentQName(&str, member->type),
15791 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15792 xmlSchemaGetComponentQName(&strBT, type->baseType));
15793 FREE_AND_NULL(str)
15794 FREE_AND_NULL(strBMT)
15795 FREE_AND_NULL(strBT)
15796 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15798 member = member->next;
15799 if (baseMember != NULL)
15800 baseMember = baseMember->next;
15805 * 3.3.2.4 Only pattern and enumeration facet components are
15806 * allowed among the {facets}.
15808 if (type->facets != NULL) {
15809 xmlSchemaFacetPtr facet;
15810 int ok = 1;
15812 facet = type->facets;
15813 do {
15814 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15815 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15816 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15817 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15818 type, facet);
15819 ok = 0;
15821 facet = facet->next;
15822 } while (facet != NULL);
15823 if (ok == 0)
15824 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15828 * SPEC (3.3.2.5) (same as 1.3.2)
15830 * NOTE (3.3.2.5) This is currently done in
15831 * xmlSchemaDeriveAndValidateFacets()
15836 return (0);
15840 * xmlSchemaCheckSRCSimpleType:
15841 * @ctxt: the schema parser context
15842 * @type: the simple type definition
15844 * Checks crc-simple-type constraints.
15846 * Returns 0 if the constraints are satisfied,
15847 * if not a positive error code and -1 on internal
15848 * errors.
15850 #if 0
15851 static int
15852 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15853 xmlSchemaTypePtr type)
15856 * src-simple-type.1 The corresponding simple type definition, if any,
15857 * must satisfy the conditions set out in Constraints on Simple Type
15858 * Definition Schema Components ($3.14.6).
15860 if (WXS_IS_RESTRICTION(type)) {
15862 * src-simple-type.2 "If the <restriction> alternative is chosen,
15863 * either it must have a base [attribute] or a <simpleType> among its
15864 * [children], but not both."
15865 * NOTE: This is checked in the parse function of <restriction>.
15870 } else if (WXS_IS_LIST(type)) {
15871 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15872 * an itemType [attribute] or a <simpleType> among its [children],
15873 * but not both."
15875 * NOTE: This is checked in the parse function of <list>.
15877 } else if (WXS_IS_UNION(type)) {
15879 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15882 return (0);
15884 #endif
15886 static int
15887 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15889 if (ctxt->vctxt == NULL) {
15890 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15891 if (ctxt->vctxt == NULL) {
15892 xmlSchemaPErr(ctxt, NULL,
15893 XML_SCHEMAP_INTERNAL,
15894 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15895 "failed to create a temp. validation context.\n",
15896 NULL, NULL);
15897 return (-1);
15899 /* TODO: Pass user data. */
15900 xmlSchemaSetValidErrors(ctxt->vctxt,
15901 ctxt->error, ctxt->warning, ctxt->errCtxt);
15902 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15903 ctxt->serror, ctxt->errCtxt);
15905 return (0);
15908 static int
15909 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15910 xmlNodePtr node,
15911 xmlSchemaTypePtr type,
15912 const xmlChar *value,
15913 xmlSchemaValPtr *retVal,
15914 int fireErrors,
15915 int normalize,
15916 int isNormalized);
15919 * xmlSchemaParseCheckCOSValidDefault:
15920 * @pctxt: the schema parser context
15921 * @type: the simple type definition
15922 * @value: the default value
15923 * @node: an optional node (the holder of the value)
15925 * Schema Component Constraint: Element Default Valid (Immediate)
15926 * (cos-valid-default)
15927 * This will be used by the parser only. For the validator there's
15928 * an other version.
15930 * Returns 0 if the constraints are satisfied,
15931 * if not, a positive error code and -1 on internal
15932 * errors.
15934 static int
15935 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15936 xmlNodePtr node,
15937 xmlSchemaTypePtr type,
15938 const xmlChar *value,
15939 xmlSchemaValPtr *val)
15941 int ret = 0;
15944 * cos-valid-default:
15945 * Schema Component Constraint: Element Default Valid (Immediate)
15946 * For a string to be a valid default with respect to a type
15947 * definition the appropriate case among the following must be true:
15949 if WXS_IS_COMPLEX(type) {
15951 * Complex type.
15953 * SPEC (2.1) "its {content type} must be a simple type definition
15954 * or mixed."
15955 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15956 * type}'s particle must be `emptiable` as defined by
15957 * Particle Emptiable ($3.9.6)."
15959 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15960 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15961 /* NOTE that this covers (2.2.2) as well. */
15962 xmlSchemaPCustomErr(pctxt,
15963 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15964 WXS_BASIC_CAST type, type->node,
15965 "For a string to be a valid default, the type definition "
15966 "must be a simple type or a complex type with mixed content "
15967 "and a particle emptiable", NULL);
15968 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15972 * 1 If the type definition is a simple type definition, then the string
15973 * must be `valid` with respect to that definition as defined by String
15974 * Valid ($3.14.4).
15976 * AND
15978 * 2.2.1 If the {content type} is a simple type definition, then the
15979 * string must be `valid` with respect to that simple type definition
15980 * as defined by String Valid ($3.14.4).
15982 if (WXS_IS_SIMPLE(type))
15983 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15984 type, value, val, 1, 1, 0);
15985 else if (WXS_HAS_SIMPLE_CONTENT(type))
15986 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15987 type->contentTypeDef, value, val, 1, 1, 0);
15988 else
15989 return (ret);
15991 if (ret < 0) {
15992 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15993 "calling xmlSchemaVCheckCVCSimpleType()");
15996 return (ret);
16000 * xmlSchemaCheckCTPropsCorrect:
16001 * @ctxt: the schema parser context
16002 * @type: the complex type definition
16004 *.(4.6) Constraints on Complex Type Definition Schema Components
16005 * Schema Component Constraint:
16006 * Complex Type Definition Properties Correct (ct-props-correct)
16007 * STATUS: (seems) complete
16009 * Returns 0 if the constraints are satisfied, a positive
16010 * error code if not and -1 if an internal error occurred.
16012 static int
16013 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
16014 xmlSchemaTypePtr type)
16017 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
16019 * SPEC (1) "The values of the properties of a complex type definition must
16020 * be as described in the property tableau in The Complex Type Definition
16021 * Schema Component ($3.4.1), modulo the impact of Missing
16022 * Sub-components ($5.3)."
16024 if ((type->baseType != NULL) &&
16025 (WXS_IS_SIMPLE(type->baseType)) &&
16026 (WXS_IS_EXTENSION(type) == 0)) {
16028 * SPEC (2) "If the {base type definition} is a simple type definition,
16029 * the {derivation method} must be extension."
16031 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16032 XML_SCHEMAP_SRC_CT_1,
16033 NULL, WXS_BASIC_CAST type,
16034 "If the base type is a simple type, the derivation method must be "
16035 "'extension'", NULL, NULL);
16036 return (XML_SCHEMAP_SRC_CT_1);
16039 * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
16040 * definition`. That is, it must be possible to reach the `ur-type
16041 * definition` by repeatedly following the {base type definition}."
16043 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
16046 * NOTE that (4) and (5) need the following:
16047 * - attribute uses need to be already inherited (apply attr. prohibitions)
16048 * - attribute group references need to be expanded already
16049 * - simple types need to be typefixed already
16051 if (type->attrUses &&
16052 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
16054 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
16055 xmlSchemaAttributeUsePtr use, tmp;
16056 int i, j, hasId = 0;
16058 for (i = uses->nbItems -1; i >= 0; i--) {
16059 use = uses->items[i];
16062 * SPEC ct-props-correct
16063 * (4) "Two distinct attribute declarations in the
16064 * {attribute uses} must not have identical {name}s and
16065 * {target namespace}s."
16067 if (i > 0) {
16068 for (j = i -1; j >= 0; j--) {
16069 tmp = uses->items[j];
16070 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16071 WXS_ATTRUSE_DECL_NAME(tmp)) &&
16072 (WXS_ATTRUSE_DECL_TNS(use) ==
16073 WXS_ATTRUSE_DECL_TNS(tmp)))
16075 xmlChar *str = NULL;
16077 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16078 XML_SCHEMAP_AG_PROPS_CORRECT,
16079 NULL, WXS_BASIC_CAST type,
16080 "Duplicate %s",
16081 xmlSchemaGetComponentDesignation(&str, use),
16082 NULL);
16083 FREE_AND_NULL(str);
16085 * Remove the duplicate.
16087 if (xmlSchemaItemListRemove(uses, i) == -1)
16088 goto exit_failure;
16089 goto next_use;
16094 * SPEC ct-props-correct
16095 * (5) "Two distinct attribute declarations in the
16096 * {attribute uses} must not have {type definition}s which
16097 * are or are derived from ID."
16099 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
16100 if (xmlSchemaIsDerivedFromBuiltInType(
16101 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
16103 if (hasId) {
16104 xmlChar *str = NULL;
16106 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16107 XML_SCHEMAP_AG_PROPS_CORRECT,
16108 NULL, WXS_BASIC_CAST type,
16109 "There must not exist more than one attribute "
16110 "declaration of type 'xs:ID' "
16111 "(or derived from 'xs:ID'). The %s violates this "
16112 "constraint",
16113 xmlSchemaGetComponentDesignation(&str, use),
16114 NULL);
16115 FREE_AND_NULL(str);
16116 if (xmlSchemaItemListRemove(uses, i) == -1)
16117 goto exit_failure;
16120 hasId = 1;
16123 next_use: {}
16126 return (0);
16127 exit_failure:
16128 return(-1);
16131 static int
16132 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16133 xmlSchemaTypePtr typeB)
16136 * TODO: This should implement component-identity
16137 * in the future.
16139 if ((typeA == NULL) || (typeB == NULL))
16140 return (0);
16141 return (typeA == typeB);
16145 * xmlSchemaCheckCOSCTDerivedOK:
16146 * @ctxt: the schema parser context
16147 * @type: the to-be derived complex type definition
16148 * @baseType: the base complex type definition
16149 * @set: the given set
16151 * Schema Component Constraint:
16152 * Type Derivation OK (Complex) (cos-ct-derived-ok)
16154 * STATUS: completed
16156 * Returns 0 if the constraints are satisfied, or 1
16157 * if not.
16159 static int
16160 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16161 xmlSchemaTypePtr type,
16162 xmlSchemaTypePtr baseType,
16163 int set)
16165 int equal = xmlSchemaAreEqualTypes(type, baseType);
16166 /* TODO: Error codes. */
16168 * SPEC "For a complex type definition (call it D, for derived)
16169 * to be validly derived from a type definition (call this
16170 * B, for base) given a subset of {extension, restriction}
16171 * all of the following must be true:"
16173 if (! equal) {
16175 * SPEC (1) "If B and D are not the same type definition, then the
16176 * {derivation method} of D must not be in the subset."
16178 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16179 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16180 return (1);
16181 } else {
16183 * SPEC (2.1) "B and D must be the same type definition."
16185 return (0);
16188 * SPEC (2.2) "B must be D's {base type definition}."
16190 if (type->baseType == baseType)
16191 return (0);
16193 * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16194 * definition`."
16196 if (WXS_IS_ANYTYPE(type->baseType))
16197 return (1);
16199 if (WXS_IS_COMPLEX(type->baseType)) {
16201 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16202 * must be validly derived from B given the subset as defined by this
16203 * constraint."
16205 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16206 baseType, set));
16207 } else {
16209 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16210 * must be validly derived from B given the subset as defined in Type
16211 * Derivation OK (Simple) ($3.14.6).
16213 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16214 baseType, set));
16219 * xmlSchemaCheckCOSDerivedOK:
16220 * @type: the derived simple type definition
16221 * @baseType: the base type definition
16223 * Calls:
16224 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16226 * Checks whether @type can be validly derived from @baseType.
16228 * Returns 0 on success, an positive error code otherwise.
16230 static int
16231 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16232 xmlSchemaTypePtr type,
16233 xmlSchemaTypePtr baseType,
16234 int set)
16236 if (WXS_IS_SIMPLE(type))
16237 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16238 else
16239 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16243 * xmlSchemaCheckCOSCTExtends:
16244 * @ctxt: the schema parser context
16245 * @type: the complex type definition
16247 * (3.4.6) Constraints on Complex Type Definition Schema Components
16248 * Schema Component Constraint:
16249 * Derivation Valid (Extension) (cos-ct-extends)
16251 * STATUS:
16252 * missing:
16253 * (1.5)
16254 * (1.4.3.2.2.2) "Particle Valid (Extension)"
16256 * Returns 0 if the constraints are satisfied, a positive
16257 * error code if not and -1 if an internal error occurred.
16259 static int
16260 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16261 xmlSchemaTypePtr type)
16263 xmlSchemaTypePtr base = type->baseType;
16265 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16266 * temporarily only.
16269 * SPEC (1) "If the {base type definition} is a complex type definition,
16270 * then all of the following must be true:"
16272 if (WXS_IS_COMPLEX(base)) {
16274 * SPEC (1.1) "The {final} of the {base type definition} must not
16275 * contain extension."
16277 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16278 xmlSchemaPCustomErr(ctxt,
16279 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16280 WXS_BASIC_CAST type, NULL,
16281 "The 'final' of the base type definition "
16282 "contains 'extension'", NULL);
16283 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16287 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16288 * since they are automatically satisfied through the
16289 * inheriting mechanism.
16290 * Note that even if redefining components, the inheriting mechanism
16291 * is used.
16293 #if 0
16295 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16296 * uses}
16297 * of the complex type definition itself, that is, for every attribute
16298 * use in the {attribute uses} of the {base type definition}, there
16299 * must be an attribute use in the {attribute uses} of the complex
16300 * type definition itself whose {attribute declaration} has the same
16301 * {name}, {target namespace} and {type definition} as its attribute
16302 * declaration"
16304 if (base->attrUses != NULL) {
16305 int i, j, found;
16306 xmlSchemaAttributeUsePtr use, buse;
16308 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16309 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16310 found = 0;
16311 if (type->attrUses != NULL) {
16312 use = (WXS_LIST_CAST type->attrUses)->items[j];
16313 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16315 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16316 WXS_ATTRUSE_DECL_NAME(buse)) &&
16317 (WXS_ATTRUSE_DECL_TNS(use) ==
16318 WXS_ATTRUSE_DECL_TNS(buse)) &&
16319 (WXS_ATTRUSE_TYPEDEF(use) ==
16320 WXS_ATTRUSE_TYPEDEF(buse))
16322 found = 1;
16323 break;
16327 if (! found) {
16328 xmlChar *str = NULL;
16330 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16331 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16332 NULL, WXS_BASIC_CAST type,
16334 * TODO: The report does not indicate that also the
16335 * type needs to be the same.
16337 "This type is missing a matching correspondent "
16338 "for its {base type}'s %s in its {attribute uses}",
16339 xmlSchemaGetComponentDesignation(&str,
16340 buse->children),
16341 NULL);
16342 FREE_AND_NULL(str)
16347 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16348 * definition must also have one, and the base type definition's
16349 * {attribute wildcard}'s {namespace constraint} must be a subset
16350 * of the complex type definition's {attribute wildcard}'s {namespace
16351 * constraint}, as defined by Wildcard Subset ($3.10.6)."
16355 * MAYBE TODO: Enable if ever needed. But this will be needed only
16356 * if created the type via a schema construction API.
16358 if (base->attributeWildcard != NULL) {
16359 if (type->attributeWildcard == NULL) {
16360 xmlChar *str = NULL;
16362 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16363 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16364 NULL, type,
16365 "The base %s has an attribute wildcard, "
16366 "but this type is missing an attribute wildcard",
16367 xmlSchemaGetComponentDesignation(&str, base));
16368 FREE_AND_NULL(str)
16370 } else if (xmlSchemaCheckCOSNSSubset(
16371 base->attributeWildcard, type->attributeWildcard))
16373 xmlChar *str = NULL;
16375 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16376 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16377 NULL, type,
16378 "The attribute wildcard is not a valid "
16379 "superset of the one in the base %s",
16380 xmlSchemaGetComponentDesignation(&str, base));
16381 FREE_AND_NULL(str)
16384 #endif
16386 * SPEC (1.4) "One of the following must be true:"
16388 if ((type->contentTypeDef != NULL) &&
16389 (type->contentTypeDef == base->contentTypeDef)) {
16391 * SPEC (1.4.1) "The {content type} of the {base type definition}
16392 * and the {content type} of the complex type definition itself
16393 * must be the same simple type definition"
16394 * PASS
16396 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16397 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16399 * SPEC (1.4.2) "The {content type} of both the {base type
16400 * definition} and the complex type definition itself must
16401 * be empty."
16402 * PASS
16404 } else {
16406 * SPEC (1.4.3) "All of the following must be true:"
16408 if (type->subtypes == NULL) {
16410 * SPEC 1.4.3.1 The {content type} of the complex type
16411 * definition itself must specify a particle.
16413 xmlSchemaPCustomErr(ctxt,
16414 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16415 WXS_BASIC_CAST type, NULL,
16416 "The content type must specify a particle", NULL);
16417 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16420 * SPEC (1.4.3.2) "One of the following must be true:"
16422 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16424 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16425 * definition} must be empty.
16426 * PASS
16428 } else {
16430 * SPEC (1.4.3.2.2) "All of the following must be true:"
16432 if ((type->contentType != base->contentType) ||
16433 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16434 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16436 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16437 * or both must be element-only."
16439 xmlSchemaPCustomErr(ctxt,
16440 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16441 WXS_BASIC_CAST type, NULL,
16442 "The content type of both, the type and its base "
16443 "type, must either 'mixed' or 'element-only'", NULL);
16444 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16447 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16448 * complex type definition must be a `valid extension`
16449 * of the {base type definition}'s particle, as defined
16450 * in Particle Valid (Extension) ($3.9.6)."
16452 * NOTE that we won't check "Particle Valid (Extension)",
16453 * since it is ensured by the derivation process in
16454 * xmlSchemaTypeFixup(). We need to implement this when heading
16455 * for a construction API
16456 * TODO: !! This is needed to be checked if redefining a type !!
16460 * URGENT TODO (1.5)
16463 } else {
16465 * SPEC (2) "If the {base type definition} is a simple type definition,
16466 * then all of the following must be true:"
16468 if (type->contentTypeDef != base) {
16470 * SPEC (2.1) "The {content type} must be the same simple type
16471 * definition."
16473 xmlSchemaPCustomErr(ctxt,
16474 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16475 WXS_BASIC_CAST type, NULL,
16476 "The content type must be the simple base type", NULL);
16477 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16479 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16481 * SPEC (2.2) "The {final} of the {base type definition} must not
16482 * contain extension"
16483 * NOTE that this is the same as (1.1).
16485 xmlSchemaPCustomErr(ctxt,
16486 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16487 WXS_BASIC_CAST type, NULL,
16488 "The 'final' of the base type definition "
16489 "contains 'extension'", NULL);
16490 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16493 return (0);
16497 * xmlSchemaCheckDerivationOKRestriction:
16498 * @ctxt: the schema parser context
16499 * @type: the complex type definition
16501 * (3.4.6) Constraints on Complex Type Definition Schema Components
16502 * Schema Component Constraint:
16503 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16505 * STATUS:
16506 * missing:
16507 * (5.4.2) ???
16509 * ATTENTION:
16510 * In XML Schema 1.1 this will be:
16511 * Validation Rule: Checking complex type subsumption
16513 * Returns 0 if the constraints are satisfied, a positive
16514 * error code if not and -1 if an internal error occurred.
16516 static int
16517 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16518 xmlSchemaTypePtr type)
16520 xmlSchemaTypePtr base;
16523 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16524 * temporarily only.
16526 base = type->baseType;
16527 if (! WXS_IS_COMPLEX(base)) {
16528 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16529 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16530 type->node, WXS_BASIC_CAST type,
16531 "The base type must be a complex type", NULL, NULL);
16532 return(ctxt->err);
16534 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16536 * SPEC (1) "The {base type definition} must be a complex type
16537 * definition whose {final} does not contain restriction."
16539 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16540 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16541 type->node, WXS_BASIC_CAST type,
16542 "The 'final' of the base type definition "
16543 "contains 'restriction'", NULL, NULL);
16544 return (ctxt->err);
16547 * SPEC (2), (3) and (4)
16548 * Those are handled in a separate function, since the
16549 * same constraints are needed for redefinition of
16550 * attribute groups as well.
16552 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16553 XML_SCHEMA_ACTION_DERIVE,
16554 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16555 type->attrUses, base->attrUses,
16556 type->attributeWildcard,
16557 base->attributeWildcard) == -1)
16559 return(-1);
16562 * SPEC (5) "One of the following must be true:"
16564 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16566 * SPEC (5.1) "The {base type definition} must be the
16567 * `ur-type definition`."
16568 * PASS
16570 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16571 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16573 * SPEC (5.2.1) "The {content type} of the complex type definition
16574 * must be a simple type definition"
16576 * SPEC (5.2.2) "One of the following must be true:"
16578 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16579 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16581 int err;
16583 * SPEC (5.2.2.1) "The {content type} of the {base type
16584 * definition} must be a simple type definition from which
16585 * the {content type} is validly derived given the empty
16586 * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16588 * ATTENTION TODO: This seems not needed if the type implicitly
16589 * derived from the base type.
16592 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16593 type->contentTypeDef, base->contentTypeDef, 0);
16594 if (err != 0) {
16595 xmlChar *strA = NULL, *strB = NULL;
16597 if (err == -1)
16598 return(-1);
16599 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16600 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16601 NULL, WXS_BASIC_CAST type,
16602 "The {content type} %s is not validly derived from the "
16603 "base type's {content type} %s",
16604 xmlSchemaGetComponentDesignation(&strA,
16605 type->contentTypeDef),
16606 xmlSchemaGetComponentDesignation(&strB,
16607 base->contentTypeDef));
16608 FREE_AND_NULL(strA);
16609 FREE_AND_NULL(strB);
16610 return(ctxt->err);
16612 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16613 (xmlSchemaIsParticleEmptiable(
16614 (xmlSchemaParticlePtr) base->subtypes))) {
16616 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16617 * and have a particle which is `emptiable` as defined in
16618 * Particle Emptiable ($3.9.6)."
16619 * PASS
16621 } else {
16622 xmlSchemaPCustomErr(ctxt,
16623 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16624 WXS_BASIC_CAST type, NULL,
16625 "The content type of the base type must be either "
16626 "a simple type or 'mixed' and an emptiable particle", NULL);
16627 return (ctxt->err);
16629 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16631 * SPEC (5.3.1) "The {content type} of the complex type itself must
16632 * be empty"
16634 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16636 * SPEC (5.3.2.1) "The {content type} of the {base type
16637 * definition} must also be empty."
16638 * PASS
16640 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16641 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16642 xmlSchemaIsParticleEmptiable(
16643 (xmlSchemaParticlePtr) base->subtypes)) {
16645 * SPEC (5.3.2.2) "The {content type} of the {base type
16646 * definition} must be elementOnly or mixed and have a particle
16647 * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16648 * PASS
16650 } else {
16651 xmlSchemaPCustomErr(ctxt,
16652 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16653 WXS_BASIC_CAST type, NULL,
16654 "The content type of the base type must be either "
16655 "empty or 'mixed' (or 'elements-only') and an emptiable "
16656 "particle", NULL);
16657 return (ctxt->err);
16659 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16660 WXS_HAS_MIXED_CONTENT(type)) {
16662 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16663 * itself must be element-only"
16665 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16667 * SPEC (5.4.1.2) "The {content type} of the complex type
16668 * definition itself and of the {base type definition} must be
16669 * mixed"
16671 xmlSchemaPCustomErr(ctxt,
16672 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16673 WXS_BASIC_CAST type, NULL,
16674 "If the content type is 'mixed', then the content type of the "
16675 "base type must also be 'mixed'", NULL);
16676 return (ctxt->err);
16679 * SPEC (5.4.2) "The particle of the complex type definition itself
16680 * must be a `valid restriction` of the particle of the {content
16681 * type} of the {base type definition} as defined in Particle Valid
16682 * (Restriction) ($3.9.6).
16684 * URGENT TODO: (5.4.2)
16686 } else {
16687 xmlSchemaPCustomErr(ctxt,
16688 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16689 WXS_BASIC_CAST type, NULL,
16690 "The type is not a valid restriction of its base type", NULL);
16691 return (ctxt->err);
16693 return (0);
16697 * xmlSchemaCheckCTComponent:
16698 * @ctxt: the schema parser context
16699 * @type: the complex type definition
16701 * (3.4.6) Constraints on Complex Type Definition Schema Components
16703 * Returns 0 if the constraints are satisfied, a positive
16704 * error code if not and -1 if an internal error occurred.
16706 static int
16707 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16708 xmlSchemaTypePtr type)
16710 int ret;
16712 * Complex Type Definition Properties Correct
16714 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16715 if (ret != 0)
16716 return (ret);
16717 if (WXS_IS_EXTENSION(type))
16718 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16719 else
16720 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16721 return (ret);
16725 * xmlSchemaCheckSRCCT:
16726 * @ctxt: the schema parser context
16727 * @type: the complex type definition
16729 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16730 * Schema Representation Constraint:
16731 * Complex Type Definition Representation OK (src-ct)
16733 * Returns 0 if the constraints are satisfied, a positive
16734 * error code if not and -1 if an internal error occurred.
16736 static int
16737 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16738 xmlSchemaTypePtr type)
16740 xmlSchemaTypePtr base;
16741 int ret = 0;
16744 * TODO: Adjust the error codes here, as I used
16745 * XML_SCHEMAP_SRC_CT_1 only yet.
16747 base = type->baseType;
16748 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16750 * 1 If the <complexContent> alternative is chosen, the type definition
16751 * `resolved` to by the `actual value` of the base [attribute]
16752 * must be a complex type definition;
16754 if (! WXS_IS_COMPLEX(base)) {
16755 xmlChar *str = NULL;
16756 xmlSchemaPCustomErr(ctxt,
16757 XML_SCHEMAP_SRC_CT_1,
16758 WXS_BASIC_CAST type, type->node,
16759 "If using <complexContent>, the base type is expected to be "
16760 "a complex type. The base type '%s' is a simple type",
16761 xmlSchemaFormatQName(&str, base->targetNamespace,
16762 base->name));
16763 FREE_AND_NULL(str)
16764 return (XML_SCHEMAP_SRC_CT_1);
16766 } else {
16768 * SPEC
16769 * 2 If the <simpleContent> alternative is chosen, all of the
16770 * following must be true:
16771 * 2.1 The type definition `resolved` to by the `actual value` of the
16772 * base [attribute] must be one of the following:
16774 if (WXS_IS_SIMPLE(base)) {
16775 if (WXS_IS_EXTENSION(type) == 0) {
16776 xmlChar *str = NULL;
16778 * 2.1.3 only if the <extension> alternative is also
16779 * chosen, a simple type definition.
16781 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16782 xmlSchemaPCustomErr(ctxt,
16783 XML_SCHEMAP_SRC_CT_1,
16784 WXS_BASIC_CAST type, NULL,
16785 "If using <simpleContent> and <restriction>, the base "
16786 "type must be a complex type. The base type '%s' is "
16787 "a simple type",
16788 xmlSchemaFormatQName(&str, base->targetNamespace,
16789 base->name));
16790 FREE_AND_NULL(str)
16791 return (XML_SCHEMAP_SRC_CT_1);
16793 } else {
16794 /* Base type is a complex type. */
16795 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16796 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16798 * 2.1.1 a complex type definition whose {content type} is a
16799 * simple type definition;
16800 * PASS
16802 if (base->contentTypeDef == NULL) {
16803 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16804 WXS_BASIC_CAST type, NULL,
16805 "Internal error: xmlSchemaCheckSRCCT, "
16806 "'%s', base type has no content type",
16807 type->name);
16808 return (-1);
16810 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16811 (WXS_IS_RESTRICTION(type))) {
16814 * 2.1.2 only if the <restriction> alternative is also
16815 * chosen, a complex type definition whose {content type}
16816 * is mixed and a particle emptiable.
16818 if (! xmlSchemaIsParticleEmptiable(
16819 (xmlSchemaParticlePtr) base->subtypes)) {
16820 ret = XML_SCHEMAP_SRC_CT_1;
16821 } else
16823 * Attention: at this point the <simpleType> child is in
16824 * ->contentTypeDef (put there during parsing).
16826 if (type->contentTypeDef == NULL) {
16827 xmlChar *str = NULL;
16829 * 2.2 If clause 2.1.2 above is satisfied, then there
16830 * must be a <simpleType> among the [children] of
16831 * <restriction>.
16833 /* TODO: Change error code to ..._SRC_CT_2_2. */
16834 xmlSchemaPCustomErr(ctxt,
16835 XML_SCHEMAP_SRC_CT_1,
16836 WXS_BASIC_CAST type, NULL,
16837 "A <simpleType> is expected among the children "
16838 "of <restriction>, if <simpleContent> is used and "
16839 "the base type '%s' is a complex type",
16840 xmlSchemaFormatQName(&str, base->targetNamespace,
16841 base->name));
16842 FREE_AND_NULL(str)
16843 return (XML_SCHEMAP_SRC_CT_1);
16845 } else {
16846 ret = XML_SCHEMAP_SRC_CT_1;
16849 if (ret > 0) {
16850 xmlChar *str = NULL;
16851 if (WXS_IS_RESTRICTION(type)) {
16852 xmlSchemaPCustomErr(ctxt,
16853 XML_SCHEMAP_SRC_CT_1,
16854 WXS_BASIC_CAST type, NULL,
16855 "If <simpleContent> and <restriction> is used, the "
16856 "base type must be a simple type or a complex type with "
16857 "mixed content and particle emptiable. The base type "
16858 "'%s' is none of those",
16859 xmlSchemaFormatQName(&str, base->targetNamespace,
16860 base->name));
16861 } else {
16862 xmlSchemaPCustomErr(ctxt,
16863 XML_SCHEMAP_SRC_CT_1,
16864 WXS_BASIC_CAST type, NULL,
16865 "If <simpleContent> and <extension> is used, the "
16866 "base type must be a simple type. The base type '%s' "
16867 "is a complex type",
16868 xmlSchemaFormatQName(&str, base->targetNamespace,
16869 base->name));
16871 FREE_AND_NULL(str)
16875 * SPEC (3) "The corresponding complex type definition component must
16876 * satisfy the conditions set out in Constraints on Complex Type
16877 * Definition Schema Components ($3.4.6);"
16878 * NOTE (3) will be done in xmlSchemaTypeFixup().
16881 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16882 * above for {attribute wildcard} is satisfied, the intensional
16883 * intersection must be expressible, as defined in Attribute Wildcard
16884 * Intersection ($3.10.6).
16885 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16887 return (ret);
16890 #ifdef ENABLE_PARTICLE_RESTRICTION
16892 * xmlSchemaCheckParticleRangeOK:
16893 * @ctxt: the schema parser context
16894 * @type: the complex type definition
16896 * (3.9.6) Constraints on Particle Schema Components
16897 * Schema Component Constraint:
16898 * Occurrence Range OK (range-ok)
16900 * STATUS: complete
16902 * Returns 0 if the constraints are satisfied, a positive
16903 * error code if not and -1 if an internal error occurred.
16905 static int
16906 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16907 int bmin, int bmax)
16909 if (rmin < bmin)
16910 return (1);
16911 if ((bmax != UNBOUNDED) &&
16912 (rmax > bmax))
16913 return (1);
16914 return (0);
16918 * xmlSchemaCheckRCaseNameAndTypeOK:
16919 * @ctxt: the schema parser context
16920 * @r: the restricting element declaration particle
16921 * @b: the base element declaration particle
16923 * (3.9.6) Constraints on Particle Schema Components
16924 * Schema Component Constraint:
16925 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16926 * (rcase-NameAndTypeOK)
16928 * STATUS:
16929 * MISSING (3.2.3)
16930 * CLARIFY: (3.2.2)
16932 * Returns 0 if the constraints are satisfied, a positive
16933 * error code if not and -1 if an internal error occurred.
16935 static int
16936 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16937 xmlSchemaParticlePtr r,
16938 xmlSchemaParticlePtr b)
16940 xmlSchemaElementPtr elemR, elemB;
16942 /* TODO: Error codes (rcase-NameAndTypeOK). */
16943 elemR = (xmlSchemaElementPtr) r->children;
16944 elemB = (xmlSchemaElementPtr) b->children;
16946 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16947 * the same."
16949 if ((elemR != elemB) &&
16950 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16951 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16952 return (1);
16954 * SPEC (2) "R's occurrence range is a valid restriction of B's
16955 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16957 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16958 b->minOccurs, b->maxOccurs) != 0)
16959 return (1);
16961 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16962 * {scope} are global."
16964 if (elemR == elemB)
16965 return (0);
16967 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16969 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16970 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16971 return (1);
16973 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16974 * or is not fixed, or R's declaration's {value constraint} is fixed
16975 * with the same value."
16977 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16978 ((elemR->value == NULL) ||
16979 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16980 /* TODO: Equality of the initial value or normalized or canonical? */
16981 (! xmlStrEqual(elemR->value, elemB->value))))
16982 return (1);
16984 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16985 * definitions} is a subset of B's declaration's {identity-constraint
16986 * definitions}, if any."
16988 if (elemB->idcs != NULL) {
16989 /* TODO */
16992 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16993 * superset of B's declaration's {disallowed substitutions}."
16995 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16996 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16997 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16998 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16999 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
17000 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
17001 return (1);
17003 * SPEC (3.2.5) "R's {type definition} is validly derived given
17004 * {extension, list, union} from B's {type definition}"
17006 * BADSPEC TODO: What's the point of adding "list" and "union" to the
17007 * set, if the corresponding constraints handle "restriction" and
17008 * "extension" only?
17012 int set = 0;
17014 set |= SUBSET_EXTENSION;
17015 set |= SUBSET_LIST;
17016 set |= SUBSET_UNION;
17017 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
17018 elemB->subtypes, set) != 0)
17019 return (1);
17021 return (0);
17025 * xmlSchemaCheckRCaseNSCompat:
17026 * @ctxt: the schema parser context
17027 * @r: the restricting element declaration particle
17028 * @b: the base wildcard particle
17030 * (3.9.6) Constraints on Particle Schema Components
17031 * Schema Component Constraint:
17032 * Particle Derivation OK (Elt:Any -- NSCompat)
17033 * (rcase-NSCompat)
17035 * STATUS: complete
17037 * Returns 0 if the constraints are satisfied, a positive
17038 * error code if not and -1 if an internal error occurred.
17040 static int
17041 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
17042 xmlSchemaParticlePtr r,
17043 xmlSchemaParticlePtr b)
17045 /* TODO:Error codes (rcase-NSCompat). */
17047 * SPEC "For an element declaration particle to be a `valid restriction`
17048 * of a wildcard particle all of the following must be true:"
17050 * SPEC (1) "The element declaration's {target namespace} is `valid`
17051 * with respect to the wildcard's {namespace constraint} as defined by
17052 * Wildcard allows Namespace Name ($3.10.4)."
17054 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
17055 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
17056 return (1);
17058 * SPEC (2) "R's occurrence range is a valid restriction of B's
17059 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17061 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17062 b->minOccurs, b->maxOccurs) != 0)
17063 return (1);
17065 return (0);
17069 * xmlSchemaCheckRCaseRecurseAsIfGroup:
17070 * @ctxt: the schema parser context
17071 * @r: the restricting element declaration particle
17072 * @b: the base model group particle
17074 * (3.9.6) Constraints on Particle Schema Components
17075 * Schema Component Constraint:
17076 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
17077 * (rcase-RecurseAsIfGroup)
17079 * STATUS: TODO
17081 * Returns 0 if the constraints are satisfied, a positive
17082 * error code if not and -1 if an internal error occurred.
17084 static int
17085 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
17086 xmlSchemaParticlePtr r,
17087 xmlSchemaParticlePtr b)
17089 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
17090 TODO
17091 return (0);
17095 * xmlSchemaCheckRCaseNSSubset:
17096 * @ctxt: the schema parser context
17097 * @r: the restricting wildcard particle
17098 * @b: the base wildcard particle
17100 * (3.9.6) Constraints on Particle Schema Components
17101 * Schema Component Constraint:
17102 * Particle Derivation OK (Any:Any -- NSSubset)
17103 * (rcase-NSSubset)
17105 * STATUS: complete
17107 * Returns 0 if the constraints are satisfied, a positive
17108 * error code if not and -1 if an internal error occurred.
17110 static int
17111 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
17112 xmlSchemaParticlePtr r,
17113 xmlSchemaParticlePtr b,
17114 int isAnyTypeBase)
17116 /* TODO: Error codes (rcase-NSSubset). */
17118 * SPEC (1) "R's occurrence range is a valid restriction of B's
17119 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17121 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17122 b->minOccurs, b->maxOccurs))
17123 return (1);
17125 * SPEC (2) "R's {namespace constraint} must be an intensional subset
17126 * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17128 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17129 (xmlSchemaWildcardPtr) b->children))
17130 return (1);
17132 * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17133 * definition`, R's {process contents} must be identical to or stronger
17134 * than B's {process contents}, where strict is stronger than lax is
17135 * stronger than skip."
17137 if (! isAnyTypeBase) {
17138 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17139 ((xmlSchemaWildcardPtr) b->children)->processContents)
17140 return (1);
17143 return (0);
17147 * xmlSchemaCheckCOSParticleRestrict:
17148 * @ctxt: the schema parser context
17149 * @type: the complex type definition
17151 * (3.9.6) Constraints on Particle Schema Components
17152 * Schema Component Constraint:
17153 * Particle Valid (Restriction) (cos-particle-restrict)
17155 * STATUS: TODO
17157 * Returns 0 if the constraints are satisfied, a positive
17158 * error code if not and -1 if an internal error occurred.
17160 static int
17161 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17162 xmlSchemaParticlePtr r,
17163 xmlSchemaParticlePtr b)
17165 int ret = 0;
17167 /*part = WXS_TYPE_PARTICLE(type);
17168 basePart = WXS_TYPE_PARTICLE(base);
17171 TODO
17174 * SPEC (1) "They are the same particle."
17176 if (r == b)
17177 return (0);
17180 return (0);
17183 #if 0
17185 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17186 * @ctxt: the schema parser context
17187 * @r: the model group particle
17188 * @b: the base wildcard particle
17190 * (3.9.6) Constraints on Particle Schema Components
17191 * Schema Component Constraint:
17192 * Particle Derivation OK (All/Choice/Sequence:Any --
17193 * NSRecurseCheckCardinality)
17194 * (rcase-NSRecurseCheckCardinality)
17196 * STATUS: TODO: subst-groups
17198 * Returns 0 if the constraints are satisfied, a positive
17199 * error code if not and -1 if an internal error occurred.
17201 static int
17202 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17203 xmlSchemaParticlePtr r,
17204 xmlSchemaParticlePtr b)
17206 xmlSchemaParticlePtr part;
17207 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17208 if ((r->children == NULL) || (r->children->children == NULL))
17209 return (-1);
17211 * SPEC "For a group particle to be a `valid restriction` of a
17212 * wildcard particle..."
17214 * SPEC (1) "Every member of the {particles} of the group is a `valid
17215 * restriction` of the wildcard as defined by
17216 * Particle Valid (Restriction) ($3.9.6)."
17218 part = (xmlSchemaParticlePtr) r->children->children;
17219 do {
17220 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17221 return (1);
17222 part = (xmlSchemaParticlePtr) part->next;
17223 } while (part != NULL);
17225 * SPEC (2) "The effective total range of the group [...] is a
17226 * valid restriction of B's occurrence range as defined by
17227 * Occurrence Range OK ($3.9.6)."
17229 if (xmlSchemaCheckParticleRangeOK(
17230 xmlSchemaGetParticleTotalRangeMin(r),
17231 xmlSchemaGetParticleTotalRangeMax(r),
17232 b->minOccurs, b->maxOccurs) != 0)
17233 return (1);
17234 return (0);
17236 #endif
17239 * xmlSchemaCheckRCaseRecurse:
17240 * @ctxt: the schema parser context
17241 * @r: the <all> or <sequence> model group particle
17242 * @b: the base <all> or <sequence> model group particle
17244 * (3.9.6) Constraints on Particle Schema Components
17245 * Schema Component Constraint:
17246 * Particle Derivation OK (All:All,Sequence:Sequence --
17247 Recurse)
17248 * (rcase-Recurse)
17250 * STATUS: ?
17251 * TODO: subst-groups
17253 * Returns 0 if the constraints are satisfied, a positive
17254 * error code if not and -1 if an internal error occurred.
17256 static int
17257 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17258 xmlSchemaParticlePtr r,
17259 xmlSchemaParticlePtr b)
17261 /* xmlSchemaParticlePtr part; */
17262 /* TODO: Error codes (rcase-Recurse). */
17263 if ((r->children == NULL) || (b->children == NULL) ||
17264 (r->children->type != b->children->type))
17265 return (-1);
17267 * SPEC "For an all or sequence group particle to be a `valid
17268 * restriction` of another group particle with the same {compositor}..."
17270 * SPEC (1) "R's occurrence range is a valid restriction of B's
17271 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17273 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17274 b->minOccurs, b->maxOccurs))
17275 return (1);
17278 return (0);
17281 #endif
17283 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17284 xmlSchemaPCustomErrExt(pctxt, \
17285 XML_SCHEMAP_INVALID_FACET_VALUE, \
17286 WXS_BASIC_CAST fac1, fac1->node, \
17287 "It is an error for both '%s' and '%s' to be specified on the "\
17288 "same type definition", \
17289 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17290 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17292 #define FACET_RESTR_ERR(fac1, msg) \
17293 xmlSchemaPCustomErr(pctxt, \
17294 XML_SCHEMAP_INVALID_FACET_VALUE, \
17295 WXS_BASIC_CAST fac1, fac1->node, \
17296 msg, NULL);
17298 #define FACET_RESTR_FIXED_ERR(fac) \
17299 xmlSchemaPCustomErr(pctxt, \
17300 XML_SCHEMAP_INVALID_FACET_VALUE, \
17301 WXS_BASIC_CAST fac, fac->node, \
17302 "The base type's facet is 'fixed', thus the value must not " \
17303 "differ", NULL);
17305 static void
17306 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17307 xmlSchemaFacetPtr facet1,
17308 xmlSchemaFacetPtr facet2,
17309 int lessGreater,
17310 int orEqual,
17311 int ofBase)
17313 xmlChar *msg = NULL;
17315 msg = xmlStrdup(BAD_CAST "'");
17316 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17317 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17318 if (lessGreater == 0)
17319 msg = xmlStrcat(msg, BAD_CAST " equal to");
17320 if (lessGreater == 1)
17321 msg = xmlStrcat(msg, BAD_CAST " greater than");
17322 else
17323 msg = xmlStrcat(msg, BAD_CAST " less than");
17325 if (orEqual)
17326 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17327 msg = xmlStrcat(msg, BAD_CAST " '");
17328 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17329 if (ofBase)
17330 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17331 else
17332 msg = xmlStrcat(msg, BAD_CAST "'");
17334 xmlSchemaPCustomErr(pctxt,
17335 XML_SCHEMAP_INVALID_FACET_VALUE,
17336 WXS_BASIC_CAST facet1, NULL,
17337 (const char *) msg, NULL);
17339 if (msg != NULL)
17340 xmlFree(msg);
17344 * xmlSchemaDeriveAndValidateFacets:
17346 * Schema Component Constraint: Simple Type Restriction (Facets)
17347 * (st-restrict-facets)
17349 static int
17350 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17351 xmlSchemaTypePtr type)
17353 xmlSchemaTypePtr base = type->baseType;
17354 xmlSchemaFacetLinkPtr link, cur, last = NULL;
17355 xmlSchemaFacetPtr facet, bfacet,
17356 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17357 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17358 fmininc = NULL, fmaxinc = NULL,
17359 fminexc = NULL, fmaxexc = NULL,
17360 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17361 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17362 bfmininc = NULL, bfmaxinc = NULL,
17363 bfminexc = NULL, bfmaxexc = NULL;
17364 int res; /* err = 0, fixedErr; */
17367 * SPEC st-restrict-facets 1:
17368 * "The {variety} of R is the same as that of B."
17371 * SPEC st-restrict-facets 2:
17372 * "If {variety} is atomic, the {primitive type definition}
17373 * of R is the same as that of B."
17375 * NOTE: we leave 1 & 2 out for now, since this will be
17376 * satisfied by the derivation process.
17377 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17380 * SPEC st-restrict-facets 3:
17381 * "The {facets} of R are the union of S and the {facets}
17382 * of B, eliminating duplicates. To eliminate duplicates,
17383 * when a facet of the same kind occurs in both S and the
17384 * {facets} of B, the one in the {facets} of B is not
17385 * included, with the exception of enumeration and pattern
17386 * facets, for which multiple occurrences with distinct values
17387 * are allowed."
17390 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17391 return (0);
17393 last = type->facetSet;
17394 if (last != NULL)
17395 while (last->next != NULL)
17396 last = last->next;
17398 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17399 facet = cur->facet;
17400 switch (facet->type) {
17401 case XML_SCHEMA_FACET_LENGTH:
17402 flength = facet; break;
17403 case XML_SCHEMA_FACET_MINLENGTH:
17404 fminlen = facet; break;
17405 case XML_SCHEMA_FACET_MININCLUSIVE:
17406 fmininc = facet; break;
17407 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17408 fminexc = facet; break;
17409 case XML_SCHEMA_FACET_MAXLENGTH:
17410 fmaxlen = facet; break;
17411 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17412 fmaxinc = facet; break;
17413 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17414 fmaxexc = facet; break;
17415 case XML_SCHEMA_FACET_TOTALDIGITS:
17416 ftotdig = facet; break;
17417 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17418 ffracdig = facet; break;
17419 default:
17420 break;
17423 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17424 facet = cur->facet;
17425 switch (facet->type) {
17426 case XML_SCHEMA_FACET_LENGTH:
17427 bflength = facet; break;
17428 case XML_SCHEMA_FACET_MINLENGTH:
17429 bfminlen = facet; break;
17430 case XML_SCHEMA_FACET_MININCLUSIVE:
17431 bfmininc = facet; break;
17432 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17433 bfminexc = facet; break;
17434 case XML_SCHEMA_FACET_MAXLENGTH:
17435 bfmaxlen = facet; break;
17436 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17437 bfmaxinc = facet; break;
17438 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17439 bfmaxexc = facet; break;
17440 case XML_SCHEMA_FACET_TOTALDIGITS:
17441 bftotdig = facet; break;
17442 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17443 bffracdig = facet; break;
17444 default:
17445 break;
17449 * length and minLength or maxLength (2.2) + (3.2)
17451 if (flength && (fminlen || fmaxlen)) {
17452 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17453 "either of 'minLength' or 'maxLength' to be specified on "
17454 "the same type definition")
17457 * Mutual exclusions in the same derivation step.
17459 if ((fmaxinc) && (fmaxexc)) {
17461 * SCC "maxInclusive and maxExclusive"
17463 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17465 if ((fmininc) && (fminexc)) {
17467 * SCC "minInclusive and minExclusive"
17469 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17472 if (flength && bflength) {
17474 * SCC "length valid restriction"
17475 * The values have to be equal.
17477 res = xmlSchemaCompareValues(flength->val, bflength->val);
17478 if (res == -2)
17479 goto internal_error;
17480 if (res != 0)
17481 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17482 if ((res != 0) && (bflength->fixed)) {
17483 FACET_RESTR_FIXED_ERR(flength)
17487 if (fminlen && bfminlen) {
17489 * SCC "minLength valid restriction"
17490 * minLength >= BASE minLength
17492 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17493 if (res == -2)
17494 goto internal_error;
17495 if (res == -1)
17496 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17497 if ((res != 0) && (bfminlen->fixed)) {
17498 FACET_RESTR_FIXED_ERR(fminlen)
17501 if (fmaxlen && bfmaxlen) {
17503 * SCC "maxLength valid restriction"
17504 * maxLength <= BASE minLength
17506 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17507 if (res == -2)
17508 goto internal_error;
17509 if (res == 1)
17510 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17511 if ((res != 0) && (bfmaxlen->fixed)) {
17512 FACET_RESTR_FIXED_ERR(fmaxlen)
17516 * SCC "length and minLength or maxLength"
17518 if (! flength)
17519 flength = bflength;
17520 if (flength) {
17521 if (! fminlen)
17522 fminlen = bfminlen;
17523 if (fminlen) {
17524 /* (1.1) length >= minLength */
17525 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17526 if (res == -2)
17527 goto internal_error;
17528 if (res == -1)
17529 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17531 if (! fmaxlen)
17532 fmaxlen = bfmaxlen;
17533 if (fmaxlen) {
17534 /* (2.1) length <= maxLength */
17535 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17536 if (res == -2)
17537 goto internal_error;
17538 if (res == 1)
17539 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17542 if (fmaxinc) {
17544 * "maxInclusive"
17546 if (fmininc) {
17547 /* SCC "maxInclusive >= minInclusive" */
17548 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17549 if (res == -2)
17550 goto internal_error;
17551 if (res == -1) {
17552 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17556 * SCC "maxInclusive valid restriction"
17558 if (bfmaxinc) {
17559 /* maxInclusive <= BASE maxInclusive */
17560 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17561 if (res == -2)
17562 goto internal_error;
17563 if (res == 1)
17564 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17565 if ((res != 0) && (bfmaxinc->fixed)) {
17566 FACET_RESTR_FIXED_ERR(fmaxinc)
17569 if (bfmaxexc) {
17570 /* maxInclusive < BASE maxExclusive */
17571 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17572 if (res == -2)
17573 goto internal_error;
17574 if (res != -1) {
17575 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17578 if (bfmininc) {
17579 /* maxInclusive >= BASE minInclusive */
17580 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17581 if (res == -2)
17582 goto internal_error;
17583 if (res == -1) {
17584 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17587 if (bfminexc) {
17588 /* maxInclusive > BASE minExclusive */
17589 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17590 if (res == -2)
17591 goto internal_error;
17592 if (res != 1) {
17593 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17597 if (fmaxexc) {
17599 * "maxExclusive >= minExclusive"
17601 if (fminexc) {
17602 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17603 if (res == -2)
17604 goto internal_error;
17605 if (res == -1) {
17606 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17610 * "maxExclusive valid restriction"
17612 if (bfmaxexc) {
17613 /* maxExclusive <= BASE maxExclusive */
17614 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17615 if (res == -2)
17616 goto internal_error;
17617 if (res == 1) {
17618 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17620 if ((res != 0) && (bfmaxexc->fixed)) {
17621 FACET_RESTR_FIXED_ERR(fmaxexc)
17624 if (bfmaxinc) {
17625 /* maxExclusive <= BASE maxInclusive */
17626 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17627 if (res == -2)
17628 goto internal_error;
17629 if (res == 1) {
17630 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17633 if (bfmininc) {
17634 /* maxExclusive > BASE minInclusive */
17635 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17636 if (res == -2)
17637 goto internal_error;
17638 if (res != 1) {
17639 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17642 if (bfminexc) {
17643 /* maxExclusive > BASE minExclusive */
17644 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17645 if (res == -2)
17646 goto internal_error;
17647 if (res != 1) {
17648 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17652 if (fminexc) {
17654 * "minExclusive < maxInclusive"
17656 if (fmaxinc) {
17657 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17658 if (res == -2)
17659 goto internal_error;
17660 if (res != -1) {
17661 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17665 * "minExclusive valid restriction"
17667 if (bfminexc) {
17668 /* minExclusive >= BASE minExclusive */
17669 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17670 if (res == -2)
17671 goto internal_error;
17672 if (res == -1) {
17673 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17675 if ((res != 0) && (bfminexc->fixed)) {
17676 FACET_RESTR_FIXED_ERR(fminexc)
17679 if (bfmaxinc) {
17680 /* minExclusive <= BASE maxInclusive */
17681 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17682 if (res == -2)
17683 goto internal_error;
17684 if (res == 1) {
17685 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17688 if (bfmininc) {
17689 /* minExclusive >= BASE minInclusive */
17690 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17691 if (res == -2)
17692 goto internal_error;
17693 if (res == -1) {
17694 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17697 if (bfmaxexc) {
17698 /* minExclusive < BASE maxExclusive */
17699 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17700 if (res == -2)
17701 goto internal_error;
17702 if (res != -1) {
17703 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17707 if (fmininc) {
17709 * "minInclusive < maxExclusive"
17711 if (fmaxexc) {
17712 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17713 if (res == -2)
17714 goto internal_error;
17715 if (res != -1) {
17716 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17720 * "minExclusive valid restriction"
17722 if (bfmininc) {
17723 /* minInclusive >= BASE minInclusive */
17724 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17725 if (res == -2)
17726 goto internal_error;
17727 if (res == -1) {
17728 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17730 if ((res != 0) && (bfmininc->fixed)) {
17731 FACET_RESTR_FIXED_ERR(fmininc)
17734 if (bfmaxinc) {
17735 /* minInclusive <= BASE maxInclusive */
17736 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17737 if (res == -2)
17738 goto internal_error;
17739 if (res == 1) {
17740 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17743 if (bfminexc) {
17744 /* minInclusive > BASE minExclusive */
17745 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17746 if (res == -2)
17747 goto internal_error;
17748 if (res != 1)
17749 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17751 if (bfmaxexc) {
17752 /* minInclusive < BASE maxExclusive */
17753 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17754 if (res == -2)
17755 goto internal_error;
17756 if (res != -1)
17757 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17760 if (ftotdig && bftotdig) {
17762 * SCC " totalDigits valid restriction"
17763 * totalDigits <= BASE totalDigits
17765 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17766 if (res == -2)
17767 goto internal_error;
17768 if (res == 1)
17769 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17770 -1, 1, 1);
17771 if ((res != 0) && (bftotdig->fixed)) {
17772 FACET_RESTR_FIXED_ERR(ftotdig)
17775 if (ffracdig && bffracdig) {
17777 * SCC "fractionDigits valid restriction"
17778 * fractionDigits <= BASE fractionDigits
17780 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17781 if (res == -2)
17782 goto internal_error;
17783 if (res == 1)
17784 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17785 -1, 1, 1);
17786 if ((res != 0) && (bffracdig->fixed)) {
17787 FACET_RESTR_FIXED_ERR(ffracdig)
17791 * SCC "fractionDigits less than or equal to totalDigits"
17793 if (! ftotdig)
17794 ftotdig = bftotdig;
17795 if (! ffracdig)
17796 ffracdig = bffracdig;
17797 if (ftotdig && ffracdig) {
17798 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17799 if (res == -2)
17800 goto internal_error;
17801 if (res == 1)
17802 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17803 -1, 1, 0);
17806 * *Enumerations* won' be added here, since only the first set
17807 * of enumerations in the ancestor-or-self axis is used
17808 * for validation, plus we need to use the base type of those
17809 * enumerations for whitespace.
17811 * *Patterns*: won't be add here, since they are ORed at
17812 * type level and ANDed at ancestor level. This will
17813 * happen during validation by walking the base axis
17814 * of the type.
17816 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17817 bfacet = cur->facet;
17819 * Special handling of enumerations and patterns.
17820 * TODO: hmm, they should not appear in the set, so remove this.
17822 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17823 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17824 continue;
17826 * Search for a duplicate facet in the current type.
17828 link = type->facetSet;
17829 /* err = 0; */
17830 /* fixedErr = 0; */
17831 while (link != NULL) {
17832 facet = link->facet;
17833 if (facet->type == bfacet->type) {
17834 switch (facet->type) {
17835 case XML_SCHEMA_FACET_WHITESPACE:
17837 * The whitespace must be stronger.
17839 if (facet->whitespace < bfacet->whitespace) {
17840 FACET_RESTR_ERR(facet,
17841 "The 'whitespace' value has to be equal to "
17842 "or stronger than the 'whitespace' value of "
17843 "the base type")
17845 if ((bfacet->fixed) &&
17846 (facet->whitespace != bfacet->whitespace)) {
17847 FACET_RESTR_FIXED_ERR(facet)
17849 break;
17850 default:
17851 break;
17853 /* Duplicate found. */
17854 break;
17856 link = link->next;
17859 * If no duplicate was found: add the base types's facet
17860 * to the set.
17862 if (link == NULL) {
17863 link = (xmlSchemaFacetLinkPtr)
17864 xmlMalloc(sizeof(xmlSchemaFacetLink));
17865 if (link == NULL) {
17866 xmlSchemaPErrMemory(pctxt,
17867 "deriving facets, creating a facet link", NULL);
17868 return (-1);
17870 link->facet = cur->facet;
17871 link->next = NULL;
17872 if (last == NULL)
17873 type->facetSet = link;
17874 else
17875 last->next = link;
17876 last = link;
17881 return (0);
17882 internal_error:
17883 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17884 "an error occurred");
17885 return (-1);
17888 static int
17889 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17890 xmlSchemaTypePtr type)
17892 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17894 * The actual value is then formed by replacing any union type
17895 * definition in the `explicit members` with the members of their
17896 * {member type definitions}, in order.
17898 * TODO: There's a bug entry at
17899 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17900 * which indicates that we'll keep the union types the future.
17902 link = type->memberTypes;
17903 while (link != NULL) {
17905 if (WXS_IS_TYPE_NOT_FIXED(link->type))
17906 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17908 if (WXS_IS_UNION(link->type)) {
17909 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17910 if (subLink != NULL) {
17911 link->type = subLink->type;
17912 if (subLink->next != NULL) {
17913 lastLink = link->next;
17914 subLink = subLink->next;
17915 prevLink = link;
17916 while (subLink != NULL) {
17917 newLink = (xmlSchemaTypeLinkPtr)
17918 xmlMalloc(sizeof(xmlSchemaTypeLink));
17919 if (newLink == NULL) {
17920 xmlSchemaPErrMemory(pctxt, "allocating a type link",
17921 NULL);
17922 return (-1);
17924 newLink->type = subLink->type;
17925 prevLink->next = newLink;
17926 prevLink = newLink;
17927 newLink->next = lastLink;
17929 subLink = subLink->next;
17934 link = link->next;
17936 return (0);
17939 static void
17940 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17942 int has = 0, needVal = 0, normVal = 0;
17944 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17945 if (has) {
17946 needVal = (type->baseType->flags &
17947 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17948 normVal = (type->baseType->flags &
17949 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17951 if (type->facets != NULL) {
17952 xmlSchemaFacetPtr fac;
17954 for (fac = type->facets; fac != NULL; fac = fac->next) {
17955 switch (fac->type) {
17956 case XML_SCHEMA_FACET_WHITESPACE:
17957 break;
17958 case XML_SCHEMA_FACET_PATTERN:
17959 normVal = 1;
17960 has = 1;
17961 break;
17962 case XML_SCHEMA_FACET_ENUMERATION:
17963 needVal = 1;
17964 normVal = 1;
17965 has = 1;
17966 break;
17967 default:
17968 has = 1;
17969 break;
17973 if (normVal)
17974 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17975 if (needVal)
17976 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17977 if (has)
17978 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17980 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17981 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17983 * OPTIMIZE VAL TODO: Some facets need a computed value.
17985 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17986 (prim->builtInType != XML_SCHEMAS_STRING)) {
17987 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17992 static int
17993 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17998 * Evaluate the whitespace-facet value.
18000 if (WXS_IS_LIST(type)) {
18001 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18002 return (0);
18003 } else if (WXS_IS_UNION(type))
18004 return (0);
18006 if (type->facetSet != NULL) {
18007 xmlSchemaFacetLinkPtr lin;
18009 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
18010 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
18011 switch (lin->facet->whitespace) {
18012 case XML_SCHEMAS_FACET_PRESERVE:
18013 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18014 break;
18015 case XML_SCHEMAS_FACET_REPLACE:
18016 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18017 break;
18018 case XML_SCHEMAS_FACET_COLLAPSE:
18019 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18020 break;
18021 default:
18022 return (-1);
18024 return (0);
18029 * For all `atomic` datatypes other than string (and types `derived`
18030 * by `restriction` from it) the value of whiteSpace is fixed to
18031 * collapse
18034 xmlSchemaTypePtr anc;
18036 for (anc = type->baseType; anc != NULL &&
18037 anc->builtInType != XML_SCHEMAS_ANYTYPE;
18038 anc = anc->baseType) {
18040 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
18041 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
18042 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18044 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
18045 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
18046 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18048 } else
18049 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18050 break;
18054 return (0);
18057 static int
18058 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
18059 xmlSchemaTypePtr type)
18061 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18062 return(0);
18063 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
18064 return(0);
18065 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
18067 if (WXS_IS_LIST(type)) {
18069 * Corresponds to <simpleType><list>...
18071 if (type->subtypes == NULL) {
18073 * This one is really needed, so get out.
18075 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18076 "list type has no item-type assigned");
18077 return(-1);
18079 } else if (WXS_IS_UNION(type)) {
18081 * Corresponds to <simpleType><union>...
18083 if (type->memberTypes == NULL) {
18085 * This one is really needed, so get out.
18087 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18088 "union type has no member-types assigned");
18089 return(-1);
18091 } else {
18093 * Corresponds to <simpleType><restriction>...
18095 if (type->baseType == NULL) {
18096 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18097 "type has no base-type assigned");
18098 return(-1);
18100 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
18101 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
18102 return(-1);
18104 * Variety
18105 * If the <restriction> alternative is chosen, then the
18106 * {variety} of the {base type definition}.
18108 if (WXS_IS_ATOMIC(type->baseType))
18109 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
18110 else if (WXS_IS_LIST(type->baseType)) {
18111 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
18113 * Inherit the itemType.
18115 type->subtypes = type->baseType->subtypes;
18116 } else if (WXS_IS_UNION(type->baseType)) {
18117 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
18119 * NOTE that we won't assign the memberTypes of the base,
18120 * since this will make trouble when freeing them; we will
18121 * use a lookup function to access them instead.
18125 return(0);
18128 #ifdef DEBUG_TYPE
18129 static void
18130 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18131 xmlSchemaTypePtr type)
18133 if (type->node != NULL) {
18134 xmlGenericError(xmlGenericErrorContext,
18135 "Type of %s : %s:%d :", name,
18136 type->node->doc->URL,
18137 xmlGetLineNo(type->node));
18138 } else {
18139 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18141 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18142 switch (type->contentType) {
18143 case XML_SCHEMA_CONTENT_SIMPLE:
18144 xmlGenericError(xmlGenericErrorContext, "simple\n");
18145 break;
18146 case XML_SCHEMA_CONTENT_ELEMENTS:
18147 xmlGenericError(xmlGenericErrorContext, "elements\n");
18148 break;
18149 case XML_SCHEMA_CONTENT_UNKNOWN:
18150 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18151 break;
18152 case XML_SCHEMA_CONTENT_EMPTY:
18153 xmlGenericError(xmlGenericErrorContext, "empty\n");
18154 break;
18155 case XML_SCHEMA_CONTENT_MIXED:
18156 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18157 type->subtypes))
18158 xmlGenericError(xmlGenericErrorContext,
18159 "mixed as emptiable particle\n");
18160 else
18161 xmlGenericError(xmlGenericErrorContext, "mixed\n");
18162 break;
18163 /* Removed, since not used. */
18165 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18166 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18167 break;
18169 case XML_SCHEMA_CONTENT_BASIC:
18170 xmlGenericError(xmlGenericErrorContext, "basic\n");
18171 break;
18172 default:
18173 xmlGenericError(xmlGenericErrorContext,
18174 "not registered !!!\n");
18175 break;
18179 #endif
18182 * 3.14.6 Constraints on Simple Type Definition Schema Components
18184 static int
18185 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18186 xmlSchemaTypePtr type)
18188 int res, olderrs = pctxt->nberrors;
18190 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18191 return(-1);
18193 if (! WXS_IS_TYPE_NOT_FIXED(type))
18194 return(0);
18196 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18197 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18199 if (type->baseType == NULL) {
18200 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18201 "missing baseType");
18202 goto exit_failure;
18204 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18205 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18207 * If a member type of a union is a union itself, we need to substitute
18208 * that member type for its member types.
18209 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18210 * types in WXS 1.1.
18212 if ((type->memberTypes != NULL) &&
18213 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18214 return(-1);
18216 * SPEC src-simple-type 1
18217 * "The corresponding simple type definition, if any, must satisfy
18218 * the conditions set out in Constraints on Simple Type Definition
18219 * Schema Components ($3.14.6)."
18222 * Schema Component Constraint: Simple Type Definition Properties Correct
18223 * (st-props-correct)
18225 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18226 HFAILURE HERROR
18228 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18229 * (cos-st-restricts)
18231 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18232 HFAILURE HERROR
18234 * TODO: Removed the error report, since it got annoying to get an
18235 * extra error report, if anything failed until now.
18236 * Enable this if needed.
18238 * xmlSchemaPErr(ctxt, type->node,
18239 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18240 * "Simple type '%s' does not satisfy the constraints "
18241 * "on simple type definitions.\n",
18242 * type->name, NULL);
18245 * Schema Component Constraint: Simple Type Restriction (Facets)
18246 * (st-restrict-facets)
18248 res = xmlSchemaCheckFacetValues(type, pctxt);
18249 HFAILURE HERROR
18250 if ((type->facetSet != NULL) ||
18251 (type->baseType->facetSet != NULL)) {
18252 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18253 HFAILURE HERROR
18256 * Whitespace value.
18258 res = xmlSchemaTypeFixupWhitespace(type);
18259 HFAILURE HERROR
18260 xmlSchemaTypeFixupOptimFacets(type);
18262 exit_error:
18263 #ifdef DEBUG_TYPE
18264 xmlSchemaDebugFixedType(pctxt, type);
18265 #endif
18266 if (olderrs != pctxt->nberrors)
18267 return(pctxt->err);
18268 return(0);
18270 exit_failure:
18271 #ifdef DEBUG_TYPE
18272 xmlSchemaDebugFixedType(pctxt, type);
18273 #endif
18274 return(-1);
18277 static int
18278 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18279 xmlSchemaTypePtr type)
18281 int res = 0, olderrs = pctxt->nberrors;
18282 xmlSchemaTypePtr baseType = type->baseType;
18284 if (! WXS_IS_TYPE_NOT_FIXED(type))
18285 return(0);
18286 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18287 if (baseType == NULL) {
18288 PERROR_INT("xmlSchemaFixupComplexType",
18289 "missing baseType");
18290 goto exit_failure;
18293 * Fixup the base type.
18295 if (WXS_IS_TYPE_NOT_FIXED(baseType))
18296 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18297 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18299 * Skip fixup if the base type is invalid.
18300 * TODO: Generate a warning!
18302 return(0);
18305 * This basically checks if the base type can be derived.
18307 res = xmlSchemaCheckSRCCT(pctxt, type);
18308 HFAILURE HERROR
18310 * Fixup the content type.
18312 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18314 * Corresponds to <complexType><simpleContent>...
18316 if ((WXS_IS_COMPLEX(baseType)) &&
18317 (baseType->contentTypeDef != NULL) &&
18318 (WXS_IS_RESTRICTION(type))) {
18319 xmlSchemaTypePtr contentBase, content;
18320 #ifdef ENABLE_NAMED_LOCALS
18321 char buf[30];
18322 const xmlChar *tmpname;
18323 #endif
18325 * SPEC (1) If <restriction> + base type is <complexType>,
18326 * "whose own {content type} is a simple type..."
18328 if (type->contentTypeDef != NULL) {
18330 * SPEC (1.1) "the simple type definition corresponding to the
18331 * <simpleType> among the [children] of <restriction> if there
18332 * is one;"
18333 * Note that this "<simpleType> among the [children]" was put
18334 * into ->contentTypeDef during parsing.
18336 contentBase = type->contentTypeDef;
18337 type->contentTypeDef = NULL;
18338 } else {
18340 * (1.2) "...otherwise (<restriction> has no <simpleType>
18341 * among its [children]), the simple type definition which
18342 * is the {content type} of the ... base type."
18344 contentBase = baseType->contentTypeDef;
18347 * SPEC
18348 * "... a simple type definition which restricts the simple
18349 * type definition identified in clause 1.1 or clause 1.2
18350 * with a set of facet components"
18352 * Create the anonymous simple type, which will be the content
18353 * type of the complex type.
18355 #ifdef ENABLE_NAMED_LOCALS
18356 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18357 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18358 content = xmlSchemaAddType(pctxt, pctxt->schema,
18359 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18360 type->node, 0);
18361 #else
18362 content = xmlSchemaAddType(pctxt, pctxt->schema,
18363 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18364 type->node, 0);
18365 #endif
18366 if (content == NULL)
18367 goto exit_failure;
18369 * We will use the same node as for the <complexType>
18370 * to have it somehow anchored in the schema doc.
18372 content->type = XML_SCHEMA_TYPE_SIMPLE;
18373 content->baseType = contentBase;
18375 * Move the facets, previously anchored on the
18376 * complexType during parsing.
18378 content->facets = type->facets;
18379 type->facets = NULL;
18380 content->facetSet = type->facetSet;
18381 type->facetSet = NULL;
18383 type->contentTypeDef = content;
18384 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18385 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18387 * Fixup the newly created type. We don't need to check
18388 * for circularity here.
18390 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18391 HFAILURE HERROR
18392 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18393 HFAILURE HERROR
18395 } else if ((WXS_IS_COMPLEX(baseType)) &&
18396 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18397 (WXS_IS_RESTRICTION(type))) {
18399 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18400 * an emptiable particle, then a simple type definition which
18401 * restricts the <restriction>'s <simpleType> child.
18403 if ((type->contentTypeDef == NULL) ||
18404 (type->contentTypeDef->baseType == NULL)) {
18406 * TODO: Check if this ever happens.
18408 xmlSchemaPCustomErr(pctxt,
18409 XML_SCHEMAP_INTERNAL,
18410 WXS_BASIC_CAST type, NULL,
18411 "Internal error: xmlSchemaTypeFixup, "
18412 "complex type '%s': the <simpleContent><restriction> "
18413 "is missing a <simpleType> child, but was not caught "
18414 "by xmlSchemaCheckSRCCT()", type->name);
18415 goto exit_failure;
18417 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18419 * SPEC (3) If <extension> + base is <complexType> with
18420 * <simpleType> content, "...then the {content type} of that
18421 * complex type definition"
18423 if (baseType->contentTypeDef == NULL) {
18425 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18426 * should have caught this already.
18428 xmlSchemaPCustomErr(pctxt,
18429 XML_SCHEMAP_INTERNAL,
18430 WXS_BASIC_CAST type, NULL,
18431 "Internal error: xmlSchemaTypeFixup, "
18432 "complex type '%s': the <extension>ed base type is "
18433 "a complex type with no simple content type",
18434 type->name);
18435 goto exit_failure;
18437 type->contentTypeDef = baseType->contentTypeDef;
18438 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18440 * SPEC (4) <extension> + base is <simpleType>
18441 * "... then that simple type definition"
18443 type->contentTypeDef = baseType;
18444 } else {
18446 * TODO: Check if this ever happens.
18448 xmlSchemaPCustomErr(pctxt,
18449 XML_SCHEMAP_INTERNAL,
18450 WXS_BASIC_CAST type, NULL,
18451 "Internal error: xmlSchemaTypeFixup, "
18452 "complex type '%s' with <simpleContent>: unhandled "
18453 "derivation case", type->name);
18454 goto exit_failure;
18456 } else {
18457 int dummySequence = 0;
18458 xmlSchemaParticlePtr particle =
18459 (xmlSchemaParticlePtr) type->subtypes;
18461 * Corresponds to <complexType><complexContent>...
18463 * NOTE that the effective mixed was already set during parsing of
18464 * <complexType> and <complexContent>; its flag value is
18465 * XML_SCHEMAS_TYPE_MIXED.
18467 * Compute the "effective content":
18468 * (2.1.1) + (2.1.2) + (2.1.3)
18470 if ((particle == NULL) ||
18471 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18472 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18473 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18474 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18475 (particle->minOccurs == 0))) &&
18476 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18477 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18479 * SPEC (2.1.4) "If the `effective mixed` is true, then
18480 * a particle whose properties are as follows:..."
18482 * Empty sequence model group with
18483 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18484 * NOTE that we sill assign it the <complexType> node to
18485 * somehow anchor it in the doc.
18487 if ((particle == NULL) ||
18488 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18490 * Create the particle.
18492 particle = xmlSchemaAddParticle(pctxt,
18493 type->node, 1, 1);
18494 if (particle == NULL)
18495 goto exit_failure;
18497 * Create the model group.
18498 */ /* URGENT TODO: avoid adding to pending items. */
18499 particle->children = (xmlSchemaTreeItemPtr)
18500 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18501 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18502 if (particle->children == NULL)
18503 goto exit_failure;
18505 type->subtypes = (xmlSchemaTypePtr) particle;
18507 dummySequence = 1;
18508 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18509 } else {
18511 * SPEC (2.1.5) "otherwise empty"
18513 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18515 } else {
18517 * SPEC (2.2) "otherwise the particle corresponding to the
18518 * <all>, <choice>, <group> or <sequence> among the
18519 * [children]."
18521 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18524 * Compute the "content type".
18526 if (WXS_IS_RESTRICTION(type)) {
18528 * SPEC (3.1) "If <restriction>..."
18529 * (3.1.1) + (3.1.2) */
18530 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18531 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18532 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18534 } else {
18536 * SPEC (3.2) "If <extension>..."
18538 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18540 * SPEC (3.2.1)
18541 * "If the `effective content` is empty, then the
18542 * {content type} of the [...] base ..."
18544 type->contentType = baseType->contentType;
18545 type->subtypes = baseType->subtypes;
18547 * Fixes bug #347316:
18548 * This is the case when the base type has a simple
18549 * type definition as content.
18551 type->contentTypeDef = baseType->contentTypeDef;
18553 * NOTE that the effective mixed is ignored here.
18555 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18557 * SPEC (3.2.2)
18559 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18560 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18561 } else {
18563 * SPEC (3.2.3)
18565 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18566 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18568 * "A model group whose {compositor} is sequence and whose
18569 * {particles} are..."
18571 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18572 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18573 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18574 XML_SCHEMA_TYPE_ALL))
18577 * SPEC cos-all-limited (1)
18579 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18580 /* TODO: error code */
18581 XML_SCHEMAP_COS_ALL_LIMITED,
18582 WXS_ITEM_NODE(type), NULL,
18583 "The type has an 'all' model group in its "
18584 "{content type} and thus cannot be derived from "
18585 "a non-empty type, since this would produce a "
18586 "'sequence' model group containing the 'all' "
18587 "model group; 'all' model groups are not "
18588 "allowed to appear inside other model groups",
18589 NULL, NULL);
18591 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18592 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18593 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18594 XML_SCHEMA_TYPE_ALL))
18597 * SPEC cos-all-limited (1)
18599 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18600 /* TODO: error code */
18601 XML_SCHEMAP_COS_ALL_LIMITED,
18602 WXS_ITEM_NODE(type), NULL,
18603 "A type cannot be derived by extension from a type "
18604 "which has an 'all' model group in its "
18605 "{content type}, since this would produce a "
18606 "'sequence' model group containing the 'all' "
18607 "model group; 'all' model groups are not "
18608 "allowed to appear inside other model groups",
18609 NULL, NULL);
18611 } else if (! dummySequence) {
18612 xmlSchemaTreeItemPtr effectiveContent =
18613 (xmlSchemaTreeItemPtr) type->subtypes;
18615 * Create the particle.
18617 particle = xmlSchemaAddParticle(pctxt,
18618 type->node, 1, 1);
18619 if (particle == NULL)
18620 goto exit_failure;
18622 * Create the "sequence" model group.
18624 particle->children = (xmlSchemaTreeItemPtr)
18625 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18626 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18627 if (particle->children == NULL)
18628 goto exit_failure;
18629 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18631 * SPEC "the particle of the {content type} of
18632 * the ... base ..."
18633 * Create a duplicate of the base type's particle
18634 * and assign its "term" to it.
18636 particle->children->children =
18637 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18638 type->node,
18639 ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18640 ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18641 if (particle->children->children == NULL)
18642 goto exit_failure;
18643 particle = (xmlSchemaParticlePtr)
18644 particle->children->children;
18645 particle->children =
18646 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18648 * SPEC "followed by the `effective content`."
18650 particle->next = effectiveContent;
18652 * This all will result in:
18653 * new-particle
18654 * --> new-sequence(
18655 * new-particle
18656 * --> base-model,
18657 * this-particle
18658 * --> this-model
18661 } else {
18663 * This is the case when there is already an empty
18664 * <sequence> with minOccurs==maxOccurs==1.
18665 * Just add the base types's content type.
18666 * NOTE that, although we miss to add an intermediate
18667 * <sequence>, this should produce no difference to
18668 * neither the regex compilation of the content model,
18669 * nor to the complex type constraints.
18671 particle->children->children =
18672 (xmlSchemaTreeItemPtr) baseType->subtypes;
18678 * Now fixup attribute uses:
18679 * - expand attr. group references
18680 * - intersect attribute wildcards
18681 * - inherit attribute uses of the base type
18682 * - inherit or union attr. wildcards if extending
18683 * - apply attr. use prohibitions if restricting
18685 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18686 HFAILURE HERROR
18688 * Apply the complex type component constraints; this will not
18689 * check attributes, since this is done in
18690 * xmlSchemaFixupTypeAttributeUses().
18692 res = xmlSchemaCheckCTComponent(pctxt, type);
18693 HFAILURE HERROR
18695 #ifdef DEBUG_TYPE
18696 xmlSchemaDebugFixedType(pctxt, type);
18697 #endif
18698 if (olderrs != pctxt->nberrors)
18699 return(pctxt->err);
18700 else
18701 return(0);
18703 exit_error:
18704 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18705 #ifdef DEBUG_TYPE
18706 xmlSchemaDebugFixedType(pctxt, type);
18707 #endif
18708 return(pctxt->err);
18710 exit_failure:
18711 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18712 #ifdef DEBUG_TYPE
18713 xmlSchemaDebugFixedType(pctxt, type);
18714 #endif
18715 return(-1);
18720 * xmlSchemaTypeFixup:
18721 * @typeDecl: the schema type definition
18722 * @ctxt: the schema parser context
18724 * Fixes the content model of the type.
18725 * URGENT TODO: We need an int result!
18727 static int
18728 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18729 xmlSchemaAbstractCtxtPtr actxt)
18731 if (type == NULL)
18732 return(0);
18733 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18734 AERROR_INT("xmlSchemaTypeFixup",
18735 "this function needs a parser context");
18736 return(-1);
18738 if (! WXS_IS_TYPE_NOT_FIXED(type))
18739 return(0);
18740 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18741 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18742 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18743 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18744 return(0);
18748 * xmlSchemaCheckFacet:
18749 * @facet: the facet
18750 * @typeDecl: the schema type definition
18751 * @pctxt: the schema parser context or NULL
18752 * @name: the optional name of the type
18754 * Checks and computes the values of facets.
18756 * Returns 0 if valid, a positive error code if not valid and
18757 * -1 in case of an internal or API error.
18760 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18761 xmlSchemaTypePtr typeDecl,
18762 xmlSchemaParserCtxtPtr pctxt,
18763 const xmlChar * name ATTRIBUTE_UNUSED)
18765 int ret = 0, ctxtGiven;
18767 if ((facet == NULL) || (typeDecl == NULL))
18768 return(-1);
18770 * TODO: will the parser context be given if used from
18771 * the relaxNG module?
18773 if (pctxt == NULL)
18774 ctxtGiven = 0;
18775 else
18776 ctxtGiven = 1;
18778 switch (facet->type) {
18779 case XML_SCHEMA_FACET_MININCLUSIVE:
18780 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18781 case XML_SCHEMA_FACET_MAXINCLUSIVE:
18782 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18783 case XML_SCHEMA_FACET_ENUMERATION: {
18785 * Okay we need to validate the value
18786 * at that point.
18788 xmlSchemaTypePtr base;
18790 /* 4.3.5.5 Constraints on enumeration Schema Components
18791 * Schema Component Constraint: enumeration valid restriction
18792 * It is an `error` if any member of {value} is not in the
18793 * `value space` of {base type definition}.
18795 * minInclusive, maxInclusive, minExclusive, maxExclusive:
18796 * The value `must` be in the
18797 * `value space` of the `base type`.
18800 * This function is intended to deliver a compiled value
18801 * on the facet. In this implementation of XML Schemata the
18802 * type holding a facet, won't be a built-in type.
18803 * Thus to ensure that other API
18804 * calls (relaxng) do work, if the given type is a built-in
18805 * type, we will assume that the given built-in type *is
18806 * already* the base type.
18808 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18809 base = typeDecl->baseType;
18810 if (base == NULL) {
18811 PERROR_INT("xmlSchemaCheckFacet",
18812 "a type user derived type has no base type");
18813 return (-1);
18815 } else
18816 base = typeDecl;
18818 if (! ctxtGiven) {
18820 * A context is needed if called from RelaxNG.
18822 pctxt = xmlSchemaNewParserCtxt("*");
18823 if (pctxt == NULL)
18824 return (-1);
18827 * NOTE: This call does not check the content nodes,
18828 * since they are not available:
18829 * facet->node is just the node holding the facet
18830 * definition, *not* the attribute holding the *value*
18831 * of the facet.
18833 ret = xmlSchemaVCheckCVCSimpleType(
18834 ACTXT_CAST pctxt, facet->node, base,
18835 facet->value, &(facet->val), 1, 1, 0);
18836 if (ret != 0) {
18837 if (ret < 0) {
18838 /* No error message for RelaxNG. */
18839 if (ctxtGiven) {
18840 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18841 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18842 "Internal error: xmlSchemaCheckFacet, "
18843 "failed to validate the value '%s' of the "
18844 "facet '%s' against the base type",
18845 facet->value, xmlSchemaFacetTypeToString(facet->type));
18847 goto internal_error;
18849 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18850 /* No error message for RelaxNG. */
18851 if (ctxtGiven) {
18852 xmlChar *str = NULL;
18854 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18855 ret, facet->node, WXS_BASIC_CAST facet,
18856 "The value '%s' of the facet does not validate "
18857 "against the base type '%s'",
18858 facet->value,
18859 xmlSchemaFormatQName(&str,
18860 base->targetNamespace, base->name));
18861 FREE_AND_NULL(str);
18863 goto exit;
18864 } else if (facet->val == NULL) {
18865 if (ctxtGiven) {
18866 PERROR_INT("xmlSchemaCheckFacet",
18867 "value was not computed");
18869 TODO
18871 break;
18873 case XML_SCHEMA_FACET_PATTERN:
18874 facet->regexp = xmlRegexpCompile(facet->value);
18875 if (facet->regexp == NULL) {
18876 ret = XML_SCHEMAP_REGEXP_INVALID;
18877 /* No error message for RelaxNG. */
18878 if (ctxtGiven) {
18879 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18880 ret, facet->node, WXS_BASIC_CAST typeDecl,
18881 "The value '%s' of the facet 'pattern' is not a "
18882 "valid regular expression",
18883 facet->value, NULL);
18886 break;
18887 case XML_SCHEMA_FACET_TOTALDIGITS:
18888 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18889 case XML_SCHEMA_FACET_LENGTH:
18890 case XML_SCHEMA_FACET_MAXLENGTH:
18891 case XML_SCHEMA_FACET_MINLENGTH:
18893 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18894 ret = xmlSchemaValidatePredefinedType(
18895 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18896 facet->value, &(facet->val));
18897 } else {
18898 ret = xmlSchemaValidatePredefinedType(
18899 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18900 facet->value, &(facet->val));
18902 if (ret != 0) {
18903 if (ret < 0) {
18904 /* No error message for RelaxNG. */
18905 if (ctxtGiven) {
18906 PERROR_INT("xmlSchemaCheckFacet",
18907 "validating facet value");
18909 goto internal_error;
18911 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18912 /* No error message for RelaxNG. */
18913 if (ctxtGiven) {
18914 /* error code */
18915 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18916 ret, facet->node, WXS_BASIC_CAST typeDecl,
18917 "The value '%s' of the facet '%s' is not a valid '%s'",
18918 facet->value,
18919 xmlSchemaFacetTypeToString(facet->type),
18920 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18921 BAD_CAST "nonNegativeInteger" :
18922 BAD_CAST "positiveInteger",
18923 NULL);
18926 break;
18928 case XML_SCHEMA_FACET_WHITESPACE:{
18929 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18930 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18931 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18932 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18933 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18934 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18935 } else {
18936 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18937 /* No error message for RelaxNG. */
18938 if (ctxtGiven) {
18939 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18940 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18941 ret, facet->node, WXS_BASIC_CAST typeDecl,
18942 "The value '%s' of the facet 'whitespace' is not "
18943 "valid", facet->value, NULL);
18947 default:
18948 break;
18950 exit:
18951 if ((! ctxtGiven) && (pctxt != NULL))
18952 xmlSchemaFreeParserCtxt(pctxt);
18953 return (ret);
18954 internal_error:
18955 if ((! ctxtGiven) && (pctxt != NULL))
18956 xmlSchemaFreeParserCtxt(pctxt);
18957 return (-1);
18961 * xmlSchemaCheckFacetValues:
18962 * @typeDecl: the schema type definition
18963 * @ctxt: the schema parser context
18965 * Checks the default values types, especially for facets
18967 static int
18968 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18969 xmlSchemaParserCtxtPtr pctxt)
18971 int res, olderrs = pctxt->nberrors;
18972 const xmlChar *name = typeDecl->name;
18974 * NOTE: It is intended to use the facets list, instead
18975 * of facetSet.
18977 if (typeDecl->facets != NULL) {
18978 xmlSchemaFacetPtr facet = typeDecl->facets;
18981 * Temporarily assign the "schema" to the validation context
18982 * of the parser context. This is needed for NOTATION validation.
18984 if (pctxt->vctxt == NULL) {
18985 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18986 return(-1);
18988 pctxt->vctxt->schema = pctxt->schema;
18989 while (facet != NULL) {
18990 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18991 HFAILURE
18992 facet = facet->next;
18994 pctxt->vctxt->schema = NULL;
18996 if (olderrs != pctxt->nberrors)
18997 return(pctxt->err);
18998 return(0);
18999 exit_failure:
19000 return(-1);
19004 * xmlSchemaGetCircModelGrDefRef:
19005 * @ctxtMGroup: the searched model group
19006 * @selfMGroup: the second searched model group
19007 * @particle: the first particle
19009 * This one is intended to be used by
19010 * xmlSchemaCheckGroupDefCircular only.
19012 * Returns the particle with the circular model group definition reference,
19013 * otherwise NULL.
19015 static xmlSchemaTreeItemPtr
19016 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
19017 xmlSchemaTreeItemPtr particle)
19019 xmlSchemaTreeItemPtr circ = NULL;
19020 xmlSchemaTreeItemPtr term;
19021 xmlSchemaModelGroupDefPtr gdef;
19023 for (; particle != NULL; particle = particle->next) {
19024 term = particle->children;
19025 if (term == NULL)
19026 continue;
19027 switch (term->type) {
19028 case XML_SCHEMA_TYPE_GROUP:
19029 gdef = (xmlSchemaModelGroupDefPtr) term;
19030 if (gdef == groupDef)
19031 return (particle);
19033 * Mark this model group definition to avoid infinite
19034 * recursion on circular references not yet examined.
19036 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
19037 continue;
19038 if (gdef->children != NULL) {
19039 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19040 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
19041 gdef->children->children);
19042 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19043 if (circ != NULL)
19044 return (circ);
19046 break;
19047 case XML_SCHEMA_TYPE_SEQUENCE:
19048 case XML_SCHEMA_TYPE_CHOICE:
19049 case XML_SCHEMA_TYPE_ALL:
19050 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
19051 if (circ != NULL)
19052 return (circ);
19053 break;
19054 default:
19055 break;
19058 return (NULL);
19062 * xmlSchemaCheckGroupDefCircular:
19063 * @item: the model group definition
19064 * @ctxt: the parser context
19065 * @name: the name
19067 * Checks for circular references to model group definitions.
19069 static void
19070 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
19071 xmlSchemaParserCtxtPtr ctxt)
19074 * Schema Component Constraint: Model Group Correct
19075 * 2 Circular groups are disallowed. That is, within the {particles}
19076 * of a group there must not be at any depth a particle whose {term}
19077 * is the group itself.
19079 if ((item == NULL) ||
19080 (item->type != XML_SCHEMA_TYPE_GROUP) ||
19081 (item->children == NULL))
19082 return;
19084 xmlSchemaTreeItemPtr circ;
19086 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
19087 if (circ != NULL) {
19088 xmlChar *str = NULL;
19090 * TODO: The error report is not adequate: this constraint
19091 * is defined for model groups but not definitions, but since
19092 * there cannot be any circular model groups without a model group
19093 * definition (if not using a construction API), we check those
19094 * definitions only.
19096 xmlSchemaPCustomErr(ctxt,
19097 XML_SCHEMAP_MG_PROPS_CORRECT_2,
19098 NULL, WXS_ITEM_NODE(circ),
19099 "Circular reference to the model group definition '%s' "
19100 "defined", xmlSchemaFormatQName(&str,
19101 item->targetNamespace, item->name));
19102 FREE_AND_NULL(str)
19104 * NOTE: We will cut the reference to avoid further
19105 * confusion of the processor. This is a fatal error.
19107 circ->children = NULL;
19113 * xmlSchemaModelGroupToModelGroupDefFixup:
19114 * @ctxt: the parser context
19115 * @mg: the model group
19117 * Assigns the model group of model group definitions to the "term"
19118 * of the referencing particle.
19119 * In xmlSchemaResolveModelGroupParticleReferences the model group
19120 * definitions were assigned to the "term", since needed for the
19121 * circularity check.
19123 * Schema Component Constraint:
19124 * All Group Limited (cos-all-limited) (1.2)
19126 static void
19127 xmlSchemaModelGroupToModelGroupDefFixup(
19128 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
19129 xmlSchemaModelGroupPtr mg)
19131 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19133 while (particle != NULL) {
19134 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19135 ((WXS_PARTICLE_TERM(particle))->type !=
19136 XML_SCHEMA_TYPE_GROUP))
19138 particle = WXS_PTC_CAST particle->next;
19139 continue;
19141 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19143 * TODO: Remove the particle.
19145 WXS_PARTICLE_TERM(particle) = NULL;
19146 particle = WXS_PTC_CAST particle->next;
19147 continue;
19150 * Assign the model group to the {term} of the particle.
19152 WXS_PARTICLE_TERM(particle) =
19153 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19155 particle = WXS_PTC_CAST particle->next;
19160 * xmlSchemaCheckAttrGroupCircularRecur:
19161 * @ctxtGr: the searched attribute group
19162 * @attr: the current attribute list to be processed
19164 * This one is intended to be used by
19165 * xmlSchemaCheckAttrGroupCircular only.
19167 * Returns the circular attribute group reference, otherwise NULL.
19169 static xmlSchemaQNameRefPtr
19170 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19171 xmlSchemaItemListPtr list)
19173 xmlSchemaAttributeGroupPtr gr;
19174 xmlSchemaQNameRefPtr ref, circ;
19175 int i;
19177 * We will search for an attribute group reference which
19178 * references the context attribute group.
19180 for (i = 0; i < list->nbItems; i++) {
19181 ref = list->items[i];
19182 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19183 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19184 (ref->item != NULL))
19186 gr = WXS_ATTR_GROUP_CAST ref->item;
19187 if (gr == ctxtGr)
19188 return(ref);
19189 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19190 continue;
19192 * Mark as visited to avoid infinite recursion on
19193 * circular references not yet examined.
19195 if ((gr->attrUses) &&
19196 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19198 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19199 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19200 (xmlSchemaItemListPtr) gr->attrUses);
19201 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19202 if (circ != NULL)
19203 return (circ);
19208 return (NULL);
19212 * xmlSchemaCheckAttrGroupCircular:
19213 * attrGr: the attribute group definition
19214 * @ctxt: the parser context
19215 * @name: the name
19217 * Checks for circular references of attribute groups.
19219 static int
19220 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19221 xmlSchemaParserCtxtPtr ctxt)
19224 * Schema Representation Constraint:
19225 * Attribute Group Definition Representation OK
19226 * 3 Circular group reference is disallowed outside <redefine>.
19227 * That is, unless this element information item's parent is
19228 * <redefine>, then among the [children], if any, there must
19229 * not be an <attributeGroup> with ref [attribute] which resolves
19230 * to the component corresponding to this <attributeGroup>. Indirect
19231 * circularity is also ruled out. That is, when QName resolution
19232 * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19233 * any <attributeGroup>s with a ref [attribute] among the [children],
19234 * it must not be the case that a `QName` is encountered at any depth
19235 * which resolves to the component corresponding to this <attributeGroup>.
19237 if (attrGr->attrUses == NULL)
19238 return(0);
19239 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19240 return(0);
19241 else {
19242 xmlSchemaQNameRefPtr circ;
19244 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19245 (xmlSchemaItemListPtr) attrGr->attrUses);
19246 if (circ != NULL) {
19247 xmlChar *str = NULL;
19249 * TODO: Report the referenced attr group as QName.
19251 xmlSchemaPCustomErr(ctxt,
19252 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19253 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19254 "Circular reference to the attribute group '%s' "
19255 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19256 FREE_AND_NULL(str);
19258 * NOTE: We will cut the reference to avoid further
19259 * confusion of the processor.
19260 * BADSPEC TODO: The spec should define how to process in this case.
19262 circ->item = NULL;
19263 return(ctxt->err);
19266 return(0);
19269 static int
19270 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19271 xmlSchemaAttributeGroupPtr attrGr);
19274 * xmlSchemaExpandAttributeGroupRefs:
19275 * @pctxt: the parser context
19276 * @node: the node of the component holding the attribute uses
19277 * @completeWild: the intersected wildcard to be returned
19278 * @list: the attribute uses
19280 * Substitutes contained attribute group references
19281 * for their attribute uses. Wildcards are intersected.
19282 * Attribute use prohibitions are removed from the list
19283 * and returned via the @prohibs list.
19284 * Pointlessness of attr. prohibs, if a matching attr. decl
19285 * is existent a well, are checked.
19287 static int
19288 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19289 xmlSchemaBasicItemPtr item,
19290 xmlSchemaWildcardPtr *completeWild,
19291 xmlSchemaItemListPtr list,
19292 xmlSchemaItemListPtr prohibs)
19294 xmlSchemaAttributeGroupPtr gr;
19295 xmlSchemaAttributeUsePtr use;
19296 xmlSchemaItemListPtr sublist;
19297 int i, j;
19298 int created = (*completeWild == NULL) ? 0 : 1;
19300 if (prohibs)
19301 prohibs->nbItems = 0;
19303 for (i = 0; i < list->nbItems; i++) {
19304 use = list->items[i];
19306 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19307 if (prohibs == NULL) {
19308 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19309 "unexpected attr prohibition found");
19310 return(-1);
19313 * Remove from attribute uses.
19315 if (xmlSchemaItemListRemove(list, i) == -1)
19316 return(-1);
19317 i--;
19319 * Note that duplicate prohibitions were already
19320 * handled at parsing time.
19323 * Add to list of prohibitions.
19325 xmlSchemaItemListAddSize(prohibs, 2, use);
19326 continue;
19328 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19329 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19331 if ((WXS_QNAME_CAST use)->item == NULL)
19332 return(-1);
19333 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19335 * Expand the referenced attr. group.
19336 * TODO: remove this, this is done in a previous step, so
19337 * already done here.
19339 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19340 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19341 return(-1);
19344 * Build the 'complete' wildcard; i.e. intersect multiple
19345 * wildcards.
19347 if (gr->attributeWildcard != NULL) {
19348 if (*completeWild == NULL) {
19349 *completeWild = gr->attributeWildcard;
19350 } else {
19351 if (! created) {
19352 xmlSchemaWildcardPtr tmpWild;
19355 * Copy the first encountered wildcard as context,
19356 * except for the annotation.
19358 * Although the complete wildcard might not correspond
19359 * to any node in the schema, we will anchor it on
19360 * the node of the owner component.
19362 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19363 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19364 WXS_ITEM_NODE(item));
19365 if (tmpWild == NULL)
19366 return(-1);
19367 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19368 tmpWild, *completeWild) == -1)
19369 return (-1);
19370 tmpWild->processContents = (*completeWild)->processContents;
19371 *completeWild = tmpWild;
19372 created = 1;
19375 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19376 gr->attributeWildcard) == -1)
19377 return(-1);
19381 * Just remove the reference if the referenced group does not
19382 * contain any attribute uses.
19384 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19385 if ((sublist == NULL) || sublist->nbItems == 0) {
19386 if (xmlSchemaItemListRemove(list, i) == -1)
19387 return(-1);
19388 i--;
19389 continue;
19392 * Add the attribute uses.
19394 list->items[i] = sublist->items[0];
19395 if (sublist->nbItems != 1) {
19396 for (j = 1; j < sublist->nbItems; j++) {
19397 i++;
19398 if (xmlSchemaItemListInsert(list,
19399 sublist->items[j], i) == -1)
19400 return(-1);
19407 * Handle pointless prohibitions of declared attributes.
19409 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19410 xmlSchemaAttributeUseProhibPtr prohib;
19412 for (i = prohibs->nbItems -1; i >= 0; i--) {
19413 prohib = prohibs->items[i];
19414 for (j = 0; j < list->nbItems; j++) {
19415 use = list->items[j];
19417 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19418 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19420 xmlChar *str = NULL;
19422 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19423 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19424 prohib->node, NULL,
19425 "Skipping pointless attribute use prohibition "
19426 "'%s', since a corresponding attribute use "
19427 "exists already in the type definition",
19428 xmlSchemaFormatQName(&str,
19429 prohib->targetNamespace, prohib->name),
19430 NULL, NULL);
19431 FREE_AND_NULL(str);
19433 * Remove the prohibition.
19435 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19436 return(-1);
19437 break;
19442 return(0);
19446 * xmlSchemaAttributeGroupExpandRefs:
19447 * @pctxt: the parser context
19448 * @attrGr: the attribute group definition
19450 * Computation of:
19451 * {attribute uses} property
19452 * {attribute wildcard} property
19454 * Substitutes contained attribute group references
19455 * for their attribute uses. Wildcards are intersected.
19457 static int
19458 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19459 xmlSchemaAttributeGroupPtr attrGr)
19461 if ((attrGr->attrUses == NULL) ||
19462 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19463 return(0);
19465 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19466 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19467 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19468 return(-1);
19469 return(0);
19473 * xmlSchemaAttributeGroupExpandRefs:
19474 * @pctxt: the parser context
19475 * @attrGr: the attribute group definition
19477 * Substitutes contained attribute group references
19478 * for their attribute uses. Wildcards are intersected.
19480 * Schema Component Constraint:
19481 * Attribute Group Definition Properties Correct (ag-props-correct)
19483 static int
19484 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19485 xmlSchemaAttributeGroupPtr attrGr)
19488 * SPEC ag-props-correct
19489 * (1) "The values of the properties of an attribute group definition
19490 * must be as described in the property tableau in The Attribute
19491 * Group Definition Schema Component ($3.6.1), modulo the impact of
19492 * Missing Sub-components ($5.3);"
19495 if ((attrGr->attrUses != NULL) &&
19496 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19498 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19499 xmlSchemaAttributeUsePtr use, tmp;
19500 int i, j, hasId = 0;
19502 for (i = uses->nbItems -1; i >= 0; i--) {
19503 use = uses->items[i];
19505 * SPEC ag-props-correct
19506 * (2) "Two distinct members of the {attribute uses} must not have
19507 * {attribute declaration}s both of whose {name}s match and whose
19508 * {target namespace}s are identical."
19510 if (i > 0) {
19511 for (j = i -1; j >= 0; j--) {
19512 tmp = uses->items[j];
19513 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19514 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19515 (WXS_ATTRUSE_DECL_TNS(use) ==
19516 WXS_ATTRUSE_DECL_TNS(tmp)))
19518 xmlChar *str = NULL;
19520 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19521 XML_SCHEMAP_AG_PROPS_CORRECT,
19522 attrGr->node, WXS_BASIC_CAST attrGr,
19523 "Duplicate %s",
19524 xmlSchemaGetComponentDesignation(&str, use),
19525 NULL);
19526 FREE_AND_NULL(str);
19528 * Remove the duplicate.
19530 if (xmlSchemaItemListRemove(uses, i) == -1)
19531 return(-1);
19532 goto next_use;
19537 * SPEC ag-props-correct
19538 * (3) "Two distinct members of the {attribute uses} must not have
19539 * {attribute declaration}s both of whose {type definition}s are or
19540 * are derived from ID."
19541 * TODO: Does 'derived' include member-types of unions?
19543 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19544 if (xmlSchemaIsDerivedFromBuiltInType(
19545 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19547 if (hasId) {
19548 xmlChar *str = NULL;
19550 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19551 XML_SCHEMAP_AG_PROPS_CORRECT,
19552 attrGr->node, WXS_BASIC_CAST attrGr,
19553 "There must not exist more than one attribute "
19554 "declaration of type 'xs:ID' "
19555 "(or derived from 'xs:ID'). The %s violates this "
19556 "constraint",
19557 xmlSchemaGetComponentDesignation(&str, use),
19558 NULL);
19559 FREE_AND_NULL(str);
19560 if (xmlSchemaItemListRemove(uses, i) == -1)
19561 return(-1);
19563 hasId = 1;
19566 next_use: {}
19569 return(0);
19573 * xmlSchemaResolveAttrGroupReferences:
19574 * @attrgrpDecl: the schema attribute definition
19575 * @ctxt: the schema parser context
19576 * @name: the attribute name
19578 * Resolves references to attribute group definitions.
19580 static int
19581 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19582 xmlSchemaParserCtxtPtr ctxt)
19584 xmlSchemaAttributeGroupPtr group;
19586 if (ref->item != NULL)
19587 return(0);
19588 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19589 ref->name,
19590 ref->targetNamespace);
19591 if (group == NULL) {
19592 xmlSchemaPResCompAttrErr(ctxt,
19593 XML_SCHEMAP_SRC_RESOLVE,
19594 NULL, ref->node,
19595 "ref", ref->name, ref->targetNamespace,
19596 ref->itemType, NULL);
19597 return(ctxt->err);
19599 ref->item = WXS_BASIC_CAST group;
19600 return(0);
19604 * xmlSchemaCheckAttrPropsCorrect:
19605 * @item: an schema attribute declaration/use
19606 * @ctxt: a schema parser context
19607 * @name: the name of the attribute
19610 * Schema Component Constraint:
19611 * Attribute Declaration Properties Correct (a-props-correct)
19613 * Validates the value constraints of an attribute declaration/use.
19614 * NOTE that this needs the simple type definitions to be already
19615 * built and checked.
19617 static int
19618 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19619 xmlSchemaAttributePtr attr)
19623 * SPEC a-props-correct (1)
19624 * "The values of the properties of an attribute declaration must
19625 * be as described in the property tableau in The Attribute
19626 * Declaration Schema Component ($3.2.1), modulo the impact of
19627 * Missing Sub-components ($5.3)."
19630 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19631 return(0);
19633 if (attr->defValue != NULL) {
19634 int ret;
19637 * SPEC a-props-correct (3)
19638 * "If the {type definition} is or is derived from ID then there
19639 * must not be a {value constraint}."
19641 if (xmlSchemaIsDerivedFromBuiltInType(
19642 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19644 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19645 XML_SCHEMAP_A_PROPS_CORRECT_3,
19646 NULL, WXS_BASIC_CAST attr,
19647 "Value constraints are not allowed if the type definition "
19648 "is or is derived from xs:ID",
19649 NULL, NULL);
19650 return(pctxt->err);
19653 * SPEC a-props-correct (2)
19654 * "if there is a {value constraint}, the canonical lexical
19655 * representation of its value must be `valid` with respect
19656 * to the {type definition} as defined in String Valid ($3.14.4)."
19657 * TODO: Don't care about the *canonical* stuff here, this requirement
19658 * will be removed in WXS 1.1 anyway.
19660 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19661 attr->node, WXS_ATTR_TYPEDEF(attr),
19662 attr->defValue, &(attr->defVal),
19663 1, 1, 0);
19664 if (ret != 0) {
19665 if (ret < 0) {
19666 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19667 "calling xmlSchemaVCheckCVCSimpleType()");
19668 return(-1);
19670 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19671 XML_SCHEMAP_A_PROPS_CORRECT_2,
19672 NULL, WXS_BASIC_CAST attr,
19673 "The value of the value constraint is not valid",
19674 NULL, NULL);
19675 return(pctxt->err);
19679 return(0);
19682 static xmlSchemaElementPtr
19683 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19684 xmlSchemaElementPtr ancestor)
19686 xmlSchemaElementPtr ret;
19688 if (WXS_SUBST_HEAD(ancestor) == NULL)
19689 return (NULL);
19690 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19691 return (ancestor);
19693 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19694 return (NULL);
19695 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19696 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19697 WXS_SUBST_HEAD(ancestor));
19698 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19700 return (ret);
19704 * xmlSchemaCheckElemPropsCorrect:
19705 * @ctxt: a schema parser context
19706 * @decl: the element declaration
19707 * @name: the name of the attribute
19709 * Schema Component Constraint:
19710 * Element Declaration Properties Correct (e-props-correct)
19712 * STATUS:
19713 * missing: (6)
19715 static int
19716 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19717 xmlSchemaElementPtr elemDecl)
19719 int ret = 0;
19720 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19722 * SPEC (1) "The values of the properties of an element declaration
19723 * must be as described in the property tableau in The Element
19724 * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19725 * Sub-components ($5.3)."
19727 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19728 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19730 xmlSchemaCheckElementDeclComponent(head, pctxt);
19732 * SPEC (3) "If there is a non-`absent` {substitution group
19733 * affiliation}, then {scope} must be global."
19735 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19736 xmlSchemaPCustomErr(pctxt,
19737 XML_SCHEMAP_E_PROPS_CORRECT_3,
19738 WXS_BASIC_CAST elemDecl, NULL,
19739 "Only global element declarations can have a "
19740 "substitution group affiliation", NULL);
19741 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19744 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19745 * That is, it must not be possible to return to an element declaration
19746 * by repeatedly following the {substitution group affiliation}
19747 * property."
19749 if (head == elemDecl)
19750 circ = head;
19751 else if (WXS_SUBST_HEAD(head) != NULL)
19752 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19753 else
19754 circ = NULL;
19755 if (circ != NULL) {
19756 xmlChar *strA = NULL, *strB = NULL;
19758 xmlSchemaPCustomErrExt(pctxt,
19759 XML_SCHEMAP_E_PROPS_CORRECT_6,
19760 WXS_BASIC_CAST circ, NULL,
19761 "The element declaration '%s' defines a circular "
19762 "substitution group to element declaration '%s'",
19763 xmlSchemaGetComponentQName(&strA, circ),
19764 xmlSchemaGetComponentQName(&strB, head),
19765 NULL);
19766 FREE_AND_NULL(strA)
19767 FREE_AND_NULL(strB)
19768 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19771 * SPEC (4) "If there is a {substitution group affiliation},
19772 * the {type definition}
19773 * of the element declaration must be validly derived from the {type
19774 * definition} of the {substitution group affiliation}, given the value
19775 * of the {substitution group exclusions} of the {substitution group
19776 * affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19777 * (if the {type definition} is complex) or as defined in
19778 * Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19779 * simple)."
19781 * NOTE: {substitution group exclusions} means the values of the
19782 * attribute "final".
19785 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19786 int set = 0;
19788 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19789 set |= SUBSET_EXTENSION;
19790 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19791 set |= SUBSET_RESTRICTION;
19793 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19794 WXS_ELEM_TYPEDEF(head), set) != 0) {
19795 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19797 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19798 xmlSchemaPCustomErrExt(pctxt,
19799 XML_SCHEMAP_E_PROPS_CORRECT_4,
19800 WXS_BASIC_CAST elemDecl, NULL,
19801 "The type definition '%s' was "
19802 "either rejected by the substitution group "
19803 "affiliation '%s', or not validly derived from its type "
19804 "definition '%s'",
19805 xmlSchemaGetComponentQName(&strA, typeDef),
19806 xmlSchemaGetComponentQName(&strB, head),
19807 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19808 FREE_AND_NULL(strA)
19809 FREE_AND_NULL(strB)
19810 FREE_AND_NULL(strC)
19815 * SPEC (5) "If the {type definition} or {type definition}'s
19816 * {content type}
19817 * is or is derived from ID then there must not be a {value constraint}.
19818 * Note: The use of ID as a type definition for elements goes beyond
19819 * XML 1.0, and should be avoided if backwards compatibility is desired"
19821 if ((elemDecl->value != NULL) &&
19822 ((WXS_IS_SIMPLE(typeDef) &&
19823 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19824 (WXS_IS_COMPLEX(typeDef) &&
19825 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19826 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19827 XML_SCHEMAS_ID)))) {
19829 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19830 xmlSchemaPCustomErr(pctxt,
19831 XML_SCHEMAP_E_PROPS_CORRECT_5,
19832 WXS_BASIC_CAST elemDecl, NULL,
19833 "The type definition (or type definition's content type) is or "
19834 "is derived from ID; value constraints are not allowed in "
19835 "conjunction with such a type definition", NULL);
19836 } else if (elemDecl->value != NULL) {
19837 int vcret;
19838 xmlNodePtr node = NULL;
19841 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19842 * representation of its value must be `valid` with respect to the
19843 * {type definition} as defined in Element Default Valid (Immediate)
19844 * ($3.3.6)."
19846 if (typeDef == NULL) {
19847 xmlSchemaPErr(pctxt, elemDecl->node,
19848 XML_SCHEMAP_INTERNAL,
19849 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19850 "type is missing... skipping validation of "
19851 "the value constraint", NULL, NULL);
19852 return (-1);
19854 if (elemDecl->node != NULL) {
19855 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19856 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19857 BAD_CAST "fixed");
19858 else
19859 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19860 BAD_CAST "default");
19862 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19863 typeDef, elemDecl->value, &(elemDecl->defVal));
19864 if (vcret != 0) {
19865 if (vcret < 0) {
19866 PERROR_INT("xmlSchemaElemCheckValConstr",
19867 "failed to validate the value constraint of an "
19868 "element declaration");
19869 return (-1);
19871 return (vcret);
19875 return (ret);
19879 * xmlSchemaCheckElemSubstGroup:
19880 * @ctxt: a schema parser context
19881 * @decl: the element declaration
19882 * @name: the name of the attribute
19884 * Schema Component Constraint:
19885 * Substitution Group (cos-equiv-class)
19887 * In Libxml2 the subst. groups will be precomputed, in terms of that
19888 * a list will be built for each subst. group head, holding all direct
19889 * referents to this head.
19890 * NOTE that this function needs:
19891 * 1. circular subst. groups to be checked beforehand
19892 * 2. the declaration's type to be derived from the head's type
19894 * STATUS:
19897 static void
19898 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19899 xmlSchemaElementPtr elemDecl)
19901 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19902 /* SPEC (1) "Its {abstract} is false." */
19903 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19904 return;
19906 xmlSchemaElementPtr head;
19907 xmlSchemaTypePtr headType, type;
19908 int set, methSet;
19910 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19911 * {disallowed substitutions} as the blocking constraint, as defined in
19912 * Substitution Group OK (Transitive) ($3.3.6)."
19914 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19915 head = WXS_SUBST_HEAD(head)) {
19916 set = 0;
19917 methSet = 0;
19919 * The blocking constraints.
19921 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19922 continue;
19923 headType = head->subtypes;
19924 type = elemDecl->subtypes;
19925 if (headType == type)
19926 goto add_member;
19927 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19928 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19929 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19930 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19932 * SPEC: Substitution Group OK (Transitive) (2.3)
19933 * "The set of all {derivation method}s involved in the
19934 * derivation of D's {type definition} from C's {type definition}
19935 * does not intersect with the union of the blocking constraint,
19936 * C's {prohibited substitutions} (if C is complex, otherwise the
19937 * empty set) and the {prohibited substitutions} (respectively the
19938 * empty set) of any intermediate {type definition}s in the
19939 * derivation of D's {type definition} from C's {type definition}."
19942 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19943 * subst.head axis, the methSet does not need to be computed for
19944 * the full depth over and over.
19947 * The set of all {derivation method}s involved in the derivation
19949 while ((type != NULL) && (type != headType)) {
19950 if ((WXS_IS_EXTENSION(type)) &&
19951 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19952 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19954 if (WXS_IS_RESTRICTION(type) &&
19955 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19956 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19958 type = type->baseType;
19961 * The {prohibited substitutions} of all intermediate types +
19962 * the head's type.
19964 type = elemDecl->subtypes->baseType;
19965 while (type != NULL) {
19966 if (WXS_IS_COMPLEX(type)) {
19967 if ((type->flags &
19968 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19969 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19970 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19971 if ((type->flags &
19972 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19973 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19974 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19975 } else
19976 break;
19977 if (type == headType)
19978 break;
19979 type = type->baseType;
19981 if ((set != 0) &&
19982 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19983 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19984 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19985 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19986 continue;
19988 add_member:
19989 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19990 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19991 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19996 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19998 * xmlSchemaCheckElementDeclComponent
19999 * @pctxt: the schema parser context
20000 * @ctxtComponent: the context component (an element declaration)
20001 * @ctxtParticle: the first particle of the context component
20002 * @searchParticle: the element declaration particle to be analysed
20004 * Schema Component Constraint: Element Declarations Consistent
20006 static int
20007 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
20008 xmlSchemaBasicItemPtr ctxtComponent,
20009 xmlSchemaParticlePtr ctxtParticle,
20010 xmlSchemaParticlePtr searchParticle,
20011 xmlSchemaParticlePtr curParticle,
20012 int search)
20014 return(0);
20016 int ret = 0;
20017 xmlSchemaParticlePtr cur = curParticle;
20018 if (curParticle == NULL) {
20019 return(0);
20021 if (WXS_PARTICLE_TERM(curParticle) == NULL) {
20023 * Just return in this case. A missing "term" of the particle
20024 * might arise due to an invalid "term" component.
20026 return(0);
20028 while (cur != NULL) {
20029 switch (WXS_PARTICLE_TERM(cur)->type) {
20030 case XML_SCHEMA_TYPE_ANY:
20031 break;
20032 case XML_SCHEMA_TYPE_ELEMENT:
20033 if (search == 0) {
20034 ret = xmlSchemaCheckElementDeclConsistent(pctxt,
20035 ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
20036 if (ret != 0)
20037 return(ret);
20038 } else {
20039 xmlSchemaElementPtr elem =
20040 WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
20042 * SPEC Element Declarations Consistent:
20043 * "If the {particles} contains, either directly,
20044 * indirectly (that is, within the {particles} of a
20045 * contained model group, recursively) or `implicitly`
20046 * two or more element declaration particles with
20047 * the same {name} and {target namespace}, then
20048 * all their type definitions must be the same
20049 * top-level definition [...]"
20051 if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
20052 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
20053 xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20054 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
20056 xmlChar *strA = NULL, *strB = NULL;
20058 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20059 /* TODO: error code */
20060 XML_SCHEMAP_COS_NONAMBIG,
20061 WXS_ITEM_NODE(cur), NULL,
20062 "In the content model of %s, there are multiple "
20063 "element declarations for '%s' with different "
20064 "type definitions",
20065 xmlSchemaGetComponentDesignation(&strA,
20066 ctxtComponent),
20067 xmlSchemaFormatQName(&strB,
20068 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20069 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
20070 FREE_AND_NULL(strA);
20071 FREE_AND_NULL(strB);
20072 return(XML_SCHEMAP_COS_NONAMBIG);
20075 break;
20076 case XML_SCHEMA_TYPE_SEQUENCE: {
20077 break;
20079 case XML_SCHEMA_TYPE_CHOICE:{
20081 xmlSchemaTreeItemPtr sub;
20083 sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
20084 while (sub != NULL) {
20085 ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
20086 ctxtParticle, ctxtElem);
20087 if (ret != 0)
20088 return(ret);
20089 sub = sub->next;
20092 break;
20094 case XML_SCHEMA_TYPE_ALL:
20095 break;
20096 case XML_SCHEMA_TYPE_GROUP:
20097 break;
20098 default:
20099 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
20100 "xmlSchemaCheckElementDeclConsistent",
20101 "found unexpected term of type '%s' in content model",
20102 WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
20103 return(-1);
20105 cur = (xmlSchemaParticlePtr) cur->next;
20108 exit:
20109 return(ret);
20111 #endif
20114 * xmlSchemaCheckElementDeclComponent
20115 * @item: an schema element declaration/particle
20116 * @ctxt: a schema parser context
20117 * @name: the name of the attribute
20119 * Validates the value constraints of an element declaration.
20120 * Adds substitution group members.
20122 static void
20123 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
20124 xmlSchemaParserCtxtPtr ctxt)
20126 if (elemDecl == NULL)
20127 return;
20128 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
20129 return;
20130 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
20131 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20133 * Adds substitution group members.
20135 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20140 * xmlSchemaResolveModelGroupParticleReferences:
20141 * @particle: a particle component
20142 * @ctxt: a parser context
20144 * Resolves references of a model group's {particles} to
20145 * model group definitions and to element declarations.
20147 static void
20148 xmlSchemaResolveModelGroupParticleReferences(
20149 xmlSchemaParserCtxtPtr ctxt,
20150 xmlSchemaModelGroupPtr mg)
20152 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20153 xmlSchemaQNameRefPtr ref;
20154 xmlSchemaBasicItemPtr refItem;
20157 * URGENT TODO: Test this.
20159 while (particle != NULL) {
20160 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20161 ((WXS_PARTICLE_TERM(particle))->type !=
20162 XML_SCHEMA_EXTRA_QNAMEREF))
20164 goto next_particle;
20166 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20168 * Resolve the reference.
20169 * NULL the {term} by default.
20171 particle->children = NULL;
20173 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20174 ref->itemType, ref->name, ref->targetNamespace);
20175 if (refItem == NULL) {
20176 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20177 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20178 ref->targetNamespace, ref->itemType, NULL);
20179 /* TODO: remove the particle. */
20180 goto next_particle;
20182 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20183 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20184 /* TODO: remove the particle. */
20185 goto next_particle;
20187 * NOTE that we will assign the model group definition
20188 * itself to the "term" of the particle. This will ease
20189 * the check for circular model group definitions. After
20190 * that the "term" will be assigned the model group of the
20191 * model group definition.
20193 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20194 XML_SCHEMA_TYPE_ALL) {
20196 * SPEC cos-all-limited (1)
20197 * SPEC cos-all-limited (1.2)
20198 * "It appears only as the value of one or both of the
20199 * following properties:"
20200 * (1.1) "the {model group} property of a model group
20201 * definition."
20202 * (1.2) "the {term} property of a particle [... of] the "
20203 * {content type} of a complex type definition."
20205 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20206 /* TODO: error code */
20207 XML_SCHEMAP_COS_ALL_LIMITED,
20208 WXS_ITEM_NODE(particle), NULL,
20209 "A model group definition is referenced, but "
20210 "it contains an 'all' model group, which "
20211 "cannot be contained by model groups",
20212 NULL, NULL);
20213 /* TODO: remove the particle. */
20214 goto next_particle;
20216 particle->children = (xmlSchemaTreeItemPtr) refItem;
20217 } else {
20219 * TODO: Are referenced element declarations the only
20220 * other components we expect here?
20222 particle->children = (xmlSchemaTreeItemPtr) refItem;
20224 next_particle:
20225 particle = WXS_PTC_CAST particle->next;
20229 static int
20230 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20231 xmlSchemaValPtr y)
20233 xmlSchemaTypePtr tx, ty, ptx, pty;
20234 int ret;
20236 while (x != NULL) {
20237 /* Same types. */
20238 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20239 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20240 ptx = xmlSchemaGetPrimitiveType(tx);
20241 pty = xmlSchemaGetPrimitiveType(ty);
20243 * (1) if a datatype T' is `derived` by `restriction` from an
20244 * atomic datatype T then the `value space` of T' is a subset of
20245 * the `value space` of T. */
20247 * (2) if datatypes T' and T'' are `derived` by `restriction`
20248 * from a common atomic ancestor T then the `value space`s of T'
20249 * and T'' may overlap.
20251 if (ptx != pty)
20252 return(0);
20254 * We assume computed values to be normalized, so do a fast
20255 * string comparison for string based types.
20257 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20258 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20259 if (! xmlStrEqual(
20260 xmlSchemaValueGetAsString(x),
20261 xmlSchemaValueGetAsString(y)))
20262 return (0);
20263 } else {
20264 ret = xmlSchemaCompareValuesWhtsp(
20265 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20266 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20267 if (ret == -2)
20268 return(-1);
20269 if (ret != 0)
20270 return(0);
20273 * Lists.
20275 x = xmlSchemaValueGetNext(x);
20276 if (x != NULL) {
20277 y = xmlSchemaValueGetNext(y);
20278 if (y == NULL)
20279 return (0);
20280 } else if (xmlSchemaValueGetNext(y) != NULL)
20281 return (0);
20282 else
20283 return (1);
20285 return (0);
20289 * xmlSchemaResolveAttrUseReferences:
20290 * @item: an attribute use
20291 * @ctxt: a parser context
20293 * Resolves the referenced attribute declaration.
20295 static int
20296 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20297 xmlSchemaParserCtxtPtr ctxt)
20299 if ((ctxt == NULL) || (ause == NULL))
20300 return(-1);
20301 if ((ause->attrDecl == NULL) ||
20302 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20303 return(0);
20306 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20309 * TODO: Evaluate, what errors could occur if the declaration is not
20310 * found.
20312 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20313 ref->name, ref->targetNamespace);
20314 if (ause->attrDecl == NULL) {
20315 xmlSchemaPResCompAttrErr(ctxt,
20316 XML_SCHEMAP_SRC_RESOLVE,
20317 WXS_BASIC_CAST ause, ause->node,
20318 "ref", ref->name, ref->targetNamespace,
20319 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20320 return(ctxt->err);;
20323 return(0);
20327 * xmlSchemaCheckAttrUsePropsCorrect:
20328 * @ctxt: a parser context
20329 * @use: an attribute use
20331 * Schema Component Constraint:
20332 * Attribute Use Correct (au-props-correct)
20335 static int
20336 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20337 xmlSchemaAttributeUsePtr use)
20339 if ((ctxt == NULL) || (use == NULL))
20340 return(-1);
20341 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20342 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20343 return(0);
20346 * SPEC au-props-correct (1)
20347 * "The values of the properties of an attribute use must be as
20348 * described in the property tableau in The Attribute Use Schema
20349 * Component ($3.5.1), modulo the impact of Missing
20350 * Sub-components ($5.3)."
20353 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20354 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20355 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20357 xmlSchemaPCustomErr(ctxt,
20358 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20359 WXS_BASIC_CAST use, NULL,
20360 "The attribute declaration has a 'fixed' value constraint "
20361 ", thus the attribute use must also have a 'fixed' value "
20362 "constraint",
20363 NULL);
20364 return(ctxt->err);
20367 * Compute and check the value constraint's value.
20369 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20370 int ret;
20372 * TODO: The spec seems to be missing a check of the
20373 * value constraint of the attribute use. We will do it here.
20376 * SPEC a-props-correct (3)
20378 if (xmlSchemaIsDerivedFromBuiltInType(
20379 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20381 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20382 XML_SCHEMAP_AU_PROPS_CORRECT,
20383 NULL, WXS_BASIC_CAST use,
20384 "Value constraints are not allowed if the type definition "
20385 "is or is derived from xs:ID",
20386 NULL, NULL);
20387 return(ctxt->err);
20390 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20391 use->node, WXS_ATTRUSE_TYPEDEF(use),
20392 use->defValue, &(use->defVal),
20393 1, 1, 0);
20394 if (ret != 0) {
20395 if (ret < 0) {
20396 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20397 "calling xmlSchemaVCheckCVCSimpleType()");
20398 return(-1);
20400 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20401 XML_SCHEMAP_AU_PROPS_CORRECT,
20402 NULL, WXS_BASIC_CAST use,
20403 "The value of the value constraint is not valid",
20404 NULL, NULL);
20405 return(ctxt->err);
20409 * SPEC au-props-correct (2)
20410 * "If the {attribute declaration} has a fixed
20411 * {value constraint}, then if the attribute use itself has a
20412 * {value constraint}, it must also be fixed and its value must match
20413 * that of the {attribute declaration}'s {value constraint}."
20415 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20416 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20418 if (! xmlSchemaAreValuesEqual(use->defVal,
20419 (WXS_ATTRUSE_DECL(use))->defVal))
20421 xmlSchemaPCustomErr(ctxt,
20422 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20423 WXS_BASIC_CAST use, NULL,
20424 "The 'fixed' value constraint of the attribute use "
20425 "must match the attribute declaration's value "
20426 "constraint '%s'",
20427 (WXS_ATTRUSE_DECL(use))->defValue);
20429 return(ctxt->err);
20431 return(0);
20438 * xmlSchemaResolveAttrTypeReferences:
20439 * @item: an attribute declaration
20440 * @ctxt: a parser context
20442 * Resolves the referenced type definition component.
20444 static int
20445 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20446 xmlSchemaParserCtxtPtr ctxt)
20449 * The simple type definition corresponding to the <simpleType> element
20450 * information item in the [children], if present, otherwise the simple
20451 * type definition `resolved` to by the `actual value` of the type
20452 * [attribute], if present, otherwise the `simple ur-type definition`.
20454 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20455 return(0);
20456 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20457 if (item->subtypes != NULL)
20458 return(0);
20459 if (item->typeName != NULL) {
20460 xmlSchemaTypePtr type;
20462 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20463 item->typeNs);
20464 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20465 xmlSchemaPResCompAttrErr(ctxt,
20466 XML_SCHEMAP_SRC_RESOLVE,
20467 WXS_BASIC_CAST item, item->node,
20468 "type", item->typeName, item->typeNs,
20469 XML_SCHEMA_TYPE_SIMPLE, NULL);
20470 return(ctxt->err);
20471 } else
20472 item->subtypes = type;
20474 } else {
20476 * The type defaults to the xs:anySimpleType.
20478 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20480 return(0);
20484 * xmlSchemaResolveIDCKeyReferences:
20485 * @idc: the identity-constraint definition
20486 * @ctxt: the schema parser context
20487 * @name: the attribute name
20489 * Resolve keyRef references to key/unique IDCs.
20490 * Schema Component Constraint:
20491 * Identity-constraint Definition Properties Correct (c-props-correct)
20493 static int
20494 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20495 xmlSchemaParserCtxtPtr pctxt)
20497 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20498 return(0);
20499 if (idc->ref->name != NULL) {
20500 idc->ref->item = (xmlSchemaBasicItemPtr)
20501 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20502 idc->ref->targetNamespace);
20503 if (idc->ref->item == NULL) {
20505 * TODO: It is actually not an error to fail to resolve
20506 * at this stage. BUT we need to be that strict!
20508 xmlSchemaPResCompAttrErr(pctxt,
20509 XML_SCHEMAP_SRC_RESOLVE,
20510 WXS_BASIC_CAST idc, idc->node,
20511 "refer", idc->ref->name,
20512 idc->ref->targetNamespace,
20513 XML_SCHEMA_TYPE_IDC_KEY, NULL);
20514 return(pctxt->err);
20515 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20517 * SPEC c-props-correct (1)
20519 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20520 XML_SCHEMAP_C_PROPS_CORRECT,
20521 NULL, WXS_BASIC_CAST idc,
20522 "The keyref references a keyref",
20523 NULL, NULL);
20524 idc->ref->item = NULL;
20525 return(pctxt->err);
20526 } else {
20527 if (idc->nbFields !=
20528 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20529 xmlChar *str = NULL;
20530 xmlSchemaIDCPtr refer;
20532 refer = (xmlSchemaIDCPtr) idc->ref->item;
20534 * SPEC c-props-correct(2)
20535 * "If the {identity-constraint category} is keyref,
20536 * the cardinality of the {fields} must equal that of
20537 * the {fields} of the {referenced key}.
20539 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20540 XML_SCHEMAP_C_PROPS_CORRECT,
20541 NULL, WXS_BASIC_CAST idc,
20542 "The cardinality of the keyref differs from the "
20543 "cardinality of the referenced key/unique '%s'",
20544 xmlSchemaFormatQName(&str, refer->targetNamespace,
20545 refer->name),
20546 NULL);
20547 FREE_AND_NULL(str)
20548 return(pctxt->err);
20552 return(0);
20555 static int
20556 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20557 xmlSchemaParserCtxtPtr pctxt)
20559 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20560 prohib->targetNamespace) == NULL) {
20562 xmlSchemaPResCompAttrErr(pctxt,
20563 XML_SCHEMAP_SRC_RESOLVE,
20564 NULL, prohib->node,
20565 "ref", prohib->name, prohib->targetNamespace,
20566 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20567 return(XML_SCHEMAP_SRC_RESOLVE);
20569 return(0);
20572 #define WXS_REDEFINED_TYPE(c) \
20573 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20575 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20576 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20578 #define WXS_REDEFINED_ATTR_GROUP(c) \
20579 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20581 static int
20582 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20584 int err = 0;
20585 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20586 xmlSchemaBasicItemPtr prev, item;
20587 int wasRedefined;
20589 if (redef == NULL)
20590 return(0);
20592 do {
20593 item = redef->item;
20595 * First try to locate the redefined component in the
20596 * schema graph starting with the redefined schema.
20597 * NOTE: According to this schema bug entry:
20598 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20599 * it's not clear if the referenced component needs to originate
20600 * from the <redefine>d schema _document_ or the schema; the latter
20601 * would include all imported and included sub-schemas of the
20602 * <redefine>d schema. Currently the latter approach is used.
20603 * SUPPLEMENT: It seems that the WG moves towards the latter
20604 * approach, so we are doing it right.
20607 prev = xmlSchemaFindRedefCompInGraph(
20608 redef->targetBucket, item->type,
20609 redef->refName, redef->refTargetNs);
20610 if (prev == NULL) {
20611 xmlChar *str = NULL;
20612 xmlNodePtr node;
20615 * SPEC src-redefine:
20616 * (6.2.1) "The `actual value` of its own name attribute plus
20617 * target namespace must successfully `resolve` to a model
20618 * group definition in I."
20619 * (7.2.1) "The `actual value` of its own name attribute plus
20620 * target namespace must successfully `resolve` to an attribute
20621 * group definition in I."
20624 * Note that, if we are redefining with the use of references
20625 * to components, the spec assumes the src-resolve to be used;
20626 * but this won't assure that we search only *inside* the
20627 * redefined schema.
20629 if (redef->reference)
20630 node = WXS_ITEM_NODE(redef->reference);
20631 else
20632 node = WXS_ITEM_NODE(item);
20633 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20635 * TODO: error code.
20636 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20637 * reference kind.
20639 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20640 "The %s '%s' to be redefined could not be found in "
20641 "the redefined schema",
20642 WXS_ITEM_TYPE_NAME(item),
20643 xmlSchemaFormatQName(&str, redef->refTargetNs,
20644 redef->refName));
20645 FREE_AND_NULL(str);
20646 err = pctxt->err;
20647 redef = redef->next;
20648 continue;
20651 * TODO: Obtaining and setting the redefinition state is really
20652 * clumsy.
20654 wasRedefined = 0;
20655 switch (item->type) {
20656 case XML_SCHEMA_TYPE_COMPLEX:
20657 case XML_SCHEMA_TYPE_SIMPLE:
20658 if ((WXS_TYPE_CAST prev)->flags &
20659 XML_SCHEMAS_TYPE_REDEFINED)
20661 wasRedefined = 1;
20662 break;
20664 /* Mark it as redefined. */
20665 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20667 * Assign the redefined type to the
20668 * base type of the redefining type.
20669 * TODO: How
20671 ((xmlSchemaTypePtr) item)->baseType =
20672 (xmlSchemaTypePtr) prev;
20673 break;
20674 case XML_SCHEMA_TYPE_GROUP:
20675 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20676 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20678 wasRedefined = 1;
20679 break;
20681 /* Mark it as redefined. */
20682 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20683 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20684 if (redef->reference != NULL) {
20686 * Overwrite the QName-reference with the
20687 * referenced model group def.
20689 (WXS_PTC_CAST redef->reference)->children =
20690 WXS_TREE_CAST prev;
20692 redef->target = prev;
20693 break;
20694 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20695 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20696 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20698 wasRedefined = 1;
20699 break;
20701 (WXS_ATTR_GROUP_CAST prev)->flags |=
20702 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20703 if (redef->reference != NULL) {
20705 * Assign the redefined attribute group to the
20706 * QName-reference component.
20707 * This is the easy case, since we will just
20708 * expand the redefined group.
20710 (WXS_QNAME_CAST redef->reference)->item = prev;
20711 redef->target = NULL;
20712 } else {
20714 * This is the complicated case: we need
20715 * to apply src-redefine (7.2.2) at a later
20716 * stage, i.e. when attribute group references
20717 * have been expanded and simple types have
20718 * been fixed.
20720 redef->target = prev;
20722 break;
20723 default:
20724 PERROR_INT("xmlSchemaResolveRedefReferences",
20725 "Unexpected redefined component type");
20726 return(-1);
20728 if (wasRedefined) {
20729 xmlChar *str = NULL;
20730 xmlNodePtr node;
20732 if (redef->reference)
20733 node = WXS_ITEM_NODE(redef->reference);
20734 else
20735 node = WXS_ITEM_NODE(redef->item);
20737 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20738 /* TODO: error code. */
20739 XML_SCHEMAP_SRC_REDEFINE,
20740 node, NULL,
20741 "The referenced %s was already redefined. Multiple "
20742 "redefinition of the same component is not supported",
20743 xmlSchemaGetComponentDesignation(&str, prev),
20744 NULL);
20745 FREE_AND_NULL(str)
20746 err = pctxt->err;
20747 redef = redef->next;
20748 continue;
20750 redef = redef->next;
20751 } while (redef != NULL);
20753 return(err);
20756 static int
20757 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20759 int err = 0;
20760 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20761 xmlSchemaBasicItemPtr item;
20763 if (redef == NULL)
20764 return(0);
20766 do {
20767 if (redef->target == NULL) {
20768 redef = redef->next;
20769 continue;
20771 item = redef->item;
20773 switch (item->type) {
20774 case XML_SCHEMA_TYPE_SIMPLE:
20775 case XML_SCHEMA_TYPE_COMPLEX:
20777 * Since the spec wants the {name} of the redefined
20778 * type to be 'absent', we'll NULL it.
20780 (WXS_TYPE_CAST redef->target)->name = NULL;
20783 * TODO: Seems like there's nothing more to do. The normal
20784 * inheritance mechanism is used. But not 100% sure.
20786 break;
20787 case XML_SCHEMA_TYPE_GROUP:
20789 * URGENT TODO:
20790 * SPEC src-redefine:
20791 * (6.2.2) "The {model group} of the model group definition
20792 * which corresponds to it per XML Representation of Model
20793 * Group Definition Schema Components ($3.7.2) must be a
20794 * `valid restriction` of the {model group} of that model
20795 * group definition in I, as defined in Particle Valid
20796 * (Restriction) ($3.9.6)."
20798 break;
20799 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20801 * SPEC src-redefine:
20802 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20803 * the attribute group definition which corresponds to it
20804 * per XML Representation of Attribute Group Definition Schema
20805 * Components ($3.6.2) must be `valid restrictions` of the
20806 * {attribute uses} and {attribute wildcard} of that attribute
20807 * group definition in I, as defined in clause 2, clause 3 and
20808 * clause 4 of Derivation Valid (Restriction, Complex)
20809 * ($3.4.6) (where references to the base type definition are
20810 * understood as references to the attribute group definition
20811 * in I)."
20813 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20814 XML_SCHEMA_ACTION_REDEFINE,
20815 item, redef->target,
20816 (WXS_ATTR_GROUP_CAST item)->attrUses,
20817 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20818 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20819 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20820 if (err == -1)
20821 return(-1);
20822 break;
20823 default:
20824 break;
20826 redef = redef->next;
20827 } while (redef != NULL);
20828 return(0);
20832 static int
20833 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20834 xmlSchemaBucketPtr bucket)
20836 xmlSchemaBasicItemPtr item;
20837 int err;
20838 xmlHashTablePtr *table;
20839 const xmlChar *name;
20840 int i;
20842 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20843 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20844 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20845 else \
20846 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20849 * Add global components to the schema's hash tables.
20850 * This is the place where duplicate components will be
20851 * detected.
20852 * TODO: I think normally we should support imports of the
20853 * same namespace from multiple locations. We don't do currently,
20854 * but if we do then according to:
20855 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20856 * we would need, if imported directly, to import redefined
20857 * components as well to be able to catch clashing components.
20858 * (I hope I'll still know what this means after some months :-()
20860 if (bucket == NULL)
20861 return(-1);
20862 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20863 return(0);
20864 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20866 for (i = 0; i < bucket->globals->nbItems; i++) {
20867 item = bucket->globals->items[i];
20868 table = NULL;
20869 switch (item->type) {
20870 case XML_SCHEMA_TYPE_COMPLEX:
20871 case XML_SCHEMA_TYPE_SIMPLE:
20872 if (WXS_REDEFINED_TYPE(item))
20873 continue;
20874 name = (WXS_TYPE_CAST item)->name;
20875 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20876 break;
20877 case XML_SCHEMA_TYPE_ELEMENT:
20878 name = (WXS_ELEM_CAST item)->name;
20879 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20880 break;
20881 case XML_SCHEMA_TYPE_ATTRIBUTE:
20882 name = (WXS_ATTR_CAST item)->name;
20883 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20884 break;
20885 case XML_SCHEMA_TYPE_GROUP:
20886 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20887 continue;
20888 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20889 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20890 break;
20891 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20892 if (WXS_REDEFINED_ATTR_GROUP(item))
20893 continue;
20894 name = (WXS_ATTR_GROUP_CAST item)->name;
20895 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20896 break;
20897 case XML_SCHEMA_TYPE_IDC_KEY:
20898 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20899 case XML_SCHEMA_TYPE_IDC_KEYREF:
20900 name = (WXS_IDC_CAST item)->name;
20901 WXS_GET_GLOBAL_HASH(bucket, idcDef)
20902 break;
20903 case XML_SCHEMA_TYPE_NOTATION:
20904 name = ((xmlSchemaNotationPtr) item)->name;
20905 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20906 break;
20907 default:
20908 PERROR_INT("xmlSchemaAddComponents",
20909 "Unexpected global component type");
20910 continue;
20912 if (*table == NULL) {
20913 *table = xmlHashCreateDict(10, pctxt->dict);
20914 if (*table == NULL) {
20915 PERROR_INT("xmlSchemaAddComponents",
20916 "failed to create a component hash table");
20917 return(-1);
20920 err = xmlHashAddEntry(*table, name, item);
20921 if (err != 0) {
20922 xmlChar *str = NULL;
20924 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20925 XML_SCHEMAP_REDEFINED_TYPE,
20926 WXS_ITEM_NODE(item),
20927 WXS_BASIC_CAST item,
20928 "A global %s '%s' does already exist",
20929 WXS_ITEM_TYPE_NAME(item),
20930 xmlSchemaGetComponentQName(&str, item));
20931 FREE_AND_NULL(str);
20935 * Process imported/included schemas.
20937 if (bucket->relations != NULL) {
20938 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20939 do {
20940 if ((rel->bucket != NULL) &&
20941 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20942 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20943 return(-1);
20945 rel = rel->next;
20946 } while (rel != NULL);
20948 return(0);
20951 static int
20952 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20953 xmlSchemaBucketPtr rootBucket)
20955 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20956 xmlSchemaTreeItemPtr item, *items;
20957 int nbItems, i, ret = 0;
20958 xmlSchemaBucketPtr oldbucket = con->bucket;
20959 xmlSchemaElementPtr elemDecl;
20961 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20963 if ((con->pending == NULL) ||
20964 (con->pending->nbItems == 0))
20965 return(0);
20968 * Since xmlSchemaFixupComplexType() will create new particles
20969 * (local components), and those particle components need a bucket
20970 * on the constructor, we'll assure here that the constructor has
20971 * a bucket.
20972 * TODO: Think about storing locals _only_ on the main bucket.
20974 if (con->bucket == NULL)
20975 con->bucket = rootBucket;
20977 /* TODO:
20978 * SPEC (src-redefine):
20979 * (6.2) "If it has no such self-reference, then all of the
20980 * following must be true:"
20982 * (6.2.2) The {model group} of the model group definition which
20983 * corresponds to it per XML Representation of Model Group
20984 * Definition Schema Components ($3.7.2) must be a `valid
20985 * restriction` of the {model group} of that model group definition
20986 * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20988 xmlSchemaCheckSRCRedefineFirst(pctxt);
20991 * Add global components to the schemata's hash tables.
20993 xmlSchemaAddComponents(pctxt, rootBucket);
20995 pctxt->ctxtType = NULL;
20996 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20997 nbItems = con->pending->nbItems;
20999 * Now that we have parsed *all* the schema document(s) and converted
21000 * them to schema components, we can resolve references, apply component
21001 * constraints, create the FSA from the content model, etc.
21004 * Resolve references of..
21006 * 1. element declarations:
21007 * - the type definition
21008 * - the substitution group affiliation
21009 * 2. simple/complex types:
21010 * - the base type definition
21011 * - the memberTypes of union types
21012 * - the itemType of list types
21013 * 3. attributes declarations and attribute uses:
21014 * - the type definition
21015 * - if an attribute use, then the attribute declaration
21016 * 4. attribute group references:
21017 * - the attribute group definition
21018 * 5. particles:
21019 * - the term of the particle (e.g. a model group)
21020 * 6. IDC key-references:
21021 * - the referenced IDC 'key' or 'unique' definition
21022 * 7. Attribute prohibitions which had a "ref" attribute.
21024 for (i = 0; i < nbItems; i++) {
21025 item = items[i];
21026 switch (item->type) {
21027 case XML_SCHEMA_TYPE_ELEMENT:
21028 xmlSchemaResolveElementReferences(
21029 (xmlSchemaElementPtr) item, pctxt);
21030 FIXHFAILURE;
21031 break;
21032 case XML_SCHEMA_TYPE_COMPLEX:
21033 case XML_SCHEMA_TYPE_SIMPLE:
21034 xmlSchemaResolveTypeReferences(
21035 (xmlSchemaTypePtr) item, pctxt);
21036 FIXHFAILURE;
21037 break;
21038 case XML_SCHEMA_TYPE_ATTRIBUTE:
21039 xmlSchemaResolveAttrTypeReferences(
21040 (xmlSchemaAttributePtr) item, pctxt);
21041 FIXHFAILURE;
21042 break;
21043 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21044 xmlSchemaResolveAttrUseReferences(
21045 (xmlSchemaAttributeUsePtr) item, pctxt);
21046 FIXHFAILURE;
21047 break;
21048 case XML_SCHEMA_EXTRA_QNAMEREF:
21049 if ((WXS_QNAME_CAST item)->itemType ==
21050 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
21052 xmlSchemaResolveAttrGroupReferences(
21053 WXS_QNAME_CAST item, pctxt);
21055 FIXHFAILURE;
21056 break;
21057 case XML_SCHEMA_TYPE_SEQUENCE:
21058 case XML_SCHEMA_TYPE_CHOICE:
21059 case XML_SCHEMA_TYPE_ALL:
21060 xmlSchemaResolveModelGroupParticleReferences(pctxt,
21061 WXS_MODEL_GROUP_CAST item);
21062 FIXHFAILURE;
21063 break;
21064 case XML_SCHEMA_TYPE_IDC_KEY:
21065 case XML_SCHEMA_TYPE_IDC_UNIQUE:
21066 case XML_SCHEMA_TYPE_IDC_KEYREF:
21067 xmlSchemaResolveIDCKeyReferences(
21068 (xmlSchemaIDCPtr) item, pctxt);
21069 FIXHFAILURE;
21070 break;
21071 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
21073 * Handle attribute prohibition which had a
21074 * "ref" attribute.
21076 xmlSchemaResolveAttrUseProhibReferences(
21077 WXS_ATTR_PROHIB_CAST item, pctxt);
21078 FIXHFAILURE;
21079 break;
21080 default:
21081 break;
21084 if (pctxt->nberrors != 0)
21085 goto exit_error;
21088 * Now that all references are resolved we
21089 * can check for circularity of...
21090 * 1. the base axis of type definitions
21091 * 2. nested model group definitions
21092 * 3. nested attribute group definitions
21093 * TODO: check for circular substitution groups.
21095 for (i = 0; i < nbItems; i++) {
21096 item = items[i];
21098 * Let's better stop on the first error here.
21100 switch (item->type) {
21101 case XML_SCHEMA_TYPE_COMPLEX:
21102 case XML_SCHEMA_TYPE_SIMPLE:
21103 xmlSchemaCheckTypeDefCircular(
21104 (xmlSchemaTypePtr) item, pctxt);
21105 FIXHFAILURE;
21106 if (pctxt->nberrors != 0)
21107 goto exit_error;
21108 break;
21109 case XML_SCHEMA_TYPE_GROUP:
21110 xmlSchemaCheckGroupDefCircular(
21111 (xmlSchemaModelGroupDefPtr) item, pctxt);
21112 FIXHFAILURE;
21113 if (pctxt->nberrors != 0)
21114 goto exit_error;
21115 break;
21116 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21117 xmlSchemaCheckAttrGroupCircular(
21118 (xmlSchemaAttributeGroupPtr) item, pctxt);
21119 FIXHFAILURE;
21120 if (pctxt->nberrors != 0)
21121 goto exit_error;
21122 break;
21123 default:
21124 break;
21127 if (pctxt->nberrors != 0)
21128 goto exit_error;
21130 * Model group definition references:
21131 * Such a reference is reflected by a particle at the component
21132 * level. Until now the 'term' of such particles pointed
21133 * to the model group definition; this was done, in order to
21134 * ease circularity checks. Now we need to set the 'term' of
21135 * such particles to the model group of the model group definition.
21137 for (i = 0; i < nbItems; i++) {
21138 item = items[i];
21139 switch (item->type) {
21140 case XML_SCHEMA_TYPE_SEQUENCE:
21141 case XML_SCHEMA_TYPE_CHOICE:
21142 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21143 WXS_MODEL_GROUP_CAST item);
21144 break;
21145 default:
21146 break;
21149 if (pctxt->nberrors != 0)
21150 goto exit_error;
21152 * Expand attribute group references of attribute group definitions.
21154 for (i = 0; i < nbItems; i++) {
21155 item = items[i];
21156 switch (item->type) {
21157 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21158 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21159 WXS_ATTR_GROUP_HAS_REFS(item))
21161 xmlSchemaAttributeGroupExpandRefs(pctxt,
21162 WXS_ATTR_GROUP_CAST item);
21163 FIXHFAILURE;
21165 break;
21166 default:
21167 break;
21170 if (pctxt->nberrors != 0)
21171 goto exit_error;
21173 * First compute the variety of simple types. This is needed as
21174 * a separate step, since otherwise we won't be able to detect
21175 * circular union types in all cases.
21177 for (i = 0; i < nbItems; i++) {
21178 item = items[i];
21179 switch (item->type) {
21180 case XML_SCHEMA_TYPE_SIMPLE:
21181 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21182 xmlSchemaFixupSimpleTypeStageOne(pctxt,
21183 (xmlSchemaTypePtr) item);
21184 FIXHFAILURE;
21186 break;
21187 default:
21188 break;
21191 if (pctxt->nberrors != 0)
21192 goto exit_error;
21194 * Detect circular union types. Note that this needs the variety to
21195 * be already computed.
21197 for (i = 0; i < nbItems; i++) {
21198 item = items[i];
21199 switch (item->type) {
21200 case XML_SCHEMA_TYPE_SIMPLE:
21201 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21202 xmlSchemaCheckUnionTypeDefCircular(pctxt,
21203 (xmlSchemaTypePtr) item);
21204 FIXHFAILURE;
21206 break;
21207 default:
21208 break;
21211 if (pctxt->nberrors != 0)
21212 goto exit_error;
21215 * Do the complete type fixup for simple types.
21217 for (i = 0; i < nbItems; i++) {
21218 item = items[i];
21219 switch (item->type) {
21220 case XML_SCHEMA_TYPE_SIMPLE:
21221 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21222 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21223 FIXHFAILURE;
21225 break;
21226 default:
21227 break;
21230 if (pctxt->nberrors != 0)
21231 goto exit_error;
21233 * At this point we need build and check all simple types.
21236 * Apply constraints for attribute declarations.
21238 for (i = 0; i < nbItems; i++) {
21239 item = items[i];
21240 switch (item->type) {
21241 case XML_SCHEMA_TYPE_ATTRIBUTE:
21242 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21243 FIXHFAILURE;
21244 break;
21245 default:
21246 break;
21249 if (pctxt->nberrors != 0)
21250 goto exit_error;
21252 * Apply constraints for attribute uses.
21254 for (i = 0; i < nbItems; i++) {
21255 item = items[i];
21256 switch (item->type) {
21257 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21258 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21259 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21260 WXS_ATTR_USE_CAST item);
21261 FIXHFAILURE;
21263 break;
21264 default:
21265 break;
21268 if (pctxt->nberrors != 0)
21269 goto exit_error;
21272 * Apply constraints for attribute group definitions.
21274 for (i = 0; i < nbItems; i++) {
21275 item = items[i];
21276 switch (item->type) {
21277 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21278 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21279 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21281 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21282 FIXHFAILURE;
21284 break;
21285 default:
21286 break;
21289 if (pctxt->nberrors != 0)
21290 goto exit_error;
21293 * Apply constraints for redefinitions.
21295 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21296 xmlSchemaCheckSRCRedefineSecond(pctxt);
21297 if (pctxt->nberrors != 0)
21298 goto exit_error;
21301 * Complex types are built and checked.
21303 for (i = 0; i < nbItems; i++) {
21304 item = con->pending->items[i];
21305 switch (item->type) {
21306 case XML_SCHEMA_TYPE_COMPLEX:
21307 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21308 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21309 FIXHFAILURE;
21311 break;
21312 default:
21313 break;
21316 if (pctxt->nberrors != 0)
21317 goto exit_error;
21320 * The list could have changed, since xmlSchemaFixupComplexType()
21321 * will create particles and model groups in some cases.
21323 items = (xmlSchemaTreeItemPtr *) con->pending->items;
21324 nbItems = con->pending->nbItems;
21327 * Apply some constraints for element declarations.
21329 for (i = 0; i < nbItems; i++) {
21330 item = items[i];
21331 switch (item->type) {
21332 case XML_SCHEMA_TYPE_ELEMENT:
21333 elemDecl = (xmlSchemaElementPtr) item;
21335 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21337 xmlSchemaCheckElementDeclComponent(
21338 (xmlSchemaElementPtr) elemDecl, pctxt);
21339 FIXHFAILURE;
21342 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21344 * Schema Component Constraint: Element Declarations Consistent
21345 * Apply this constraint to local types of element declarations.
21347 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21348 (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21349 (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21351 xmlSchemaCheckElementDeclConsistent(pctxt,
21352 WXS_BASIC_CAST elemDecl,
21353 WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21354 NULL, NULL, 0);
21356 #endif
21357 break;
21358 default:
21359 break;
21362 if (pctxt->nberrors != 0)
21363 goto exit_error;
21366 * Finally we can build the automaton from the content model of
21367 * complex types.
21370 for (i = 0; i < nbItems; i++) {
21371 item = items[i];
21372 switch (item->type) {
21373 case XML_SCHEMA_TYPE_COMPLEX:
21374 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21375 /* FIXHFAILURE; */
21376 break;
21377 default:
21378 break;
21381 if (pctxt->nberrors != 0)
21382 goto exit_error;
21384 * URGENT TODO: cos-element-consistent
21386 goto exit;
21388 exit_error:
21389 ret = pctxt->err;
21390 goto exit;
21392 exit_failure:
21393 ret = -1;
21395 exit:
21397 * Reset the constructor. This is needed for XSI acquisition, since
21398 * those items will be processed over and over again for every XSI
21399 * if not cleared here.
21401 con->bucket = oldbucket;
21402 con->pending->nbItems = 0;
21403 if (con->substGroups != NULL) {
21404 xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21405 con->substGroups = NULL;
21407 if (con->redefs != NULL) {
21408 xmlSchemaRedefListFree(con->redefs);
21409 con->redefs = NULL;
21411 return(ret);
21414 * xmlSchemaParse:
21415 * @ctxt: a schema validation context
21417 * parse a schema definition resource and build an internal
21418 * XML Schema structure which can be used to validate instances.
21420 * Returns the internal XML Schema structure built from the resource or
21421 * NULL in case of error
21423 xmlSchemaPtr
21424 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21426 xmlSchemaPtr mainSchema = NULL;
21427 xmlSchemaBucketPtr bucket = NULL;
21428 int res;
21431 * This one is used if the schema to be parsed was specified via
21432 * the API; i.e. not automatically by the validated instance document.
21435 xmlSchemaInitTypes();
21437 if (ctxt == NULL)
21438 return (NULL);
21440 /* TODO: Init the context. Is this all we need?*/
21441 ctxt->nberrors = 0;
21442 ctxt->err = 0;
21443 ctxt->counter = 0;
21445 /* Create the *main* schema. */
21446 mainSchema = xmlSchemaNewSchema(ctxt);
21447 if (mainSchema == NULL)
21448 goto exit_failure;
21450 * Create the schema constructor.
21452 if (ctxt->constructor == NULL) {
21453 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21454 if (ctxt->constructor == NULL)
21455 return(NULL);
21456 /* Take ownership of the constructor to be able to free it. */
21457 ctxt->ownsConstructor = 1;
21459 ctxt->constructor->mainSchema = mainSchema;
21461 * Locate and add the schema document.
21463 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21464 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21465 NULL, NULL, &bucket);
21466 if (res == -1)
21467 goto exit_failure;
21468 if (res != 0)
21469 goto exit;
21471 if (bucket == NULL) {
21472 /* TODO: Error code, actually we failed to *locate* the schema. */
21473 if (ctxt->URL)
21474 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21475 NULL, NULL,
21476 "Failed to locate the main schema resource at '%s'",
21477 ctxt->URL, NULL);
21478 else
21479 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21480 NULL, NULL,
21481 "Failed to locate the main schema resource",
21482 NULL, NULL);
21483 goto exit;
21485 /* Then do the parsing for good. */
21486 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21487 goto exit_failure;
21488 if (ctxt->nberrors != 0)
21489 goto exit;
21491 mainSchema->doc = bucket->doc;
21492 mainSchema->preserve = ctxt->preserve;
21494 ctxt->schema = mainSchema;
21496 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21497 goto exit_failure;
21500 * TODO: This is not nice, since we cannot distinguish from the
21501 * result if there was an internal error or not.
21503 exit:
21504 if (ctxt->nberrors != 0) {
21505 if (mainSchema) {
21506 xmlSchemaFree(mainSchema);
21507 mainSchema = NULL;
21509 if (ctxt->constructor) {
21510 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21511 ctxt->constructor = NULL;
21512 ctxt->ownsConstructor = 0;
21515 ctxt->schema = NULL;
21516 return(mainSchema);
21517 exit_failure:
21519 * Quite verbose, but should catch internal errors, which were
21520 * not communicated.
21522 if (mainSchema) {
21523 xmlSchemaFree(mainSchema);
21524 mainSchema = NULL;
21526 if (ctxt->constructor) {
21527 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21528 ctxt->constructor = NULL;
21529 ctxt->ownsConstructor = 0;
21531 PERROR_INT2("xmlSchemaParse",
21532 "An internal error occurred");
21533 ctxt->schema = NULL;
21534 return(NULL);
21538 * xmlSchemaSetParserErrors:
21539 * @ctxt: a schema validation context
21540 * @err: the error callback
21541 * @warn: the warning callback
21542 * @ctx: contextual data for the callbacks
21544 * Set the callback functions used to handle errors for a validation context
21546 void
21547 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21548 xmlSchemaValidityErrorFunc err,
21549 xmlSchemaValidityWarningFunc warn, void *ctx)
21551 if (ctxt == NULL)
21552 return;
21553 ctxt->error = err;
21554 ctxt->warning = warn;
21555 ctxt->errCtxt = ctx;
21556 if (ctxt->vctxt != NULL)
21557 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21561 * xmlSchemaSetParserStructuredErrors:
21562 * @ctxt: a schema parser context
21563 * @serror: the structured error function
21564 * @ctx: the functions context
21566 * Set the structured error callback
21568 void
21569 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21570 xmlStructuredErrorFunc serror,
21571 void *ctx)
21573 if (ctxt == NULL)
21574 return;
21575 ctxt->serror = serror;
21576 ctxt->errCtxt = ctx;
21577 if (ctxt->vctxt != NULL)
21578 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21582 * xmlSchemaGetParserErrors:
21583 * @ctxt: a XMl-Schema parser context
21584 * @err: the error callback result
21585 * @warn: the warning callback result
21586 * @ctx: contextual data for the callbacks result
21588 * Get the callback information used to handle errors for a parser context
21590 * Returns -1 in case of failure, 0 otherwise
21593 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21594 xmlSchemaValidityErrorFunc * err,
21595 xmlSchemaValidityWarningFunc * warn, void **ctx)
21597 if (ctxt == NULL)
21598 return(-1);
21599 if (err != NULL)
21600 *err = ctxt->error;
21601 if (warn != NULL)
21602 *warn = ctxt->warning;
21603 if (ctx != NULL)
21604 *ctx = ctxt->errCtxt;
21605 return(0);
21609 * xmlSchemaFacetTypeToString:
21610 * @type: the facet type
21612 * Convert the xmlSchemaTypeType to a char string.
21614 * Returns the char string representation of the facet type if the
21615 * type is a facet and an "Internal Error" string otherwise.
21617 static const xmlChar *
21618 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21620 switch (type) {
21621 case XML_SCHEMA_FACET_PATTERN:
21622 return (BAD_CAST "pattern");
21623 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21624 return (BAD_CAST "maxExclusive");
21625 case XML_SCHEMA_FACET_MAXINCLUSIVE:
21626 return (BAD_CAST "maxInclusive");
21627 case XML_SCHEMA_FACET_MINEXCLUSIVE:
21628 return (BAD_CAST "minExclusive");
21629 case XML_SCHEMA_FACET_MININCLUSIVE:
21630 return (BAD_CAST "minInclusive");
21631 case XML_SCHEMA_FACET_WHITESPACE:
21632 return (BAD_CAST "whiteSpace");
21633 case XML_SCHEMA_FACET_ENUMERATION:
21634 return (BAD_CAST "enumeration");
21635 case XML_SCHEMA_FACET_LENGTH:
21636 return (BAD_CAST "length");
21637 case XML_SCHEMA_FACET_MAXLENGTH:
21638 return (BAD_CAST "maxLength");
21639 case XML_SCHEMA_FACET_MINLENGTH:
21640 return (BAD_CAST "minLength");
21641 case XML_SCHEMA_FACET_TOTALDIGITS:
21642 return (BAD_CAST "totalDigits");
21643 case XML_SCHEMA_FACET_FRACTIONDIGITS:
21644 return (BAD_CAST "fractionDigits");
21645 default:
21646 break;
21648 return (BAD_CAST "Internal Error");
21651 static xmlSchemaWhitespaceValueType
21652 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21655 * The normalization type can be changed only for types which are derived
21656 * from xsd:string.
21658 if (type->type == XML_SCHEMA_TYPE_BASIC) {
21660 * Note that we assume a whitespace of preserve for anySimpleType.
21662 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21663 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21664 return(XML_SCHEMA_WHITESPACE_PRESERVE);
21665 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21666 return(XML_SCHEMA_WHITESPACE_REPLACE);
21667 else {
21669 * For all `atomic` datatypes other than string (and types `derived`
21670 * by `restriction` from it) the value of whiteSpace is fixed to
21671 * collapse
21672 * Note that this includes built-in list datatypes.
21674 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21676 } else if (WXS_IS_LIST(type)) {
21678 * For list types the facet "whiteSpace" is fixed to "collapse".
21680 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21681 } else if (WXS_IS_UNION(type)) {
21682 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21683 } else if (WXS_IS_ATOMIC(type)) {
21684 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21685 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21686 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21687 return (XML_SCHEMA_WHITESPACE_REPLACE);
21688 else
21689 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21691 return (-1);
21694 /************************************************************************
21696 * Simple type validation *
21698 ************************************************************************/
21701 /************************************************************************
21703 * DOM Validation code *
21705 ************************************************************************/
21708 * xmlSchemaAssembleByLocation:
21709 * @pctxt: a schema parser context
21710 * @vctxt: a schema validation context
21711 * @schema: the existing schema
21712 * @node: the node that fired the assembling
21713 * @nsName: the namespace name of the new schema
21714 * @location: the location of the schema
21716 * Expands an existing schema by an additional schema.
21718 * Returns 0 if the new schema is correct, a positive error code
21719 * number otherwise and -1 in case of an internal or API error.
21721 static int
21722 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21723 xmlSchemaPtr schema,
21724 xmlNodePtr node,
21725 const xmlChar *nsName,
21726 const xmlChar *location)
21728 int ret = 0;
21729 xmlSchemaParserCtxtPtr pctxt;
21730 xmlSchemaBucketPtr bucket = NULL;
21732 if ((vctxt == NULL) || (schema == NULL))
21733 return (-1);
21735 if (vctxt->pctxt == NULL) {
21736 VERROR_INT("xmlSchemaAssembleByLocation",
21737 "no parser context available");
21738 return(-1);
21740 pctxt = vctxt->pctxt;
21741 if (pctxt->constructor == NULL) {
21742 PERROR_INT("xmlSchemaAssembleByLocation",
21743 "no constructor");
21744 return(-1);
21747 * Acquire the schema document.
21749 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21750 location, node);
21752 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21753 * the process will automatically change this to
21754 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21756 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21757 location, NULL, NULL, 0, node, NULL, nsName,
21758 &bucket);
21759 if (ret != 0)
21760 return(ret);
21761 if (bucket == NULL) {
21763 * Generate a warning that the document could not be located.
21765 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21766 node, NULL,
21767 "The document at location '%s' could not be acquired",
21768 location, NULL, NULL);
21769 return(ret);
21772 * The first located schema will be handled as if all other
21773 * schemas imported by XSI were imported by this first schema.
21775 if ((bucket != NULL) &&
21776 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21777 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21779 * TODO: Is this handled like an import? I.e. is it not an error
21780 * if the schema cannot be located?
21782 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21783 return(0);
21785 * We will reuse the parser context for every schema imported
21786 * directly via XSI. So reset the context.
21788 pctxt->nberrors = 0;
21789 pctxt->err = 0;
21790 pctxt->doc = bucket->doc;
21792 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21793 if (ret == -1) {
21794 pctxt->doc = NULL;
21795 goto exit_failure;
21797 /* Paranoid error channelling. */
21798 if ((ret == 0) && (pctxt->nberrors != 0))
21799 ret = pctxt->err;
21800 if (pctxt->nberrors == 0) {
21802 * Only bother to fixup pending components, if there was
21803 * no error yet.
21804 * For every XSI acquired schema (and its sub-schemata) we will
21805 * fixup the components.
21807 xmlSchemaFixupComponents(pctxt, bucket);
21808 ret = pctxt->err;
21810 * Not nice, but we need somehow to channel the schema parser
21811 * error to the validation context.
21813 if ((ret != 0) && (vctxt->err == 0))
21814 vctxt->err = ret;
21815 vctxt->nberrors += pctxt->nberrors;
21816 } else {
21817 /* Add to validation error sum. */
21818 vctxt->nberrors += pctxt->nberrors;
21820 pctxt->doc = NULL;
21821 return(ret);
21822 exit_failure:
21823 pctxt->doc = NULL;
21824 return (-1);
21827 static xmlSchemaAttrInfoPtr
21828 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21829 int metaType)
21831 if (vctxt->nbAttrInfos == 0)
21832 return (NULL);
21834 int i;
21835 xmlSchemaAttrInfoPtr iattr;
21837 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21838 iattr = vctxt->attrInfos[i];
21839 if (iattr->metaType == metaType)
21840 return (iattr);
21844 return (NULL);
21848 * xmlSchemaAssembleByXSI:
21849 * @vctxt: a schema validation context
21851 * Expands an existing schema by an additional schema using
21852 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21853 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21854 * must be set to 1.
21856 * Returns 0 if the new schema is correct, a positive error code
21857 * number otherwise and -1 in case of an internal or API error.
21859 static int
21860 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21862 const xmlChar *cur, *end;
21863 const xmlChar *nsname = NULL, *location;
21864 int count = 0;
21865 int ret = 0;
21866 xmlSchemaAttrInfoPtr iattr;
21869 * Parse the value; we will assume an even number of values
21870 * to be given (this is how Xerces and XSV work).
21872 * URGENT TODO: !! This needs to work for both
21873 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21874 * element !!
21876 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21877 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21878 if (iattr == NULL)
21879 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21880 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21881 if (iattr == NULL)
21882 return (0);
21883 cur = iattr->value;
21884 do {
21886 * TODO: Move the string parsing mechanism away from here.
21888 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21890 * Get the namespace name.
21892 while (IS_BLANK_CH(*cur))
21893 cur++;
21894 end = cur;
21895 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21896 end++;
21897 if (end == cur)
21898 break;
21899 count++; /* TODO: Don't use the schema's dict. */
21900 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21901 cur = end;
21904 * Get the URI.
21906 while (IS_BLANK_CH(*cur))
21907 cur++;
21908 end = cur;
21909 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21910 end++;
21911 if (end == cur) {
21912 if (iattr->metaType ==
21913 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21916 * If using @schemaLocation then tuples are expected.
21917 * I.e. the namespace name *and* the document's URI.
21919 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21920 iattr->node, NULL,
21921 "The value must consist of tuples: the target namespace "
21922 "name and the document's URI", NULL, NULL, NULL);
21924 break;
21926 count++; /* TODO: Don't use the schema's dict. */
21927 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21928 cur = end;
21929 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21930 iattr->node, nsname, location);
21931 if (ret == -1) {
21932 VERROR_INT("xmlSchemaAssembleByXSI",
21933 "assembling schemata");
21934 return (-1);
21936 } while (*cur != 0);
21937 return (ret);
21940 static const xmlChar *
21941 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21942 const xmlChar *prefix)
21944 if (vctxt->sax != NULL) {
21945 int i, j;
21946 xmlSchemaNodeInfoPtr inode;
21948 for (i = vctxt->depth; i >= 0; i--) {
21949 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21950 inode = vctxt->elemInfos[i];
21951 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21952 if (((prefix == NULL) &&
21953 (inode->nsBindings[j] == NULL)) ||
21954 ((prefix != NULL) && xmlStrEqual(prefix,
21955 inode->nsBindings[j]))) {
21958 * Note that the namespace bindings are already
21959 * in a string dict.
21961 return (inode->nsBindings[j+1]);
21966 return (NULL);
21967 #ifdef LIBXML_READER_ENABLED
21968 } else if (vctxt->reader != NULL) {
21969 xmlChar *nsName;
21971 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21972 if (nsName != NULL) {
21973 const xmlChar *ret;
21975 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21976 xmlFree(nsName);
21977 return (ret);
21978 } else
21979 return (NULL);
21980 #endif
21981 } else {
21982 xmlNsPtr ns;
21984 if ((vctxt->inode->node == NULL) ||
21985 (vctxt->inode->node->doc == NULL)) {
21986 VERROR_INT("xmlSchemaLookupNamespace",
21987 "no node or node's doc available");
21988 return (NULL);
21990 ns = xmlSearchNs(vctxt->inode->node->doc,
21991 vctxt->inode->node, prefix);
21992 if (ns != NULL)
21993 return (ns->href);
21994 return (NULL);
21999 * This one works on the schema of the validation context.
22001 static int
22002 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
22003 xmlSchemaPtr schema,
22004 xmlNodePtr node,
22005 const xmlChar *value,
22006 xmlSchemaValPtr *val,
22007 int valNeeded)
22009 int ret;
22011 if (vctxt && (vctxt->schema == NULL)) {
22012 VERROR_INT("xmlSchemaValidateNotation",
22013 "a schema is needed on the validation context");
22014 return (-1);
22016 ret = xmlValidateQName(value, 1);
22017 if (ret != 0)
22018 return (ret);
22020 xmlChar *localName = NULL;
22021 xmlChar *prefix = NULL;
22023 localName = xmlSplitQName2(value, &prefix);
22024 if (prefix != NULL) {
22025 const xmlChar *nsName = NULL;
22027 if (vctxt != NULL)
22028 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
22029 else if (node != NULL) {
22030 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
22031 if (ns != NULL)
22032 nsName = ns->href;
22033 } else {
22034 xmlFree(prefix);
22035 xmlFree(localName);
22036 return (1);
22038 if (nsName == NULL) {
22039 xmlFree(prefix);
22040 xmlFree(localName);
22041 return (1);
22043 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
22044 if ((valNeeded) && (val != NULL)) {
22045 (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
22046 xmlStrdup(nsName));
22047 if (*val == NULL)
22048 ret = -1;
22050 } else
22051 ret = 1;
22052 xmlFree(prefix);
22053 xmlFree(localName);
22054 } else {
22055 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
22056 if (valNeeded && (val != NULL)) {
22057 (*val) = xmlSchemaNewNOTATIONValue(
22058 BAD_CAST xmlStrdup(value), NULL);
22059 if (*val == NULL)
22060 ret = -1;
22062 } else
22063 return (1);
22066 return (ret);
22069 static int
22070 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
22071 const xmlChar* lname,
22072 const xmlChar* nsname)
22074 int i;
22076 lname = xmlDictLookup(vctxt->dict, lname, -1);
22077 if (lname == NULL)
22078 return(-1);
22079 if (nsname != NULL) {
22080 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
22081 if (nsname == NULL)
22082 return(-1);
22084 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
22085 if ((vctxt->nodeQNames->items [i] == lname) &&
22086 (vctxt->nodeQNames->items[i +1] == nsname))
22087 /* Already there */
22088 return(i);
22090 /* Add new entry. */
22091 i = vctxt->nodeQNames->nbItems;
22092 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
22093 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
22094 return(i);
22097 /************************************************************************
22099 * Validation of identity-constraints (IDC) *
22101 ************************************************************************/
22104 * xmlSchemaAugmentIDC:
22105 * @idcDef: the IDC definition
22107 * Creates an augmented IDC definition item.
22109 * Returns the item, or NULL on internal errors.
22111 static void
22112 xmlSchemaAugmentIDC(void *payload, void *data,
22113 const xmlChar *name ATTRIBUTE_UNUSED)
22115 xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
22116 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22117 xmlSchemaIDCAugPtr aidc;
22119 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
22120 if (aidc == NULL) {
22121 xmlSchemaVErrMemory(vctxt,
22122 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
22123 NULL);
22124 return;
22126 aidc->keyrefDepth = -1;
22127 aidc->def = idcDef;
22128 aidc->next = NULL;
22129 if (vctxt->aidcs == NULL)
22130 vctxt->aidcs = aidc;
22131 else {
22132 aidc->next = vctxt->aidcs;
22133 vctxt->aidcs = aidc;
22136 * Save if we have keyrefs at all.
22138 if ((vctxt->hasKeyrefs == 0) &&
22139 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22140 vctxt->hasKeyrefs = 1;
22144 * xmlSchemaAugmentImportedIDC:
22145 * @imported: the imported schema
22147 * Creates an augmented IDC definition for the imported schema.
22149 static void
22150 xmlSchemaAugmentImportedIDC(void *payload, void *data,
22151 const xmlChar *name ATTRIBUTE_UNUSED) {
22152 xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
22153 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22154 if (imported->schema->idcDef != NULL) {
22155 xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
22160 * xmlSchemaIDCNewBinding:
22161 * @idcDef: the IDC definition of this binding
22163 * Creates a new IDC binding.
22165 * Returns the new IDC binding, NULL on internal errors.
22167 static xmlSchemaPSVIIDCBindingPtr
22168 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22170 xmlSchemaPSVIIDCBindingPtr ret;
22172 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22173 sizeof(xmlSchemaPSVIIDCBinding));
22174 if (ret == NULL) {
22175 xmlSchemaVErrMemory(NULL,
22176 "allocating a PSVI IDC binding item", NULL);
22177 return (NULL);
22179 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22180 ret->definition = idcDef;
22181 return (ret);
22185 * xmlSchemaIDCStoreNodeTableItem:
22186 * @vctxt: the WXS validation context
22187 * @item: the IDC node table item
22189 * The validation context is used to store IDC node table items.
22190 * They are stored to avoid copying them if IDC node-tables are merged
22191 * with corresponding parent IDC node-tables (bubbling).
22193 * Returns 0 if succeeded, -1 on internal errors.
22195 static int
22196 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22197 xmlSchemaPSVIIDCNodePtr item)
22200 * Add to global list.
22202 if (vctxt->idcNodes == NULL) {
22203 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22204 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22205 if (vctxt->idcNodes == NULL) {
22206 xmlSchemaVErrMemory(vctxt,
22207 "allocating the IDC node table item list", NULL);
22208 return (-1);
22210 vctxt->sizeIdcNodes = 20;
22211 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22212 vctxt->sizeIdcNodes *= 2;
22213 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22214 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22215 sizeof(xmlSchemaPSVIIDCNodePtr));
22216 if (vctxt->idcNodes == NULL) {
22217 xmlSchemaVErrMemory(vctxt,
22218 "re-allocating the IDC node table item list", NULL);
22219 return (-1);
22222 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22224 return (0);
22228 * xmlSchemaIDCStoreKey:
22229 * @vctxt: the WXS validation context
22230 * @item: the IDC key
22232 * The validation context is used to store an IDC key.
22234 * Returns 0 if succeeded, -1 on internal errors.
22236 static int
22237 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22238 xmlSchemaPSVIIDCKeyPtr key)
22241 * Add to global list.
22243 if (vctxt->idcKeys == NULL) {
22244 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22245 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22246 if (vctxt->idcKeys == NULL) {
22247 xmlSchemaVErrMemory(vctxt,
22248 "allocating the IDC key storage list", NULL);
22249 return (-1);
22251 vctxt->sizeIdcKeys = 40;
22252 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22253 vctxt->sizeIdcKeys *= 2;
22254 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22255 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22256 sizeof(xmlSchemaPSVIIDCKeyPtr));
22257 if (vctxt->idcKeys == NULL) {
22258 xmlSchemaVErrMemory(vctxt,
22259 "re-allocating the IDC key storage list", NULL);
22260 return (-1);
22263 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22265 return (0);
22269 * xmlSchemaIDCAppendNodeTableItem:
22270 * @bind: the IDC binding
22271 * @ntItem: the node-table item
22273 * Appends the IDC node-table item to the binding.
22275 * Returns 0 on success and -1 on internal errors.
22277 static int
22278 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22279 xmlSchemaPSVIIDCNodePtr ntItem)
22281 if (bind->nodeTable == NULL) {
22282 bind->sizeNodes = 10;
22283 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22284 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22285 if (bind->nodeTable == NULL) {
22286 xmlSchemaVErrMemory(NULL,
22287 "allocating an array of IDC node-table items", NULL);
22288 return(-1);
22290 } else if (bind->sizeNodes <= bind->nbNodes) {
22291 bind->sizeNodes *= 2;
22292 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22293 xmlRealloc(bind->nodeTable, bind->sizeNodes *
22294 sizeof(xmlSchemaPSVIIDCNodePtr));
22295 if (bind->nodeTable == NULL) {
22296 xmlSchemaVErrMemory(NULL,
22297 "re-allocating an array of IDC node-table items", NULL);
22298 return(-1);
22301 bind->nodeTable[bind->nbNodes++] = ntItem;
22302 return(0);
22306 * xmlSchemaIDCAcquireBinding:
22307 * @vctxt: the WXS validation context
22308 * @matcher: the IDC matcher
22310 * Looks up an PSVI IDC binding, for the IDC definition and
22311 * of the given matcher. If none found, a new one is created
22312 * and added to the IDC table.
22314 * Returns an IDC binding or NULL on internal errors.
22316 static xmlSchemaPSVIIDCBindingPtr
22317 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22318 xmlSchemaIDCMatcherPtr matcher)
22320 xmlSchemaNodeInfoPtr ielem;
22322 ielem = vctxt->elemInfos[matcher->depth];
22324 if (ielem->idcTable == NULL) {
22325 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22326 if (ielem->idcTable == NULL)
22327 return (NULL);
22328 return(ielem->idcTable);
22329 } else {
22330 xmlSchemaPSVIIDCBindingPtr bind = NULL;
22332 bind = ielem->idcTable;
22333 do {
22334 if (bind->definition == matcher->aidc->def)
22335 return(bind);
22336 if (bind->next == NULL) {
22337 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22338 if (bind->next == NULL)
22339 return (NULL);
22340 return(bind->next);
22342 bind = bind->next;
22343 } while (bind != NULL);
22345 return (NULL);
22348 static xmlSchemaItemListPtr
22349 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22350 xmlSchemaIDCMatcherPtr matcher)
22352 if (matcher->targets == NULL)
22353 matcher->targets = xmlSchemaItemListCreate();
22354 return(matcher->targets);
22358 * xmlSchemaIDCFreeKey:
22359 * @key: the IDC key
22361 * Frees an IDC key together with its compiled value.
22363 static void
22364 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22366 if (key->val != NULL)
22367 xmlSchemaFreeValue(key->val);
22368 xmlFree(key);
22372 * xmlSchemaIDCFreeBinding:
22374 * Frees an IDC binding. Note that the node table-items
22375 * are not freed.
22377 static void
22378 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22380 if (bind->nodeTable != NULL)
22381 xmlFree(bind->nodeTable);
22382 if (bind->dupls != NULL)
22383 xmlSchemaItemListFree(bind->dupls);
22384 xmlFree(bind);
22388 * xmlSchemaIDCFreeIDCTable:
22389 * @bind: the first IDC binding in the list
22391 * Frees an IDC table, i.e. all the IDC bindings in the list.
22393 static void
22394 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22396 xmlSchemaPSVIIDCBindingPtr prev;
22398 while (bind != NULL) {
22399 prev = bind;
22400 bind = bind->next;
22401 xmlSchemaIDCFreeBinding(prev);
22405 static void
22406 xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
22408 xmlIDCHashEntryPtr e = payload, n;
22409 while (e) {
22410 n = e->next;
22411 xmlFree(e);
22412 e = n;
22417 * xmlSchemaIDCFreeMatcherList:
22418 * @matcher: the first IDC matcher in the list
22420 * Frees a list of IDC matchers.
22422 static void
22423 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22425 xmlSchemaIDCMatcherPtr next;
22427 while (matcher != NULL) {
22428 next = matcher->next;
22429 if (matcher->keySeqs != NULL) {
22430 int i;
22431 for (i = 0; i < matcher->sizeKeySeqs; i++)
22432 if (matcher->keySeqs[i] != NULL)
22433 xmlFree(matcher->keySeqs[i]);
22434 xmlFree(matcher->keySeqs);
22436 if (matcher->targets != NULL) {
22437 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22438 int i;
22439 xmlSchemaPSVIIDCNodePtr idcNode;
22441 * Node-table items for keyrefs are not stored globally
22442 * to the validation context, since they are not bubbled.
22443 * We need to free them here.
22445 for (i = 0; i < matcher->targets->nbItems; i++) {
22446 idcNode =
22447 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22448 xmlFree(idcNode->keys);
22449 xmlFree(idcNode);
22452 xmlSchemaItemListFree(matcher->targets);
22454 if (matcher->htab != NULL)
22455 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22456 xmlFree(matcher);
22457 matcher = next;
22462 * xmlSchemaIDCReleaseMatcherList:
22463 * @vctxt: the WXS validation context
22464 * @matcher: the first IDC matcher in the list
22466 * Caches a list of IDC matchers for reuse.
22468 static void
22469 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22470 xmlSchemaIDCMatcherPtr matcher)
22472 xmlSchemaIDCMatcherPtr next;
22474 while (matcher != NULL) {
22475 next = matcher->next;
22476 if (matcher->keySeqs != NULL) {
22477 int i;
22479 * Don't free the array, but only the content.
22481 for (i = 0; i < matcher->sizeKeySeqs; i++)
22482 if (matcher->keySeqs[i] != NULL) {
22483 xmlFree(matcher->keySeqs[i]);
22484 matcher->keySeqs[i] = NULL;
22487 if (matcher->targets) {
22488 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22489 int i;
22490 xmlSchemaPSVIIDCNodePtr idcNode;
22492 * Node-table items for keyrefs are not stored globally
22493 * to the validation context, since they are not bubbled.
22494 * We need to free them here.
22496 for (i = 0; i < matcher->targets->nbItems; i++) {
22497 idcNode =
22498 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22499 xmlFree(idcNode->keys);
22500 xmlFree(idcNode);
22503 xmlSchemaItemListFree(matcher->targets);
22504 matcher->targets = NULL;
22506 if (matcher->htab != NULL) {
22507 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22508 matcher->htab = NULL;
22510 matcher->next = NULL;
22512 * Cache the matcher.
22514 if (vctxt->idcMatcherCache != NULL)
22515 matcher->nextCached = vctxt->idcMatcherCache;
22516 vctxt->idcMatcherCache = matcher;
22518 matcher = next;
22523 * xmlSchemaIDCAddStateObject:
22524 * @vctxt: the WXS validation context
22525 * @matcher: the IDC matcher
22526 * @sel: the XPath information
22527 * @parent: the parent "selector" state object if any
22528 * @type: "selector" or "field"
22530 * Creates/reuses and activates state objects for the given
22531 * XPath information; if the XPath expression consists of unions,
22532 * multiple state objects are created for every unioned expression.
22534 * Returns 0 on success and -1 on internal errors.
22536 static int
22537 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22538 xmlSchemaIDCMatcherPtr matcher,
22539 xmlSchemaIDCSelectPtr sel,
22540 int type)
22542 xmlSchemaIDCStateObjPtr sto;
22545 * Reuse the state objects from the pool.
22547 if (vctxt->xpathStatePool != NULL) {
22548 sto = vctxt->xpathStatePool;
22549 vctxt->xpathStatePool = sto->next;
22550 sto->next = NULL;
22551 } else {
22553 * Create a new state object.
22555 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22556 if (sto == NULL) {
22557 xmlSchemaVErrMemory(NULL,
22558 "allocating an IDC state object", NULL);
22559 return (-1);
22561 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22564 * Add to global list.
22566 if (vctxt->xpathStates != NULL)
22567 sto->next = vctxt->xpathStates;
22568 vctxt->xpathStates = sto;
22571 * Free the old xpath validation context.
22573 if (sto->xpathCtxt != NULL)
22574 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22577 * Create a new XPath (pattern) validation context.
22579 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22580 (xmlPatternPtr) sel->xpathComp);
22581 if (sto->xpathCtxt == NULL) {
22582 VERROR_INT("xmlSchemaIDCAddStateObject",
22583 "failed to create an XPath validation context");
22584 return (-1);
22586 sto->type = type;
22587 sto->depth = vctxt->depth;
22588 sto->matcher = matcher;
22589 sto->sel = sel;
22590 sto->nbHistory = 0;
22592 #ifdef DEBUG_IDC
22593 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22594 sto->sel->xpath);
22595 #endif
22596 return (0);
22600 * xmlSchemaXPathEvaluate:
22601 * @vctxt: the WXS validation context
22602 * @nodeType: the nodeType of the current node
22604 * Evaluates all active XPath state objects.
22606 * Returns the number of IC "field" state objects which resolved to
22607 * this node, 0 if none resolved and -1 on internal errors.
22609 static int
22610 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22611 xmlElementType nodeType)
22613 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22614 int res, resolved = 0, depth = vctxt->depth;
22616 if (vctxt->xpathStates == NULL)
22617 return (0);
22619 if (nodeType == XML_ATTRIBUTE_NODE)
22620 depth++;
22621 #ifdef DEBUG_IDC
22623 xmlChar *str = NULL;
22624 xmlGenericError(xmlGenericErrorContext,
22625 "IDC: EVAL on %s, depth %d, type %d\n",
22626 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22627 vctxt->inode->localName), depth, nodeType);
22628 FREE_AND_NULL(str)
22630 #endif
22632 * Process all active XPath state objects.
22634 first = vctxt->xpathStates;
22635 sto = first;
22636 while (sto != head) {
22637 #ifdef DEBUG_IDC
22638 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22639 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22640 sto->matcher->aidc->def->name, sto->sel->xpath);
22641 else
22642 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22643 sto->matcher->aidc->def->name, sto->sel->xpath);
22644 #endif
22645 if (nodeType == XML_ELEMENT_NODE)
22646 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22647 vctxt->inode->localName, vctxt->inode->nsName);
22648 else
22649 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22650 vctxt->inode->localName, vctxt->inode->nsName);
22652 if (res == -1) {
22653 VERROR_INT("xmlSchemaXPathEvaluate",
22654 "calling xmlStreamPush()");
22655 return (-1);
22657 if (res == 0)
22658 goto next_sto;
22660 * Full match.
22662 #ifdef DEBUG_IDC
22663 xmlGenericError(xmlGenericErrorContext, "IDC: "
22664 "MATCH\n");
22665 #endif
22667 * Register a match in the state object history.
22669 if (sto->history == NULL) {
22670 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22671 if (sto->history == NULL) {
22672 xmlSchemaVErrMemory(NULL,
22673 "allocating the state object history", NULL);
22674 return(-1);
22676 sto->sizeHistory = 5;
22677 } else if (sto->sizeHistory <= sto->nbHistory) {
22678 sto->sizeHistory *= 2;
22679 sto->history = (int *) xmlRealloc(sto->history,
22680 sto->sizeHistory * sizeof(int));
22681 if (sto->history == NULL) {
22682 xmlSchemaVErrMemory(NULL,
22683 "re-allocating the state object history", NULL);
22684 return(-1);
22687 sto->history[sto->nbHistory++] = depth;
22689 #ifdef DEBUG_IDC
22690 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22691 vctxt->depth);
22692 #endif
22694 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22695 xmlSchemaIDCSelectPtr sel;
22697 * Activate state objects for the IDC fields of
22698 * the IDC selector.
22700 #ifdef DEBUG_IDC
22701 xmlGenericError(xmlGenericErrorContext, "IDC: "
22702 "activating field states\n");
22703 #endif
22704 sel = sto->matcher->aidc->def->fields;
22705 while (sel != NULL) {
22706 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22707 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22708 return (-1);
22709 sel = sel->next;
22711 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22713 * An IDC key node was found by the IDC field.
22715 #ifdef DEBUG_IDC
22716 xmlGenericError(xmlGenericErrorContext,
22717 "IDC: key found\n");
22718 #endif
22720 * Notify that the character value of this node is
22721 * needed.
22723 if (resolved == 0) {
22724 if ((vctxt->inode->flags &
22725 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22726 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22728 resolved++;
22730 next_sto:
22731 if (sto->next == NULL) {
22733 * Evaluate field state objects created on this node as well.
22735 head = first;
22736 sto = vctxt->xpathStates;
22737 } else
22738 sto = sto->next;
22740 return (resolved);
22743 static const xmlChar *
22744 xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
22745 xmlChar **buf,
22746 xmlSchemaPSVIIDCKeyPtr *seq,
22747 int count, int for_hash)
22749 int i, res;
22750 xmlChar *value = NULL;
22752 *buf = xmlStrdup(BAD_CAST "[");
22753 for (i = 0; i < count; i++) {
22754 *buf = xmlStrcat(*buf, BAD_CAST "'");
22755 if (!for_hash)
22756 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22757 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22758 &value);
22759 else {
22760 res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
22762 if (res == 0)
22763 *buf = xmlStrcat(*buf, BAD_CAST value);
22764 else {
22765 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22766 "failed to compute a canonical value");
22767 *buf = xmlStrcat(*buf, BAD_CAST "???");
22769 if (i < count -1)
22770 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22771 else
22772 *buf = xmlStrcat(*buf, BAD_CAST "'");
22773 if (value != NULL) {
22774 xmlFree(value);
22775 value = NULL;
22778 *buf = xmlStrcat(*buf, BAD_CAST "]");
22780 return (BAD_CAST *buf);
22783 static const xmlChar *
22784 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22785 xmlChar **buf,
22786 xmlSchemaPSVIIDCKeyPtr *seq,
22787 int count)
22789 return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
22792 static const xmlChar *
22793 xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
22794 xmlChar **buf,
22795 xmlSchemaPSVIIDCKeyPtr *seq,
22796 int count)
22798 return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
22802 * xmlSchemaXPathPop:
22803 * @vctxt: the WXS validation context
22805 * Pops all XPath states.
22807 * Returns 0 on success and -1 on internal errors.
22809 static int
22810 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22812 xmlSchemaIDCStateObjPtr sto;
22813 int res;
22815 if (vctxt->xpathStates == NULL)
22816 return(0);
22817 sto = vctxt->xpathStates;
22818 do {
22819 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22820 if (res == -1)
22821 return (-1);
22822 sto = sto->next;
22823 } while (sto != NULL);
22824 return(0);
22828 * xmlSchemaXPathProcessHistory:
22829 * @vctxt: the WXS validation context
22830 * @type: the simple/complex type of the current node if any at all
22831 * @val: the precompiled value
22833 * Processes and pops the history items of the IDC state objects.
22834 * IDC key-sequences are validated/created on IDC bindings.
22836 * Returns 0 on success and -1 on internal errors.
22838 static int
22839 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22840 int depth)
22842 xmlSchemaIDCStateObjPtr sto, nextsto;
22843 int res, matchDepth;
22844 xmlSchemaPSVIIDCKeyPtr key = NULL;
22845 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22847 if (vctxt->xpathStates == NULL)
22848 return (0);
22849 sto = vctxt->xpathStates;
22851 #ifdef DEBUG_IDC
22853 xmlChar *str = NULL;
22854 xmlGenericError(xmlGenericErrorContext,
22855 "IDC: BACK on %s, depth %d\n",
22856 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22857 vctxt->inode->localName), vctxt->depth);
22858 FREE_AND_NULL(str)
22860 #endif
22862 * Evaluate the state objects.
22864 while (sto != NULL) {
22865 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22866 if (res == -1) {
22867 VERROR_INT("xmlSchemaXPathProcessHistory",
22868 "calling xmlStreamPop()");
22869 return (-1);
22871 #ifdef DEBUG_IDC
22872 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22873 sto->sel->xpath);
22874 #endif
22875 if (sto->nbHistory == 0)
22876 goto deregister_check;
22878 matchDepth = sto->history[sto->nbHistory -1];
22881 * Only matches at the current depth are of interest.
22883 if (matchDepth != depth) {
22884 sto = sto->next;
22885 continue;
22887 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22889 * NOTE: According to
22890 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22891 * ... the simple-content of complex types is also allowed.
22894 if (WXS_IS_COMPLEX(type)) {
22895 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22897 * Sanity check for complex types with simple content.
22899 simpleType = type->contentTypeDef;
22900 if (simpleType == NULL) {
22901 VERROR_INT("xmlSchemaXPathProcessHistory",
22902 "field resolves to a CT with simple content "
22903 "but the CT is missing the ST definition");
22904 return (-1);
22906 } else
22907 simpleType = NULL;
22908 } else
22909 simpleType = type;
22910 if (simpleType == NULL) {
22911 xmlChar *str = NULL;
22914 * Not qualified if the field resolves to a node of non
22915 * simple type.
22917 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22918 XML_SCHEMAV_CVC_IDC, NULL,
22919 WXS_BASIC_CAST sto->matcher->aidc->def,
22920 "The XPath '%s' of a field of %s does evaluate to a node of "
22921 "non-simple type",
22922 sto->sel->xpath,
22923 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22924 FREE_AND_NULL(str);
22925 sto->nbHistory--;
22926 goto deregister_check;
22929 if ((key == NULL) && (vctxt->inode->val == NULL)) {
22931 * Failed to provide the normalized value; maybe
22932 * the value was invalid.
22934 VERROR(XML_SCHEMAV_CVC_IDC,
22935 WXS_BASIC_CAST sto->matcher->aidc->def,
22936 "Warning: No precomputed value available, the value "
22937 "was either invalid or something strange happened");
22938 sto->nbHistory--;
22939 goto deregister_check;
22940 } else {
22941 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22942 xmlSchemaPSVIIDCKeyPtr *keySeq;
22943 int pos, idx;
22946 * The key will be anchored on the matcher's list of
22947 * key-sequences. The position in this list is determined
22948 * by the target node's depth relative to the matcher's
22949 * depth of creation (i.e. the depth of the scope element).
22951 * Element Depth Pos List-entries
22952 * <scope> 0 NULL
22953 * <bar> 1 NULL
22954 * <target/> 2 2 target
22955 * <bar>
22956 * </scope>
22958 * The size of the list is only dependent on the depth of
22959 * the tree.
22960 * An entry will be NULLed in selector_leave, i.e. when
22961 * we hit the target's
22963 pos = sto->depth - matcher->depth;
22964 idx = sto->sel->index;
22967 * Create/grow the array of key-sequences.
22969 if (matcher->keySeqs == NULL) {
22970 if (pos > 9)
22971 matcher->sizeKeySeqs = pos * 2;
22972 else
22973 matcher->sizeKeySeqs = 10;
22974 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22975 xmlMalloc(matcher->sizeKeySeqs *
22976 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22977 if (matcher->keySeqs == NULL) {
22978 xmlSchemaVErrMemory(NULL,
22979 "allocating an array of key-sequences",
22980 NULL);
22981 return(-1);
22983 memset(matcher->keySeqs, 0,
22984 matcher->sizeKeySeqs *
22985 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22986 } else if (pos >= matcher->sizeKeySeqs) {
22987 int i = matcher->sizeKeySeqs;
22989 matcher->sizeKeySeqs *= 2;
22990 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22991 xmlRealloc(matcher->keySeqs,
22992 matcher->sizeKeySeqs *
22993 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22994 if (matcher->keySeqs == NULL) {
22995 xmlSchemaVErrMemory(NULL,
22996 "reallocating an array of key-sequences",
22997 NULL);
22998 return (-1);
23001 * The array needs to be NULLed.
23002 * TODO: Use memset?
23004 for (; i < matcher->sizeKeySeqs; i++)
23005 matcher->keySeqs[i] = NULL;
23009 * Get/create the key-sequence.
23011 keySeq = matcher->keySeqs[pos];
23012 if (keySeq == NULL) {
23013 goto create_sequence;
23014 } else if (keySeq[idx] != NULL) {
23015 xmlChar *str = NULL;
23017 * cvc-identity-constraint:
23018 * 3 For each node in the `target node set` all
23019 * of the {fields}, with that node as the context
23020 * node, evaluate to either an empty node-set or
23021 * a node-set with exactly one member, which must
23022 * have a simple type.
23024 * The key was already set; report an error.
23026 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23027 XML_SCHEMAV_CVC_IDC, NULL,
23028 WXS_BASIC_CAST matcher->aidc->def,
23029 "The XPath '%s' of a field of %s evaluates to a "
23030 "node-set with more than one member",
23031 sto->sel->xpath,
23032 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
23033 FREE_AND_NULL(str);
23034 sto->nbHistory--;
23035 goto deregister_check;
23036 } else
23037 goto create_key;
23039 create_sequence:
23041 * Create a key-sequence.
23043 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
23044 matcher->aidc->def->nbFields *
23045 sizeof(xmlSchemaPSVIIDCKeyPtr));
23046 if (keySeq == NULL) {
23047 xmlSchemaVErrMemory(NULL,
23048 "allocating an IDC key-sequence", NULL);
23049 return(-1);
23051 memset(keySeq, 0, matcher->aidc->def->nbFields *
23052 sizeof(xmlSchemaPSVIIDCKeyPtr));
23053 matcher->keySeqs[pos] = keySeq;
23054 create_key:
23056 * Create a key once per node only.
23058 if (key == NULL) {
23059 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
23060 sizeof(xmlSchemaPSVIIDCKey));
23061 if (key == NULL) {
23062 xmlSchemaVErrMemory(NULL,
23063 "allocating a IDC key", NULL);
23064 xmlFree(keySeq);
23065 matcher->keySeqs[pos] = NULL;
23066 return(-1);
23069 * Consume the compiled value.
23071 key->type = simpleType;
23072 key->val = vctxt->inode->val;
23073 vctxt->inode->val = NULL;
23075 * Store the key in a global list.
23077 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
23078 xmlSchemaIDCFreeKey(key);
23079 return (-1);
23082 keySeq[idx] = key;
23084 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
23086 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
23087 /* xmlSchemaPSVIIDCBindingPtr bind; */
23088 xmlSchemaPSVIIDCNodePtr ntItem;
23089 xmlSchemaIDCMatcherPtr matcher;
23090 xmlSchemaIDCPtr idc;
23091 xmlSchemaItemListPtr targets;
23092 int pos, i, j, nbKeys;
23094 * Here we have the following scenario:
23095 * An IDC 'selector' state object resolved to a target node,
23096 * during the time this target node was in the
23097 * ancestor-or-self axis, the 'field' state object(s) looked
23098 * out for matching nodes to create a key-sequence for this
23099 * target node. Now we are back to this target node and need
23100 * to put the key-sequence, together with the target node
23101 * itself, into the node-table of the corresponding IDC
23102 * binding.
23104 matcher = sto->matcher;
23105 idc = matcher->aidc->def;
23106 nbKeys = idc->nbFields;
23107 pos = depth - matcher->depth;
23109 * Check if the matcher has any key-sequences at all, plus
23110 * if it has a key-sequence for the current target node.
23112 if ((matcher->keySeqs == NULL) ||
23113 (matcher->sizeKeySeqs <= pos)) {
23114 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23115 goto selector_key_error;
23116 else
23117 goto selector_leave;
23120 keySeq = &(matcher->keySeqs[pos]);
23121 if (*keySeq == NULL) {
23122 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23123 goto selector_key_error;
23124 else
23125 goto selector_leave;
23128 for (i = 0; i < nbKeys; i++) {
23129 if ((*keySeq)[i] == NULL) {
23131 * Not qualified, if not all fields did resolve.
23133 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
23135 * All fields of a "key" IDC must resolve.
23137 goto selector_key_error;
23139 goto selector_leave;
23143 * All fields did resolve.
23147 * 4.1 If the {identity-constraint category} is unique(/key),
23148 * then no two members of the `qualified node set` have
23149 * `key-sequences` whose members are pairwise equal, as
23150 * defined by Equal in [XML Schemas: Datatypes].
23152 * Get the IDC binding from the matcher and check for
23153 * duplicate key-sequences.
23155 #if 0
23156 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23157 #endif
23158 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
23159 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
23160 (targets->nbItems != 0)) {
23161 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
23162 xmlIDCHashEntryPtr e;
23164 res = 0;
23166 if (!matcher->htab)
23167 e = NULL;
23168 else {
23169 xmlChar *value = NULL;
23170 xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
23171 e = xmlHashLookup(matcher->htab, value);
23172 FREE_AND_NULL(value);
23176 * Compare the key-sequences, key by key.
23178 for (;e; e = e->next) {
23179 bkeySeq =
23180 ((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
23181 for (j = 0; j < nbKeys; j++) {
23182 ckey = (*keySeq)[j];
23183 bkey = bkeySeq[j];
23184 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23185 if (res == -1) {
23186 return (-1);
23187 } else if (res == 0) {
23189 * One of the keys differs, so the key-sequence
23190 * won't be equal; get out.
23192 break;
23195 if (res == 1) {
23197 * Duplicate key-sequence found.
23199 break;
23202 if (e) {
23203 xmlChar *str = NULL, *strB = NULL;
23205 * TODO: Try to report the key-sequence.
23207 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23208 XML_SCHEMAV_CVC_IDC, NULL,
23209 WXS_BASIC_CAST idc,
23210 "Duplicate key-sequence %s in %s",
23211 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23212 (*keySeq), nbKeys),
23213 xmlSchemaGetIDCDesignation(&strB, idc));
23214 FREE_AND_NULL(str);
23215 FREE_AND_NULL(strB);
23216 goto selector_leave;
23220 * Add a node-table item to the IDC binding.
23222 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23223 sizeof(xmlSchemaPSVIIDCNode));
23224 if (ntItem == NULL) {
23225 xmlSchemaVErrMemory(NULL,
23226 "allocating an IDC node-table item", NULL);
23227 xmlFree(*keySeq);
23228 *keySeq = NULL;
23229 return(-1);
23231 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23234 * Store the node-table item in a global list.
23236 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23237 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23238 xmlFree(ntItem);
23239 xmlFree(*keySeq);
23240 *keySeq = NULL;
23241 return (-1);
23243 ntItem->nodeQNameID = -1;
23244 } else {
23246 * Save a cached QName for this node on the IDC node, to be
23247 * able to report it, even if the node is not saved.
23249 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23250 vctxt->inode->localName, vctxt->inode->nsName);
23251 if (ntItem->nodeQNameID == -1) {
23252 xmlFree(ntItem);
23253 xmlFree(*keySeq);
23254 *keySeq = NULL;
23255 return (-1);
23259 * Init the node-table item: Save the node, position and
23260 * consume the key-sequence.
23262 ntItem->node = vctxt->node;
23263 ntItem->nodeLine = vctxt->inode->nodeLine;
23264 ntItem->keys = *keySeq;
23265 *keySeq = NULL;
23266 #if 0
23267 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23268 #endif
23269 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23270 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23272 * Free the item, since keyref items won't be
23273 * put on a global list.
23275 xmlFree(ntItem->keys);
23276 xmlFree(ntItem);
23278 return (-1);
23280 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23281 xmlChar *value = NULL;
23282 xmlIDCHashEntryPtr r, e;
23283 if (!matcher->htab)
23284 matcher->htab = xmlHashCreate(4);
23285 xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
23286 e = xmlMalloc(sizeof *e);
23287 e->index = targets->nbItems - 1;
23288 r = xmlHashLookup(matcher->htab, value);
23289 if (r) {
23290 e->next = r->next;
23291 r->next = e;
23292 } else {
23293 e->next = NULL;
23294 xmlHashAddEntry(matcher->htab, value, e);
23296 FREE_AND_NULL(value);
23299 goto selector_leave;
23300 selector_key_error:
23302 xmlChar *str = NULL;
23304 * 4.2.1 (KEY) The `target node set` and the
23305 * `qualified node set` are equal, that is, every
23306 * member of the `target node set` is also a member
23307 * of the `qualified node set` and vice versa.
23309 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23310 XML_SCHEMAV_CVC_IDC, NULL,
23311 WXS_BASIC_CAST idc,
23312 "Not all fields of %s evaluate to a node",
23313 xmlSchemaGetIDCDesignation(&str, idc), NULL);
23314 FREE_AND_NULL(str);
23316 selector_leave:
23318 * Free the key-sequence if not added to the IDC table.
23320 if ((keySeq != NULL) && (*keySeq != NULL)) {
23321 xmlFree(*keySeq);
23322 *keySeq = NULL;
23324 } /* if selector */
23326 sto->nbHistory--;
23328 deregister_check:
23330 * Deregister state objects if they reach the depth of creation.
23332 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23333 #ifdef DEBUG_IDC
23334 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
23335 sto->sel->xpath);
23336 #endif
23337 if (vctxt->xpathStates != sto) {
23338 VERROR_INT("xmlSchemaXPathProcessHistory",
23339 "The state object to be removed is not the first "
23340 "in the list");
23342 nextsto = sto->next;
23344 * Unlink from the list of active XPath state objects.
23346 vctxt->xpathStates = sto->next;
23347 sto->next = vctxt->xpathStatePool;
23349 * Link it to the pool of reusable state objects.
23351 vctxt->xpathStatePool = sto;
23352 sto = nextsto;
23353 } else
23354 sto = sto->next;
23355 } /* while (sto != NULL) */
23356 return (0);
23360 * xmlSchemaIDCRegisterMatchers:
23361 * @vctxt: the WXS validation context
23362 * @elemDecl: the element declaration
23364 * Creates helper objects to evaluate IDC selectors/fields
23365 * successively.
23367 * Returns 0 if OK and -1 on internal errors.
23369 static int
23370 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23371 xmlSchemaElementPtr elemDecl)
23373 xmlSchemaIDCMatcherPtr matcher, last = NULL;
23374 xmlSchemaIDCPtr idc, refIdc;
23375 xmlSchemaIDCAugPtr aidc;
23377 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23378 if (idc == NULL)
23379 return (0);
23381 #ifdef DEBUG_IDC
23383 xmlChar *str = NULL;
23384 xmlGenericError(xmlGenericErrorContext,
23385 "IDC: REGISTER on %s, depth %d\n",
23386 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23387 vctxt->inode->localName), vctxt->depth);
23388 FREE_AND_NULL(str)
23390 #endif
23391 if (vctxt->inode->idcMatchers != NULL) {
23392 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23393 "The chain of IDC matchers is expected to be empty");
23394 return (-1);
23396 do {
23397 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23399 * Since IDCs bubbles are expensive we need to know the
23400 * depth at which the bubbles should stop; this will be
23401 * the depth of the top-most keyref IDC. If no keyref
23402 * references a key/unique IDC, the keyrefDepth will
23403 * be -1, indicating that no bubbles are needed.
23405 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23406 if (refIdc != NULL) {
23408 * Remember that we have keyrefs on this node.
23410 vctxt->inode->hasKeyrefs = 1;
23412 * Lookup the referenced augmented IDC info.
23414 aidc = vctxt->aidcs;
23415 while (aidc != NULL) {
23416 if (aidc->def == refIdc)
23417 break;
23418 aidc = aidc->next;
23420 if (aidc == NULL) {
23421 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23422 "Could not find an augmented IDC item for an IDC "
23423 "definition");
23424 return (-1);
23426 if ((aidc->keyrefDepth == -1) ||
23427 (vctxt->depth < aidc->keyrefDepth))
23428 aidc->keyrefDepth = vctxt->depth;
23432 * Lookup the augmented IDC item for the IDC definition.
23434 aidc = vctxt->aidcs;
23435 while (aidc != NULL) {
23436 if (aidc->def == idc)
23437 break;
23438 aidc = aidc->next;
23440 if (aidc == NULL) {
23441 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23442 "Could not find an augmented IDC item for an IDC definition");
23443 return (-1);
23446 * Create an IDC matcher for every IDC definition.
23448 if (vctxt->idcMatcherCache != NULL) {
23450 * Reuse a cached matcher.
23452 matcher = vctxt->idcMatcherCache;
23453 vctxt->idcMatcherCache = matcher->nextCached;
23454 matcher->nextCached = NULL;
23455 } else {
23456 matcher = (xmlSchemaIDCMatcherPtr)
23457 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23458 if (matcher == NULL) {
23459 xmlSchemaVErrMemory(vctxt,
23460 "allocating an IDC matcher", NULL);
23461 return (-1);
23463 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23465 if (last == NULL)
23466 vctxt->inode->idcMatchers = matcher;
23467 else
23468 last->next = matcher;
23469 last = matcher;
23471 matcher->type = IDC_MATCHER;
23472 matcher->depth = vctxt->depth;
23473 matcher->aidc = aidc;
23474 matcher->idcType = aidc->def->type;
23475 #ifdef DEBUG_IDC
23476 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
23477 #endif
23479 * Init the automaton state object.
23481 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23482 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23483 return (-1);
23485 idc = idc->next;
23486 } while (idc != NULL);
23487 return (0);
23490 static int
23491 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23492 xmlSchemaNodeInfoPtr ielem)
23494 xmlSchemaPSVIIDCBindingPtr bind;
23495 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23496 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23497 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23499 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23500 /* vctxt->createIDCNodeTables */
23501 while (matcher != NULL) {
23503 * Skip keyref IDCs and empty IDC target-lists.
23505 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23506 WXS_ILIST_IS_EMPTY(matcher->targets))
23508 matcher = matcher->next;
23509 continue;
23512 * If we _want_ the IDC node-table to be created in any case
23513 * then do so. Otherwise create them only if keyrefs need them.
23515 if ((! vctxt->createIDCNodeTables) &&
23516 ((matcher->aidc->keyrefDepth == -1) ||
23517 (matcher->aidc->keyrefDepth > vctxt->depth)))
23519 matcher = matcher->next;
23520 continue;
23523 * Get/create the IDC binding on this element for the IDC definition.
23525 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23526 if (bind == NULL)
23527 goto internal_error;
23529 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23530 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23531 nbDupls = bind->dupls->nbItems;
23532 } else {
23533 dupls = NULL;
23534 nbDupls = 0;
23536 if (bind->nodeTable != NULL) {
23537 nbNodeTable = bind->nbNodes;
23538 } else {
23539 nbNodeTable = 0;
23542 if ((nbNodeTable == 0) && (nbDupls == 0)) {
23544 * Transfer all IDC target-nodes to the IDC node-table.
23546 bind->nodeTable =
23547 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23548 bind->sizeNodes = matcher->targets->sizeItems;
23549 bind->nbNodes = matcher->targets->nbItems;
23551 matcher->targets->items = NULL;
23552 matcher->targets->sizeItems = 0;
23553 matcher->targets->nbItems = 0;
23554 if (matcher->htab) {
23555 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
23556 matcher->htab = NULL;
23558 } else {
23560 * Compare the key-sequences and add to the IDC node-table.
23562 nbTargets = matcher->targets->nbItems;
23563 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23564 nbFields = matcher->aidc->def->nbFields;
23565 i = 0;
23566 do {
23567 keys = targets[i]->keys;
23568 if (nbDupls) {
23570 * Search in already found duplicates first.
23572 j = 0;
23573 do {
23574 if (nbFields == 1) {
23575 res = xmlSchemaAreValuesEqual(keys[0]->val,
23576 dupls[j]->keys[0]->val);
23577 if (res == -1)
23578 goto internal_error;
23579 if (res == 1) {
23581 * Equal key-sequence.
23583 goto next_target;
23585 } else {
23586 res = 0;
23587 ntkeys = dupls[j]->keys;
23588 for (k = 0; k < nbFields; k++) {
23589 res = xmlSchemaAreValuesEqual(keys[k]->val,
23590 ntkeys[k]->val);
23591 if (res == -1)
23592 goto internal_error;
23593 if (res == 0) {
23595 * One of the keys differs.
23597 break;
23600 if (res == 1) {
23602 * Equal key-sequence found.
23604 goto next_target;
23607 j++;
23608 } while (j < nbDupls);
23610 if (nbNodeTable) {
23611 j = 0;
23612 do {
23613 if (nbFields == 1) {
23614 res = xmlSchemaAreValuesEqual(keys[0]->val,
23615 bind->nodeTable[j]->keys[0]->val);
23616 if (res == -1)
23617 goto internal_error;
23618 if (res == 0) {
23620 * The key-sequence differs.
23622 goto next_node_table_entry;
23624 } else {
23625 res = 0;
23626 ntkeys = bind->nodeTable[j]->keys;
23627 for (k = 0; k < nbFields; k++) {
23628 res = xmlSchemaAreValuesEqual(keys[k]->val,
23629 ntkeys[k]->val);
23630 if (res == -1)
23631 goto internal_error;
23632 if (res == 0) {
23634 * One of the keys differs.
23636 goto next_node_table_entry;
23641 * Add the duplicate to the list of duplicates.
23643 if (bind->dupls == NULL) {
23644 bind->dupls = xmlSchemaItemListCreate();
23645 if (bind->dupls == NULL)
23646 goto internal_error;
23648 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23649 goto internal_error;
23651 * Remove the duplicate entry from the IDC node-table.
23653 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23654 bind->nbNodes--;
23656 goto next_target;
23658 next_node_table_entry:
23659 j++;
23660 } while (j < nbNodeTable);
23663 * If everything is fine, then add the IDC target-node to
23664 * the IDC node-table.
23666 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23667 goto internal_error;
23669 next_target:
23670 i++;
23671 } while (i < nbTargets);
23673 matcher = matcher->next;
23675 return(0);
23677 internal_error:
23678 return(-1);
23682 * xmlSchemaBubbleIDCNodeTables:
23683 * @depth: the current tree depth
23685 * Merges IDC bindings of an element at @depth into the corresponding IDC
23686 * bindings of its parent element. If a duplicate note-table entry is found,
23687 * both, the parent node-table entry and child entry are discarded from the
23688 * node-table of the parent.
23690 * Returns 0 if OK and -1 on internal errors.
23692 static int
23693 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23695 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23696 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23697 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23698 xmlSchemaIDCAugPtr aidc;
23699 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23701 bind = vctxt->inode->idcTable;
23702 if (bind == NULL) {
23703 /* Fine, no table, no bubbles. */
23704 return (0);
23707 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23709 * Walk all bindings; create new or add to existing bindings.
23710 * Remove duplicate key-sequences.
23712 while (bind != NULL) {
23714 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23715 goto next_binding;
23717 * Check if the key/unique IDC table needs to be bubbled.
23719 if (! vctxt->createIDCNodeTables) {
23720 aidc = vctxt->aidcs;
23721 do {
23722 if (aidc->def == bind->definition) {
23723 if ((aidc->keyrefDepth == -1) ||
23724 (aidc->keyrefDepth >= vctxt->depth)) {
23725 goto next_binding;
23727 break;
23729 aidc = aidc->next;
23730 } while (aidc != NULL);
23733 if (parTable != NULL)
23734 parBind = *parTable;
23736 * Search a matching parent binding for the
23737 * IDC definition.
23739 while (parBind != NULL) {
23740 if (parBind->definition == bind->definition)
23741 break;
23742 parBind = parBind->next;
23745 if (parBind != NULL) {
23747 * Compare every node-table entry of the child node,
23748 * i.e. the key-sequence within, ...
23750 oldNum = parBind->nbNodes; /* Skip newly added items. */
23752 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23753 oldDupls = parBind->dupls->nbItems;
23754 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23755 } else {
23756 dupls = NULL;
23757 oldDupls = 0;
23760 parNodes = parBind->nodeTable;
23761 nbFields = bind->definition->nbFields;
23763 for (i = 0; i < bind->nbNodes; i++) {
23764 node = bind->nodeTable[i];
23765 if (node == NULL)
23766 continue;
23768 * ...with every key-sequence of the parent node, already
23769 * evaluated to be a duplicate key-sequence.
23771 if (oldDupls) {
23772 j = 0;
23773 while (j < oldDupls) {
23774 if (nbFields == 1) {
23775 ret = xmlSchemaAreValuesEqual(
23776 node->keys[0]->val,
23777 dupls[j]->keys[0]->val);
23778 if (ret == -1)
23779 goto internal_error;
23780 if (ret == 0) {
23781 j++;
23782 continue;
23784 } else {
23785 parNode = dupls[j];
23786 for (k = 0; k < nbFields; k++) {
23787 ret = xmlSchemaAreValuesEqual(
23788 node->keys[k]->val,
23789 parNode->keys[k]->val);
23790 if (ret == -1)
23791 goto internal_error;
23792 if (ret == 0)
23793 break;
23796 if (ret == 1)
23797 /* Duplicate found. */
23798 break;
23799 j++;
23801 if (j != oldDupls) {
23802 /* Duplicate found. Skip this entry. */
23803 continue;
23807 * ... and with every key-sequence of the parent node.
23809 if (oldNum) {
23810 j = 0;
23811 while (j < oldNum) {
23812 parNode = parNodes[j];
23813 if (nbFields == 1) {
23814 ret = xmlSchemaAreValuesEqual(
23815 node->keys[0]->val,
23816 parNode->keys[0]->val);
23817 if (ret == -1)
23818 goto internal_error;
23819 if (ret == 0) {
23820 j++;
23821 continue;
23823 } else {
23824 for (k = 0; k < nbFields; k++) {
23825 ret = xmlSchemaAreValuesEqual(
23826 node->keys[k]->val,
23827 parNode->keys[k]->val);
23828 if (ret == -1)
23829 goto internal_error;
23830 if (ret == 0)
23831 break;
23834 if (ret == 1)
23835 /* Duplicate found. */
23836 break;
23837 j++;
23839 if (j != oldNum) {
23841 * Handle duplicates. Move the duplicate in
23842 * the parent's node-table to the list of
23843 * duplicates.
23845 oldNum--;
23846 parBind->nbNodes--;
23848 * Move last old item to pos of duplicate.
23850 parNodes[j] = parNodes[oldNum];
23852 if (parBind->nbNodes != oldNum) {
23854 * If new items exist, move last new item to
23855 * last of old items.
23857 parNodes[oldNum] =
23858 parNodes[parBind->nbNodes];
23860 if (parBind->dupls == NULL) {
23861 parBind->dupls = xmlSchemaItemListCreate();
23862 if (parBind->dupls == NULL)
23863 goto internal_error;
23865 xmlSchemaItemListAdd(parBind->dupls, parNode);
23866 } else {
23868 * Add the node-table entry (node and key-sequence) of
23869 * the child node to the node table of the parent node.
23871 if (parBind->nodeTable == NULL) {
23872 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23873 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23874 if (parBind->nodeTable == NULL) {
23875 xmlSchemaVErrMemory(NULL,
23876 "allocating IDC list of node-table items", NULL);
23877 goto internal_error;
23879 parBind->sizeNodes = 1;
23880 } else if (parBind->nbNodes >= parBind->sizeNodes) {
23881 parBind->sizeNodes *= 2;
23882 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23883 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23884 sizeof(xmlSchemaPSVIIDCNodePtr));
23885 if (parBind->nodeTable == NULL) {
23886 xmlSchemaVErrMemory(NULL,
23887 "re-allocating IDC list of node-table items", NULL);
23888 goto internal_error;
23891 parNodes = parBind->nodeTable;
23893 * Append the new node-table entry to the 'new node-table
23894 * entries' section.
23896 parNodes[parBind->nbNodes++] = node;
23902 } else {
23904 * No binding for the IDC was found: create a new one and
23905 * copy all node-tables.
23907 parBind = xmlSchemaIDCNewBinding(bind->definition);
23908 if (parBind == NULL)
23909 goto internal_error;
23912 * TODO: Hmm, how to optimize the initial number of
23913 * allocated entries?
23915 if (bind->nbNodes != 0) {
23917 * Add all IDC node-table entries.
23919 if (! vctxt->psviExposeIDCNodeTables) {
23921 * Just move the entries.
23922 * NOTE: this is quite save here, since
23923 * all the keyref lookups have already been
23924 * performed.
23926 parBind->nodeTable = bind->nodeTable;
23927 bind->nodeTable = NULL;
23928 parBind->sizeNodes = bind->sizeNodes;
23929 bind->sizeNodes = 0;
23930 parBind->nbNodes = bind->nbNodes;
23931 bind->nbNodes = 0;
23932 } else {
23934 * Copy the entries.
23936 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23937 xmlMalloc(bind->nbNodes *
23938 sizeof(xmlSchemaPSVIIDCNodePtr));
23939 if (parBind->nodeTable == NULL) {
23940 xmlSchemaVErrMemory(NULL,
23941 "allocating an array of IDC node-table "
23942 "items", NULL);
23943 xmlSchemaIDCFreeBinding(parBind);
23944 goto internal_error;
23946 parBind->sizeNodes = bind->nbNodes;
23947 parBind->nbNodes = bind->nbNodes;
23948 memcpy(parBind->nodeTable, bind->nodeTable,
23949 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23952 if (bind->dupls) {
23954 * Move the duplicates.
23956 if (parBind->dupls != NULL)
23957 xmlSchemaItemListFree(parBind->dupls);
23958 parBind->dupls = bind->dupls;
23959 bind->dupls = NULL;
23961 if (parTable != NULL) {
23962 if (*parTable == NULL)
23963 *parTable = parBind;
23964 else {
23965 parBind->next = *parTable;
23966 *parTable = parBind;
23971 next_binding:
23972 bind = bind->next;
23974 return (0);
23976 internal_error:
23977 return(-1);
23981 * xmlSchemaCheckCVCIDCKeyRef:
23982 * @vctxt: the WXS validation context
23983 * @elemDecl: the element declaration
23985 * Check the cvc-idc-keyref constraints.
23987 static int
23988 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23990 xmlSchemaIDCMatcherPtr matcher;
23991 xmlSchemaPSVIIDCBindingPtr bind;
23993 matcher = vctxt->inode->idcMatchers;
23995 * Find a keyref.
23997 while (matcher != NULL) {
23998 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23999 matcher->targets &&
24000 matcher->targets->nbItems)
24002 int i, j, k, res, nbFields, hasDupls;
24003 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
24004 xmlSchemaPSVIIDCNodePtr refNode = NULL;
24005 xmlHashTablePtr table = NULL;
24007 nbFields = matcher->aidc->def->nbFields;
24010 * Find the IDC node-table for the referenced IDC key/unique.
24012 bind = vctxt->inode->idcTable;
24013 while (bind != NULL) {
24014 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
24015 bind->definition)
24016 break;
24017 bind = bind->next;
24019 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
24021 * Search for a matching key-sequences.
24023 if (bind) {
24024 table = xmlHashCreate(bind->nbNodes * 2);
24025 for (j = 0; j < bind->nbNodes; j++) {
24026 xmlChar *value;
24027 xmlIDCHashEntryPtr r, e;
24028 keys = bind->nodeTable[j]->keys;
24029 xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
24030 e = xmlMalloc(sizeof *e);
24031 e->index = j;
24032 r = xmlHashLookup(table, value);
24033 if (r) {
24034 e->next = r->next;
24035 r->next = e;
24036 } else {
24037 e->next = NULL;
24038 xmlHashAddEntry(table, value, e);
24040 FREE_AND_NULL(value);
24043 for (i = 0; i < matcher->targets->nbItems; i++) {
24044 res = 0;
24045 refNode = matcher->targets->items[i];
24046 if (bind != NULL) {
24047 xmlChar *value;
24048 xmlIDCHashEntryPtr e;
24049 refKeys = refNode->keys;
24050 xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
24051 e = xmlHashLookup(table, value);
24052 FREE_AND_NULL(value);
24053 res = 0;
24054 for (;e; e = e->next) {
24055 keys = bind->nodeTable[e->index]->keys;
24056 for (k = 0; k < nbFields; k++) {
24057 res = xmlSchemaAreValuesEqual(keys[k]->val,
24058 refKeys[k]->val);
24059 if (res == 0)
24060 break;
24061 else if (res == -1) {
24062 return (-1);
24065 if (res == 1) {
24067 * Match found.
24069 break;
24072 if ((res == 0) && hasDupls) {
24074 * Search in duplicates
24076 for (j = 0; j < bind->dupls->nbItems; j++) {
24077 keys = ((xmlSchemaPSVIIDCNodePtr)
24078 bind->dupls->items[j])->keys;
24079 for (k = 0; k < nbFields; k++) {
24080 res = xmlSchemaAreValuesEqual(keys[k]->val,
24081 refKeys[k]->val);
24082 if (res == 0)
24083 break;
24084 else if (res == -1) {
24085 return (-1);
24088 if (res == 1) {
24090 * Match in duplicates found.
24092 xmlChar *str = NULL, *strB = NULL;
24093 xmlSchemaKeyrefErr(vctxt,
24094 XML_SCHEMAV_CVC_IDC, refNode,
24095 (xmlSchemaTypePtr) matcher->aidc->def,
24096 "More than one match found for "
24097 "key-sequence %s of keyref '%s'",
24098 xmlSchemaFormatIDCKeySequence(vctxt, &str,
24099 refNode->keys, nbFields),
24100 xmlSchemaGetComponentQName(&strB,
24101 matcher->aidc->def));
24102 FREE_AND_NULL(str);
24103 FREE_AND_NULL(strB);
24104 break;
24110 if (res == 0) {
24111 xmlChar *str = NULL, *strB = NULL;
24112 xmlSchemaKeyrefErr(vctxt,
24113 XML_SCHEMAV_CVC_IDC, refNode,
24114 (xmlSchemaTypePtr) matcher->aidc->def,
24115 "No match found for key-sequence %s of keyref '%s'",
24116 xmlSchemaFormatIDCKeySequence(vctxt, &str,
24117 refNode->keys, nbFields),
24118 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
24119 FREE_AND_NULL(str);
24120 FREE_AND_NULL(strB);
24123 if (table) {
24124 xmlHashFree(table, xmlFreeIDCHashEntry);
24127 matcher = matcher->next;
24129 /* TODO: Return an error if any error encountered. */
24130 return (0);
24133 /************************************************************************
24135 * XML Reader validation code *
24137 ************************************************************************/
24139 static xmlSchemaAttrInfoPtr
24140 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
24142 xmlSchemaAttrInfoPtr iattr;
24144 * Grow/create list of attribute infos.
24146 if (vctxt->attrInfos == NULL) {
24147 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24148 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
24149 vctxt->sizeAttrInfos = 1;
24150 if (vctxt->attrInfos == NULL) {
24151 xmlSchemaVErrMemory(vctxt,
24152 "allocating attribute info list", NULL);
24153 return (NULL);
24155 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
24156 vctxt->sizeAttrInfos++;
24157 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24158 xmlRealloc(vctxt->attrInfos,
24159 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
24160 if (vctxt->attrInfos == NULL) {
24161 xmlSchemaVErrMemory(vctxt,
24162 "re-allocating attribute info list", NULL);
24163 return (NULL);
24165 } else {
24166 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
24167 if (iattr->localName != NULL) {
24168 VERROR_INT("xmlSchemaGetFreshAttrInfo",
24169 "attr info not cleared");
24170 return (NULL);
24172 iattr->nodeType = XML_ATTRIBUTE_NODE;
24173 return (iattr);
24176 * Create an attribute info.
24178 iattr = (xmlSchemaAttrInfoPtr)
24179 xmlMalloc(sizeof(xmlSchemaAttrInfo));
24180 if (iattr == NULL) {
24181 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
24182 return (NULL);
24184 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
24185 iattr->nodeType = XML_ATTRIBUTE_NODE;
24186 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
24188 return (iattr);
24191 static int
24192 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
24193 xmlNodePtr attrNode,
24194 int nodeLine,
24195 const xmlChar *localName,
24196 const xmlChar *nsName,
24197 int ownedNames,
24198 xmlChar *value,
24199 int ownedValue)
24201 xmlSchemaAttrInfoPtr attr;
24203 attr = xmlSchemaGetFreshAttrInfo(vctxt);
24204 if (attr == NULL) {
24205 VERROR_INT("xmlSchemaPushAttribute",
24206 "calling xmlSchemaGetFreshAttrInfo()");
24207 return (-1);
24209 attr->node = attrNode;
24210 attr->nodeLine = nodeLine;
24211 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
24212 attr->localName = localName;
24213 attr->nsName = nsName;
24214 if (ownedNames)
24215 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
24217 * Evaluate if it's an XSI attribute.
24219 if (nsName != NULL) {
24220 if (xmlStrEqual(localName, BAD_CAST "nil")) {
24221 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24222 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
24224 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
24225 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24226 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
24228 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
24229 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24230 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
24232 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
24233 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24234 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24236 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24237 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24240 attr->value = value;
24241 if (ownedValue)
24242 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24243 if (attr->metaType != 0)
24244 attr->state = XML_SCHEMAS_ATTR_META;
24245 return (0);
24249 * xmlSchemaClearElemInfo:
24250 * @vctxt: the WXS validation context
24251 * @ielem: the element information item
24253 static void
24254 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24255 xmlSchemaNodeInfoPtr ielem)
24257 ielem->hasKeyrefs = 0;
24258 ielem->appliedXPath = 0;
24259 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24260 FREE_AND_NULL(ielem->localName);
24261 FREE_AND_NULL(ielem->nsName);
24262 } else {
24263 ielem->localName = NULL;
24264 ielem->nsName = NULL;
24266 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24267 FREE_AND_NULL(ielem->value);
24268 } else {
24269 ielem->value = NULL;
24271 if (ielem->val != NULL) {
24273 * PSVI TODO: Be careful not to free it when the value is
24274 * exposed via PSVI.
24276 xmlSchemaFreeValue(ielem->val);
24277 ielem->val = NULL;
24279 if (ielem->idcMatchers != NULL) {
24281 * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24282 * Does it work?
24284 xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24285 #if 0
24286 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24287 #endif
24288 ielem->idcMatchers = NULL;
24290 if (ielem->idcTable != NULL) {
24292 * OPTIMIZE TODO: Use a pool of IDC tables??.
24294 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24295 ielem->idcTable = NULL;
24297 if (ielem->regexCtxt != NULL) {
24298 xmlRegFreeExecCtxt(ielem->regexCtxt);
24299 ielem->regexCtxt = NULL;
24301 if (ielem->nsBindings != NULL) {
24302 xmlFree((xmlChar **)ielem->nsBindings);
24303 ielem->nsBindings = NULL;
24304 ielem->nbNsBindings = 0;
24305 ielem->sizeNsBindings = 0;
24310 * xmlSchemaGetFreshElemInfo:
24311 * @vctxt: the schema validation context
24313 * Creates/reuses and initializes the element info item for
24314 * the current tree depth.
24316 * Returns the element info item or NULL on API or internal errors.
24318 static xmlSchemaNodeInfoPtr
24319 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24321 xmlSchemaNodeInfoPtr info = NULL;
24323 if (vctxt->depth > vctxt->sizeElemInfos) {
24324 VERROR_INT("xmlSchemaGetFreshElemInfo",
24325 "inconsistent depth encountered");
24326 return (NULL);
24328 if (vctxt->elemInfos == NULL) {
24329 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24330 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24331 if (vctxt->elemInfos == NULL) {
24332 xmlSchemaVErrMemory(vctxt,
24333 "allocating the element info array", NULL);
24334 return (NULL);
24336 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24337 vctxt->sizeElemInfos = 10;
24338 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24339 int i = vctxt->sizeElemInfos;
24341 vctxt->sizeElemInfos *= 2;
24342 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24343 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24344 sizeof(xmlSchemaNodeInfoPtr));
24345 if (vctxt->elemInfos == NULL) {
24346 xmlSchemaVErrMemory(vctxt,
24347 "re-allocating the element info array", NULL);
24348 return (NULL);
24351 * We need the new memory to be NULLed.
24352 * TODO: Use memset instead?
24354 for (; i < vctxt->sizeElemInfos; i++)
24355 vctxt->elemInfos[i] = NULL;
24356 } else
24357 info = vctxt->elemInfos[vctxt->depth];
24359 if (info == NULL) {
24360 info = (xmlSchemaNodeInfoPtr)
24361 xmlMalloc(sizeof(xmlSchemaNodeInfo));
24362 if (info == NULL) {
24363 xmlSchemaVErrMemory(vctxt,
24364 "allocating an element info", NULL);
24365 return (NULL);
24367 vctxt->elemInfos[vctxt->depth] = info;
24368 } else {
24369 if (info->localName != NULL) {
24370 VERROR_INT("xmlSchemaGetFreshElemInfo",
24371 "elem info has not been cleared");
24372 return (NULL);
24375 memset(info, 0, sizeof(xmlSchemaNodeInfo));
24376 info->nodeType = XML_ELEMENT_NODE;
24377 info->depth = vctxt->depth;
24379 return (info);
24382 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24383 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24384 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24386 static int
24387 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24388 xmlNodePtr node,
24389 xmlSchemaTypePtr type,
24390 xmlSchemaValType valType,
24391 const xmlChar * value,
24392 xmlSchemaValPtr val,
24393 unsigned long length,
24394 int fireErrors)
24396 int ret, error = 0, found;
24398 xmlSchemaTypePtr tmpType;
24399 xmlSchemaFacetLinkPtr facetLink;
24400 xmlSchemaFacetPtr facet;
24401 unsigned long len = 0;
24402 xmlSchemaWhitespaceValueType ws;
24405 * In Libxml2, derived built-in types have currently no explicit facets.
24407 if (type->type == XML_SCHEMA_TYPE_BASIC)
24408 return (0);
24411 * NOTE: Do not jump away, if the facetSet of the given type is
24412 * empty: until now, "pattern" and "enumeration" facets of the
24413 * *base types* need to be checked as well.
24415 if (type->facetSet == NULL)
24416 goto pattern_and_enum;
24418 if (! WXS_IS_ATOMIC(type)) {
24419 if (WXS_IS_LIST(type))
24420 goto WXS_IS_LIST;
24421 else
24422 goto pattern_and_enum;
24426 * Whitespace handling is only of importance for string-based
24427 * types.
24429 tmpType = xmlSchemaGetPrimitiveType(type);
24430 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24431 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24432 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24433 } else
24434 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24437 * If the value was not computed (for string or
24438 * anySimpleType based types), then use the provided
24439 * type.
24441 if (val != NULL)
24442 valType = xmlSchemaGetValType(val);
24444 ret = 0;
24445 for (facetLink = type->facetSet; facetLink != NULL;
24446 facetLink = facetLink->next) {
24448 * Skip the pattern "whiteSpace": it is used to
24449 * format the character content beforehand.
24451 switch (facetLink->facet->type) {
24452 case XML_SCHEMA_FACET_WHITESPACE:
24453 case XML_SCHEMA_FACET_PATTERN:
24454 case XML_SCHEMA_FACET_ENUMERATION:
24455 continue;
24456 case XML_SCHEMA_FACET_LENGTH:
24457 case XML_SCHEMA_FACET_MINLENGTH:
24458 case XML_SCHEMA_FACET_MAXLENGTH:
24459 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24460 valType, value, val, &len, ws);
24461 break;
24462 default:
24463 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24464 valType, value, val, ws);
24465 break;
24467 if (ret < 0) {
24468 AERROR_INT("xmlSchemaValidateFacets",
24469 "validating against a atomic type facet");
24470 return (-1);
24471 } else if (ret > 0) {
24472 if (fireErrors)
24473 xmlSchemaFacetErr(actxt, ret, node,
24474 value, len, type, facetLink->facet, NULL, NULL, NULL);
24475 else
24476 return (ret);
24477 if (error == 0)
24478 error = ret;
24480 ret = 0;
24483 WXS_IS_LIST:
24484 if (! WXS_IS_LIST(type))
24485 goto pattern_and_enum;
24487 * "length", "minLength" and "maxLength" of list types.
24489 ret = 0;
24490 for (facetLink = type->facetSet; facetLink != NULL;
24491 facetLink = facetLink->next) {
24493 switch (facetLink->facet->type) {
24494 case XML_SCHEMA_FACET_LENGTH:
24495 case XML_SCHEMA_FACET_MINLENGTH:
24496 case XML_SCHEMA_FACET_MAXLENGTH:
24497 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24498 value, length, NULL);
24499 break;
24500 default:
24501 continue;
24503 if (ret < 0) {
24504 AERROR_INT("xmlSchemaValidateFacets",
24505 "validating against a list type facet");
24506 return (-1);
24507 } else if (ret > 0) {
24508 if (fireErrors)
24509 xmlSchemaFacetErr(actxt, ret, node,
24510 value, length, type, facetLink->facet, NULL, NULL, NULL);
24511 else
24512 return (ret);
24513 if (error == 0)
24514 error = ret;
24516 ret = 0;
24519 pattern_and_enum:
24520 found = 0;
24522 * Process enumerations. Facet values are in the value space
24523 * of the defining type's base type. This seems to be a bug in the
24524 * XML Schema 1.0 spec. Use the whitespace type of the base type.
24525 * Only the first set of enumerations in the ancestor-or-self axis
24526 * is used for validation.
24528 ret = 0;
24529 tmpType = type;
24530 do {
24531 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24532 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24533 continue;
24534 found = 1;
24535 ret = xmlSchemaAreValuesEqual(facet->val, val);
24536 if (ret == 1)
24537 break;
24538 else if (ret < 0) {
24539 AERROR_INT("xmlSchemaValidateFacets",
24540 "validating against an enumeration facet");
24541 return (-1);
24544 if (ret != 0)
24545 break;
24547 * Break on the first set of enumerations. Any additional
24548 * enumerations which might be existent on the ancestors
24549 * of the current type are restricted by this set; thus
24550 * *must* *not* be taken into account.
24552 if (found)
24553 break;
24554 tmpType = tmpType->baseType;
24555 } while ((tmpType != NULL) &&
24556 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24557 if (found && (ret == 0)) {
24558 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24559 if (fireErrors) {
24560 xmlSchemaFacetErr(actxt, ret, node,
24561 value, 0, type, NULL, NULL, NULL, NULL);
24562 } else
24563 return (ret);
24564 if (error == 0)
24565 error = ret;
24569 * Process patters. Pattern facets are ORed at type level
24570 * and ANDed if derived. Walk the base type axis.
24572 tmpType = type;
24573 facet = NULL;
24574 do {
24575 found = 0;
24576 for (facetLink = tmpType->facetSet; facetLink != NULL;
24577 facetLink = facetLink->next) {
24578 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24579 continue;
24580 found = 1;
24582 * NOTE that for patterns, @value needs to be the
24583 * normalized value.
24585 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24586 if (ret == 1)
24587 break;
24588 else if (ret < 0) {
24589 AERROR_INT("xmlSchemaValidateFacets",
24590 "validating against a pattern facet");
24591 return (-1);
24592 } else {
24594 * Save the last non-validating facet.
24596 facet = facetLink->facet;
24599 if (found && (ret != 1)) {
24600 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24601 if (fireErrors) {
24602 xmlSchemaFacetErr(actxt, ret, node,
24603 value, 0, type, facet, NULL, NULL, NULL);
24604 } else
24605 return (ret);
24606 if (error == 0)
24607 error = ret;
24608 break;
24610 tmpType = tmpType->baseType;
24611 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24613 return (error);
24616 static xmlChar *
24617 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24618 const xmlChar *value)
24620 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24621 case XML_SCHEMA_WHITESPACE_COLLAPSE:
24622 return (xmlSchemaCollapseString(value));
24623 case XML_SCHEMA_WHITESPACE_REPLACE:
24624 return (xmlSchemaWhiteSpaceReplace(value));
24625 default:
24626 return (NULL);
24630 static int
24631 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24632 const xmlChar *value,
24633 xmlSchemaValPtr *val,
24634 int valNeeded)
24636 int ret;
24637 xmlChar *stripped;
24638 const xmlChar *nsName;
24639 xmlChar *local, *prefix = NULL;
24641 ret = xmlValidateQName(value, 1);
24642 if (ret != 0) {
24643 if (ret == -1) {
24644 VERROR_INT("xmlSchemaValidateQName",
24645 "calling xmlValidateQName()");
24646 return (-1);
24648 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24651 * NOTE: xmlSplitQName2 will always return a duplicated
24652 * strings.
24654 /* TODO: Export and use xmlSchemaStrip instead */
24655 stripped = xmlSchemaCollapseString(value);
24656 local = xmlSplitQName2(stripped ? stripped : value, &prefix);
24657 xmlFree(stripped);
24658 if (local == NULL)
24659 local = xmlStrdup(value);
24661 * OPTIMIZE TODO: Use flags for:
24662 * - is there any namespace binding?
24663 * - is there a default namespace?
24665 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24667 if (prefix != NULL) {
24668 xmlFree(prefix);
24670 * A namespace must be found if the prefix is
24671 * NOT NULL.
24673 if (nsName == NULL) {
24674 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24675 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24676 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24677 "The QName value '%s' has no "
24678 "corresponding namespace declaration in "
24679 "scope", value, NULL);
24680 if (local != NULL)
24681 xmlFree(local);
24682 return (ret);
24685 if (valNeeded && val) {
24686 if (nsName != NULL)
24687 *val = xmlSchemaNewQNameValue(
24688 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24689 else
24690 *val = xmlSchemaNewQNameValue(NULL,
24691 BAD_CAST local);
24692 } else
24693 xmlFree(local);
24694 return (0);
24698 * cvc-simple-type
24700 static int
24701 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24702 xmlNodePtr node,
24703 xmlSchemaTypePtr type,
24704 const xmlChar *value,
24705 xmlSchemaValPtr *retVal,
24706 int fireErrors,
24707 int normalize,
24708 int isNormalized)
24710 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24711 xmlSchemaValPtr val = NULL;
24712 /* xmlSchemaWhitespaceValueType ws; */
24713 xmlChar *normValue = NULL;
24715 #define NORMALIZE(atype) \
24716 if ((! isNormalized) && \
24717 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24718 normValue = xmlSchemaNormalizeValue(atype, value); \
24719 if (normValue != NULL) \
24720 value = normValue; \
24721 isNormalized = 1; \
24724 if ((retVal != NULL) && (*retVal != NULL)) {
24725 xmlSchemaFreeValue(*retVal);
24726 *retVal = NULL;
24729 * 3.14.4 Simple Type Definition Validation Rules
24730 * Validation Rule: String Valid
24733 * 1 It is schema-valid with respect to that definition as defined
24734 * by Datatype Valid in [XML Schemas: Datatypes].
24737 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24738 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24739 * the string must be a `declared entity name`.
24742 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24743 * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24744 * then every whitespace-delimited substring of the string must be a `declared
24745 * entity name`.
24748 * 2.3 otherwise no further condition applies.
24750 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24751 valNeeded = 1;
24752 if (value == NULL)
24753 value = BAD_CAST "";
24754 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24755 xmlSchemaTypePtr biType; /* The built-in type. */
24757 * SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24758 * a literal in the `lexical space` of {base type definition}"
24761 * Whitespace-normalize.
24763 NORMALIZE(type);
24764 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24766 * Get the built-in type.
24768 biType = type->baseType;
24769 while ((biType != NULL) &&
24770 (biType->type != XML_SCHEMA_TYPE_BASIC))
24771 biType = biType->baseType;
24773 if (biType == NULL) {
24774 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24775 "could not get the built-in type");
24776 goto internal_error;
24778 } else
24779 biType = type;
24781 * NOTATIONs need to be processed here, since they need
24782 * to lookup in the hashtable of NOTATION declarations of the schema.
24784 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24785 switch (biType->builtInType) {
24786 case XML_SCHEMAS_NOTATION:
24787 ret = xmlSchemaValidateNotation(
24788 (xmlSchemaValidCtxtPtr) actxt,
24789 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24790 NULL, value, &val, valNeeded);
24791 break;
24792 case XML_SCHEMAS_QNAME:
24793 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24794 value, &val, valNeeded);
24795 break;
24796 default:
24797 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24798 if (valNeeded)
24799 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24800 value, &val, node);
24801 else
24802 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24803 value, NULL, node);
24804 break;
24806 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24807 switch (biType->builtInType) {
24808 case XML_SCHEMAS_NOTATION:
24809 ret = xmlSchemaValidateNotation(NULL,
24810 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24811 value, &val, valNeeded);
24812 break;
24813 default:
24814 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24815 if (valNeeded)
24816 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24817 value, &val, node);
24818 else
24819 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24820 value, NULL, node);
24821 break;
24823 } else {
24825 * Validation via a public API is not implemented yet.
24827 TODO
24828 goto internal_error;
24830 if (ret != 0) {
24831 if (ret < 0) {
24832 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24833 "validating against a built-in type");
24834 goto internal_error;
24836 if (WXS_IS_LIST(type))
24837 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24838 else
24839 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24841 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24843 * Check facets.
24845 ret = xmlSchemaValidateFacets(actxt, node, type,
24846 (xmlSchemaValType) biType->builtInType, value, val,
24847 0, fireErrors);
24848 if (ret != 0) {
24849 if (ret < 0) {
24850 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24851 "validating facets of atomic simple type");
24852 goto internal_error;
24854 if (WXS_IS_LIST(type))
24855 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24856 else
24857 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24860 else if (fireErrors && (ret > 0))
24861 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24862 } else if (WXS_IS_LIST(type)) {
24864 xmlSchemaTypePtr itemType;
24865 const xmlChar *cur, *end;
24866 xmlChar *tmpValue = NULL;
24867 unsigned long len = 0;
24868 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24869 /* 1.2.2 if {variety} is `list` then the string must be a sequence
24870 * of white space separated tokens, each of which `match`es a literal
24871 * in the `lexical space` of {item type definition}
24874 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24875 * the list type has an enum or pattern facet.
24877 NORMALIZE(type);
24879 * VAL TODO: Optimize validation of empty values.
24880 * VAL TODO: We do not have computed values for lists.
24882 itemType = WXS_LIST_ITEMTYPE(type);
24883 cur = value;
24884 do {
24885 while (IS_BLANK_CH(*cur))
24886 cur++;
24887 end = cur;
24888 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24889 end++;
24890 if (end == cur)
24891 break;
24892 tmpValue = xmlStrndup(cur, end - cur);
24893 len++;
24895 if (valNeeded)
24896 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24897 tmpValue, &curVal, fireErrors, 0, 1);
24898 else
24899 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24900 tmpValue, NULL, fireErrors, 0, 1);
24901 FREE_AND_NULL(tmpValue);
24902 if (curVal != NULL) {
24904 * Add to list of computed values.
24906 if (val == NULL)
24907 val = curVal;
24908 else
24909 xmlSchemaValueAppend(prevVal, curVal);
24910 prevVal = curVal;
24911 curVal = NULL;
24913 if (ret != 0) {
24914 if (ret < 0) {
24915 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24916 "validating an item of list simple type");
24917 goto internal_error;
24919 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24920 break;
24922 cur = end;
24923 } while (*cur != 0);
24924 FREE_AND_NULL(tmpValue);
24925 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24927 * Apply facets (pattern, enumeration).
24929 ret = xmlSchemaValidateFacets(actxt, node, type,
24930 XML_SCHEMAS_UNKNOWN, value, val,
24931 len, fireErrors);
24932 if (ret != 0) {
24933 if (ret < 0) {
24934 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24935 "validating facets of list simple type");
24936 goto internal_error;
24938 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24941 if (fireErrors && (ret > 0)) {
24943 * Report the normalized value.
24945 normalize = 1;
24946 NORMALIZE(type);
24947 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24949 } else if (WXS_IS_UNION(type)) {
24950 xmlSchemaTypeLinkPtr memberLink;
24952 * TODO: For all datatypes `derived` by `union` whiteSpace does
24953 * not apply directly; however, the normalization behavior of `union`
24954 * types is controlled by the value of whiteSpace on that one of the
24955 * `memberTypes` against which the `union` is successfully validated.
24957 * This means that the value is normalized by the first validating
24958 * member type, then the facets of the union type are applied. This
24959 * needs changing of the value!
24963 * 1.2.3 if {variety} is `union` then the string must `match` a
24964 * literal in the `lexical space` of at least one member of
24965 * {member type definitions}
24967 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24968 if (memberLink == NULL) {
24969 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24970 "union simple type has no member types");
24971 goto internal_error;
24974 * Always normalize union type values, since we currently
24975 * cannot store the whitespace information with the value
24976 * itself; otherwise a later value-comparison would be
24977 * not possible.
24979 while (memberLink != NULL) {
24980 if (valNeeded)
24981 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24982 memberLink->type, value, &val, 0, 1, 0);
24983 else
24984 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24985 memberLink->type, value, NULL, 0, 1, 0);
24986 if (ret <= 0)
24987 break;
24988 memberLink = memberLink->next;
24990 if (ret != 0) {
24991 if (ret < 0) {
24992 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24993 "validating members of union simple type");
24994 goto internal_error;
24996 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24999 * Apply facets (pattern, enumeration).
25001 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
25003 * The normalization behavior of `union` types is controlled by
25004 * the value of whiteSpace on that one of the `memberTypes`
25005 * against which the `union` is successfully validated.
25007 NORMALIZE(memberLink->type);
25008 ret = xmlSchemaValidateFacets(actxt, node, type,
25009 XML_SCHEMAS_UNKNOWN, value, val,
25010 0, fireErrors);
25011 if (ret != 0) {
25012 if (ret < 0) {
25013 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
25014 "validating facets of union simple type");
25015 goto internal_error;
25017 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
25020 if (fireErrors && (ret > 0))
25021 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
25024 if (normValue != NULL)
25025 xmlFree(normValue);
25026 if (ret == 0) {
25027 if (retVal != NULL)
25028 *retVal = val;
25029 else if (val != NULL)
25030 xmlSchemaFreeValue(val);
25031 } else if (val != NULL)
25032 xmlSchemaFreeValue(val);
25033 return (ret);
25034 internal_error:
25035 if (normValue != NULL)
25036 xmlFree(normValue);
25037 if (val != NULL)
25038 xmlSchemaFreeValue(val);
25039 return (-1);
25042 static int
25043 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
25044 const xmlChar *value,
25045 const xmlChar **nsName,
25046 const xmlChar **localName)
25048 int ret = 0;
25050 if ((nsName == NULL) || (localName == NULL))
25051 return (-1);
25052 *nsName = NULL;
25053 *localName = NULL;
25055 ret = xmlValidateQName(value, 1);
25056 if (ret == -1)
25057 return (-1);
25058 if (ret > 0) {
25059 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
25060 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25061 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
25062 return (1);
25065 xmlChar *local = NULL;
25066 xmlChar *prefix;
25069 * NOTE: xmlSplitQName2 will return a duplicated
25070 * string.
25072 local = xmlSplitQName2(value, &prefix);
25073 if (local == NULL)
25074 *localName = xmlDictLookup(vctxt->dict, value, -1);
25075 else {
25076 *localName = xmlDictLookup(vctxt->dict, local, -1);
25077 xmlFree(local);
25080 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
25082 if (prefix != NULL) {
25083 xmlFree(prefix);
25085 * A namespace must be found if the prefix is NOT NULL.
25087 if (*nsName == NULL) {
25088 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25089 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25090 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
25091 "The QName value '%s' has no "
25092 "corresponding namespace declaration in scope",
25093 value, NULL);
25094 return (2);
25098 return (0);
25101 static int
25102 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
25103 xmlSchemaAttrInfoPtr iattr,
25104 xmlSchemaTypePtr *localType,
25105 xmlSchemaElementPtr elemDecl)
25107 int ret = 0;
25109 * cvc-elt (3.3.4) : (4)
25110 * AND
25111 * Schema-Validity Assessment (Element) (cvc-assess-elt)
25112 * (1.2.1.2.1) - (1.2.1.2.4)
25113 * Handle 'xsi:type'.
25115 if (localType == NULL)
25116 return (-1);
25117 *localType = NULL;
25118 if (iattr == NULL)
25119 return (0);
25120 else {
25121 const xmlChar *nsName = NULL, *local = NULL;
25123 * TODO: We should report a *warning* that the type was overridden
25124 * by the instance.
25126 ACTIVATE_ATTRIBUTE(iattr);
25128 * (cvc-elt) (3.3.4) : (4.1)
25129 * (cvc-assess-elt) (1.2.1.2.2)
25131 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
25132 &nsName, &local);
25133 if (ret != 0) {
25134 if (ret < 0) {
25135 VERROR_INT("xmlSchemaValidateElementByDeclaration",
25136 "calling xmlSchemaQNameExpand() to validate the "
25137 "attribute 'xsi:type'");
25138 goto internal_error;
25140 goto exit;
25143 * (cvc-elt) (3.3.4) : (4.2)
25144 * (cvc-assess-elt) (1.2.1.2.3)
25146 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
25147 if (*localType == NULL) {
25148 xmlChar *str = NULL;
25150 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25151 XML_SCHEMAV_CVC_ELT_4_2, NULL,
25152 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
25153 "The QName value '%s' of the xsi:type attribute does not "
25154 "resolve to a type definition",
25155 xmlSchemaFormatQName(&str, nsName, local), NULL);
25156 FREE_AND_NULL(str);
25157 ret = vctxt->err;
25158 goto exit;
25160 if (elemDecl != NULL) {
25161 int set = 0;
25164 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
25165 * "The `local type definition` must be validly
25166 * derived from the {type definition} given the union of
25167 * the {disallowed substitutions} and the {type definition}'s
25168 * {prohibited substitutions}, as defined in
25169 * Type Derivation OK (Complex) ($3.4.6)
25170 * (if it is a complex type definition),
25171 * or given {disallowed substitutions} as defined in Type
25172 * Derivation OK (Simple) ($3.14.6) (if it is a simple type
25173 * definition)."
25175 * {disallowed substitutions}: the "block" on the element decl.
25176 * {prohibited substitutions}: the "block" on the type def.
25179 * OPTIMIZE TODO: We could map types already evaluated
25180 * to be validly derived from other types to avoid checking
25181 * this over and over for the same types.
25183 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
25184 (elemDecl->subtypes->flags &
25185 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
25186 set |= SUBSET_EXTENSION;
25188 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
25189 (elemDecl->subtypes->flags &
25190 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
25191 set |= SUBSET_RESTRICTION;
25194 * REMOVED and CHANGED since this produced a parser context
25195 * which adds to the string dict of the schema. So this would
25196 * change the schema and we don't want this. We don't need
25197 * the parser context anymore.
25199 * if ((vctxt->pctxt == NULL) &&
25200 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
25201 * return (-1);
25204 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
25205 elemDecl->subtypes, set) != 0) {
25206 xmlChar *str = NULL;
25208 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25209 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
25210 "The type definition '%s', specified by xsi:type, is "
25211 "blocked or not validly derived from the type definition "
25212 "of the element declaration",
25213 xmlSchemaFormatQName(&str,
25214 (*localType)->targetNamespace,
25215 (*localType)->name),
25216 NULL);
25217 FREE_AND_NULL(str);
25218 ret = vctxt->err;
25219 *localType = NULL;
25223 exit:
25224 ACTIVATE_ELEM;
25225 return (ret);
25226 internal_error:
25227 ACTIVATE_ELEM;
25228 return (-1);
25231 static int
25232 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
25234 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
25235 xmlSchemaTypePtr actualType;
25238 * cvc-elt (3.3.4) : 1
25240 if (elemDecl == NULL) {
25241 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25242 "No matching declaration available");
25243 return (vctxt->err);
25245 actualType = WXS_ELEM_TYPEDEF(elemDecl);
25247 * cvc-elt (3.3.4) : 2
25249 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25250 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25251 "The element declaration is abstract");
25252 return (vctxt->err);
25254 if (actualType == NULL) {
25255 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25256 "The type definition is absent");
25257 return (XML_SCHEMAV_CVC_TYPE_1);
25259 if (vctxt->nbAttrInfos != 0) {
25260 int ret;
25261 xmlSchemaAttrInfoPtr iattr;
25263 * cvc-elt (3.3.4) : 3
25264 * Handle 'xsi:nil'.
25266 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25267 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25268 if (iattr) {
25269 ACTIVATE_ATTRIBUTE(iattr);
25271 * Validate the value.
25273 ret = xmlSchemaVCheckCVCSimpleType(
25274 ACTXT_CAST vctxt, NULL,
25275 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25276 iattr->value, &(iattr->val), 1, 0, 0);
25277 ACTIVATE_ELEM;
25278 if (ret < 0) {
25279 VERROR_INT("xmlSchemaValidateElemDecl",
25280 "calling xmlSchemaVCheckCVCSimpleType() to "
25281 "validate the attribute 'xsi:nil'");
25282 return (-1);
25284 if (ret == 0) {
25285 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25287 * cvc-elt (3.3.4) : 3.1
25289 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25290 "The element is not 'nillable'");
25291 /* Does not return an error on purpose. */
25292 } else {
25293 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25295 * cvc-elt (3.3.4) : 3.2.2
25297 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25298 (elemDecl->value != NULL)) {
25299 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25300 "The element cannot be 'nilled' because "
25301 "there is a fixed value constraint defined "
25302 "for it");
25303 /* Does not return an error on purpose. */
25304 } else
25305 vctxt->inode->flags |=
25306 XML_SCHEMA_ELEM_INFO_NILLED;
25312 * cvc-elt (3.3.4) : 4
25313 * Handle 'xsi:type'.
25315 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25316 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25317 if (iattr) {
25318 xmlSchemaTypePtr localType = NULL;
25320 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25321 elemDecl);
25322 if (ret != 0) {
25323 if (ret == -1) {
25324 VERROR_INT("xmlSchemaValidateElemDecl",
25325 "calling xmlSchemaProcessXSIType() to "
25326 "process the attribute 'xsi:type'");
25327 return (-1);
25329 /* Does not return an error on purpose. */
25331 if (localType != NULL) {
25332 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25333 actualType = localType;
25338 * IDC: Register identity-constraint XPath matchers.
25340 if ((elemDecl->idcs != NULL) &&
25341 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25342 return (-1);
25344 * No actual type definition.
25346 if (actualType == NULL) {
25347 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25348 "The type definition is absent");
25349 return (XML_SCHEMAV_CVC_TYPE_1);
25352 * Remember the actual type definition.
25354 vctxt->inode->typeDef = actualType;
25356 return (0);
25359 static int
25360 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25362 xmlSchemaAttrInfoPtr iattr;
25363 int ret = 0, i;
25366 * SPEC cvc-type (3.1.1)
25367 * "The attributes of must be empty, excepting those whose namespace
25368 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25369 * whose local name is one of type, nil, schemaLocation or
25370 * noNamespaceSchemaLocation."
25372 if (vctxt->nbAttrInfos == 0)
25373 return (0);
25374 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25375 iattr = vctxt->attrInfos[i];
25376 if (! iattr->metaType) {
25377 ACTIVATE_ATTRIBUTE(iattr)
25378 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25379 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25380 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25383 ACTIVATE_ELEM
25384 return (ret);
25388 * Cleanup currently used attribute infos.
25390 static void
25391 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25393 int i;
25394 xmlSchemaAttrInfoPtr attr;
25396 if (vctxt->nbAttrInfos == 0)
25397 return;
25398 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25399 attr = vctxt->attrInfos[i];
25400 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25401 if (attr->localName != NULL)
25402 xmlFree((xmlChar *) attr->localName);
25403 if (attr->nsName != NULL)
25404 xmlFree((xmlChar *) attr->nsName);
25406 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25407 if (attr->value != NULL)
25408 xmlFree((xmlChar *) attr->value);
25410 if (attr->val != NULL) {
25411 xmlSchemaFreeValue(attr->val);
25412 attr->val = NULL;
25414 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25416 vctxt->nbAttrInfos = 0;
25420 * 3.4.4 Complex Type Definition Validation Rules
25421 * Element Locally Valid (Complex Type) (cvc-complex-type)
25422 * 3.2.4 Attribute Declaration Validation Rules
25423 * Validation Rule: Attribute Locally Valid (cvc-attribute)
25424 * Attribute Locally Valid (Use) (cvc-au)
25426 * Only "assessed" attribute information items will be visible to
25427 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25429 static int
25430 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25432 xmlSchemaTypePtr type = vctxt->inode->typeDef;
25433 xmlSchemaItemListPtr attrUseList;
25434 xmlSchemaAttributeUsePtr attrUse = NULL;
25435 xmlSchemaAttributePtr attrDecl = NULL;
25436 xmlSchemaAttrInfoPtr iattr, tmpiattr;
25437 int i, j, found, nbAttrs, nbUses;
25438 int xpathRes = 0, res, wildIDs = 0, fixed;
25439 xmlNodePtr defAttrOwnerElem = NULL;
25442 * SPEC (cvc-attribute)
25443 * (1) "The declaration must not be `absent` (see Missing
25444 * Sub-components ($5.3) for how this can fail to be
25445 * the case)."
25446 * (2) "Its {type definition} must not be absent."
25448 * NOTE (1) + (2): This is not handled here, since we currently do not
25449 * allow validation against schemas which have missing sub-components.
25451 * SPEC (cvc-complex-type)
25452 * (3) "For each attribute information item in the element information
25453 * item's [attributes] excepting those whose [namespace name] is
25454 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25455 * [local name] is one of type, nil, schemaLocation or
25456 * noNamespaceSchemaLocation, the appropriate case among the following
25457 * must be true:
25460 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25462 * @nbAttrs is the number of attributes present in the instance.
25464 nbAttrs = vctxt->nbAttrInfos;
25465 if (attrUseList != NULL)
25466 nbUses = attrUseList->nbItems;
25467 else
25468 nbUses = 0;
25469 for (i = 0; i < nbUses; i++) {
25470 found = 0;
25471 attrUse = attrUseList->items[i];
25472 attrDecl = WXS_ATTRUSE_DECL(attrUse);
25473 for (j = 0; j < nbAttrs; j++) {
25474 iattr = vctxt->attrInfos[j];
25476 * SPEC (cvc-complex-type) (3)
25477 * Skip meta attributes.
25479 if (iattr->metaType)
25480 continue;
25481 if (iattr->localName[0] != attrDecl->name[0])
25482 continue;
25483 if (!xmlStrEqual(iattr->localName, attrDecl->name))
25484 continue;
25485 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25486 continue;
25487 found = 1;
25489 * SPEC (cvc-complex-type)
25490 * (3.1) "If there is among the {attribute uses} an attribute
25491 * use with an {attribute declaration} whose {name} matches
25492 * the attribute information item's [local name] and whose
25493 * {target namespace} is identical to the attribute information
25494 * item's [namespace name] (where an `absent` {target namespace}
25495 * is taken to be identical to a [namespace name] with no value),
25496 * then the attribute information must be `valid` with respect
25497 * to that attribute use as per Attribute Locally Valid (Use)
25498 * ($3.5.4). In this case the {attribute declaration} of that
25499 * attribute use is the `context-determined declaration` for the
25500 * attribute information item with respect to Schema-Validity
25501 * Assessment (Attribute) ($3.2.4) and
25502 * Assessment Outcome (Attribute) ($3.2.5).
25504 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25505 iattr->use = attrUse;
25507 * Context-determined declaration.
25509 iattr->decl = attrDecl;
25510 iattr->typeDef = attrDecl->subtypes;
25511 break;
25514 if (found)
25515 continue;
25517 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25519 * Handle non-existent, required attributes.
25521 * SPEC (cvc-complex-type)
25522 * (4) "The {attribute declaration} of each attribute use in
25523 * the {attribute uses} whose {required} is true matches one
25524 * of the attribute information items in the element information
25525 * item's [attributes] as per clause 3.1 above."
25527 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25528 if (tmpiattr == NULL) {
25529 VERROR_INT(
25530 "xmlSchemaVAttributesComplex",
25531 "calling xmlSchemaGetFreshAttrInfo()");
25532 return (-1);
25534 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25535 tmpiattr->use = attrUse;
25536 tmpiattr->decl = attrDecl;
25537 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25538 ((attrUse->defValue != NULL) ||
25539 (attrDecl->defValue != NULL))) {
25541 * Handle non-existent, optional, default/fixed attributes.
25543 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25544 if (tmpiattr == NULL) {
25545 VERROR_INT(
25546 "xmlSchemaVAttributesComplex",
25547 "calling xmlSchemaGetFreshAttrInfo()");
25548 return (-1);
25550 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25551 tmpiattr->use = attrUse;
25552 tmpiattr->decl = attrDecl;
25553 tmpiattr->typeDef = attrDecl->subtypes;
25554 tmpiattr->localName = attrDecl->name;
25555 tmpiattr->nsName = attrDecl->targetNamespace;
25559 if (vctxt->nbAttrInfos == 0)
25560 return (0);
25562 * Validate against the wildcard.
25564 if (type->attributeWildcard != NULL) {
25566 * SPEC (cvc-complex-type)
25567 * (3.2.1) "There must be an {attribute wildcard}."
25569 for (i = 0; i < nbAttrs; i++) {
25570 iattr = vctxt->attrInfos[i];
25572 * SPEC (cvc-complex-type) (3)
25573 * Skip meta attributes.
25575 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25576 continue;
25578 * SPEC (cvc-complex-type)
25579 * (3.2.2) "The attribute information item must be `valid` with
25580 * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25582 * SPEC Item Valid (Wildcard) (cvc-wildcard)
25583 * "... its [namespace name] must be `valid` with respect to
25584 * the wildcard constraint, as defined in Wildcard allows
25585 * Namespace Name ($3.10.4)."
25587 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25588 iattr->nsName) == 0) {
25590 * Handle processContents.
25592 * SPEC (cvc-wildcard):
25593 * processContents | context-determined declaration:
25594 * "strict" "mustFind"
25595 * "lax" "none"
25596 * "skip" "skip"
25598 if (type->attributeWildcard->processContents ==
25599 XML_SCHEMAS_ANY_SKIP) {
25601 * context-determined declaration = "skip"
25603 * SPEC PSVI Assessment Outcome (Attribute)
25604 * [validity] = "notKnown"
25605 * [validation attempted] = "none"
25607 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25608 continue;
25611 * Find an attribute declaration.
25613 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25614 iattr->localName, iattr->nsName);
25615 if (iattr->decl != NULL) {
25616 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25618 * SPEC (cvc-complex-type)
25619 * (5) "Let [Definition:] the wild IDs be the set of
25620 * all attribute information item to which clause 3.2
25621 * applied and whose `validation` resulted in a
25622 * `context-determined declaration` of mustFind or no
25623 * `context-determined declaration` at all, and whose
25624 * [local name] and [namespace name] resolve (as
25625 * defined by QName resolution (Instance) ($3.15.4)) to
25626 * an attribute declaration whose {type definition} is
25627 * or is derived from ID. Then all of the following
25628 * must be true:"
25630 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25631 if (xmlSchemaIsDerivedFromBuiltInType(
25632 iattr->typeDef, XML_SCHEMAS_ID)) {
25634 * SPEC (5.1) "There must be no more than one
25635 * item in `wild IDs`."
25637 if (wildIDs != 0) {
25638 /* VAL TODO */
25639 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25640 TODO
25641 continue;
25643 wildIDs++;
25645 * SPEC (cvc-complex-type)
25646 * (5.2) "If `wild IDs` is non-empty, there must not
25647 * be any attribute uses among the {attribute uses}
25648 * whose {attribute declaration}'s {type definition}
25649 * is or is derived from ID."
25651 if (attrUseList != NULL) {
25652 for (j = 0; j < attrUseList->nbItems; j++) {
25653 if (xmlSchemaIsDerivedFromBuiltInType(
25654 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25655 XML_SCHEMAS_ID)) {
25656 /* URGENT VAL TODO: implement */
25657 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25658 TODO
25659 break;
25664 } else if (type->attributeWildcard->processContents ==
25665 XML_SCHEMAS_ANY_LAX) {
25666 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25668 * SPEC PSVI Assessment Outcome (Attribute)
25669 * [validity] = "notKnown"
25670 * [validation attempted] = "none"
25672 } else {
25673 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25679 if (vctxt->nbAttrInfos == 0)
25680 return (0);
25683 * Get the owner element; needed for creation of default attributes.
25684 * This fixes bug #341337, reported by David Grohmann.
25686 if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25687 xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25688 if (ielem && ielem->node && ielem->node->doc)
25689 defAttrOwnerElem = ielem->node;
25692 * Validate values, create default attributes, evaluate IDCs.
25694 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25695 iattr = vctxt->attrInfos[i];
25697 * VAL TODO: Note that we won't try to resolve IDCs to
25698 * "lax" and "skip" validated attributes. Check what to
25699 * do in this case.
25701 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25702 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25703 continue;
25705 * VAL TODO: What to do if the type definition is missing?
25707 if (iattr->typeDef == NULL) {
25708 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25709 continue;
25712 ACTIVATE_ATTRIBUTE(iattr);
25713 fixed = 0;
25714 xpathRes = 0;
25716 if (vctxt->xpathStates != NULL) {
25718 * Evaluate IDCs.
25720 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25721 XML_ATTRIBUTE_NODE);
25722 if (xpathRes == -1) {
25723 VERROR_INT("xmlSchemaVAttributesComplex",
25724 "calling xmlSchemaXPathEvaluate()");
25725 goto internal_error;
25729 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25731 * Default/fixed attributes.
25732 * We need the value only if we need to resolve IDCs or
25733 * will create default attributes.
25735 if ((xpathRes) || (defAttrOwnerElem)) {
25736 if (iattr->use->defValue != NULL) {
25737 iattr->value = (xmlChar *) iattr->use->defValue;
25738 iattr->val = iattr->use->defVal;
25739 } else {
25740 iattr->value = (xmlChar *) iattr->decl->defValue;
25741 iattr->val = iattr->decl->defVal;
25744 * IDCs will consume the precomputed default value,
25745 * so we need to clone it.
25747 if (iattr->val == NULL) {
25748 VERROR_INT("xmlSchemaVAttributesComplex",
25749 "default/fixed value on an attribute use was "
25750 "not precomputed");
25751 goto internal_error;
25753 iattr->val = xmlSchemaCopyValue(iattr->val);
25754 if (iattr->val == NULL) {
25755 VERROR_INT("xmlSchemaVAttributesComplex",
25756 "calling xmlSchemaCopyValue()");
25757 goto internal_error;
25761 * PSVI: Add the default attribute to the current element.
25762 * VAL TODO: Should we use the *normalized* value? This currently
25763 * uses the *initial* value.
25766 if (defAttrOwnerElem) {
25767 xmlChar *normValue;
25768 const xmlChar *value;
25770 value = iattr->value;
25772 * Normalize the value.
25774 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25775 iattr->value);
25776 if (normValue != NULL)
25777 value = BAD_CAST normValue;
25779 if (iattr->nsName == NULL) {
25780 if (xmlNewProp(defAttrOwnerElem,
25781 iattr->localName, value) == NULL) {
25782 VERROR_INT("xmlSchemaVAttributesComplex",
25783 "calling xmlNewProp()");
25784 if (normValue != NULL)
25785 xmlFree(normValue);
25786 goto internal_error;
25788 } else {
25789 xmlNsPtr ns;
25791 ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25792 defAttrOwnerElem, iattr->nsName);
25793 if (ns == NULL) {
25794 xmlChar prefix[12];
25795 int counter = 0;
25798 * Create a namespace declaration on the validation
25799 * root node if no namespace declaration is in scope.
25801 do {
25802 snprintf((char *) prefix, 12, "p%d", counter++);
25803 ns = xmlSearchNs(defAttrOwnerElem->doc,
25804 defAttrOwnerElem, BAD_CAST prefix);
25805 if (counter > 1000) {
25806 VERROR_INT(
25807 "xmlSchemaVAttributesComplex",
25808 "could not compute a ns prefix for a "
25809 "default/fixed attribute");
25810 if (normValue != NULL)
25811 xmlFree(normValue);
25812 goto internal_error;
25814 } while (ns != NULL);
25815 ns = xmlNewNs(vctxt->validationRoot,
25816 iattr->nsName, BAD_CAST prefix);
25819 * TODO:
25820 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25821 * If we have QNames: do we need to ensure there's a
25822 * prefix defined for the QName?
25824 xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25826 if (normValue != NULL)
25827 xmlFree(normValue);
25830 * Go directly to IDC evaluation.
25832 goto eval_idcs;
25835 * Validate the value.
25837 if (vctxt->value != NULL) {
25839 * Free last computed value; just for safety reasons.
25841 xmlSchemaFreeValue(vctxt->value);
25842 vctxt->value = NULL;
25845 * Note that the attribute *use* can be unavailable, if
25846 * the attribute was a wild attribute.
25848 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25849 ((iattr->use != NULL) &&
25850 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25851 fixed = 1;
25852 else
25853 fixed = 0;
25855 * SPEC (cvc-attribute)
25856 * (3) "The item's `normalized value` must be locally `valid`
25857 * with respect to that {type definition} as per
25858 * String Valid ($3.14.4)."
25860 * VAL TODO: Do we already have the
25861 * "normalized attribute value" here?
25863 if (xpathRes || fixed) {
25864 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25866 * Request a computed value.
25868 res = xmlSchemaVCheckCVCSimpleType(
25869 ACTXT_CAST vctxt,
25870 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25871 1, 1, 0);
25872 } else {
25873 res = xmlSchemaVCheckCVCSimpleType(
25874 ACTXT_CAST vctxt,
25875 iattr->node, iattr->typeDef, iattr->value, NULL,
25876 1, 0, 0);
25879 if (res != 0) {
25880 if (res == -1) {
25881 VERROR_INT("xmlSchemaVAttributesComplex",
25882 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25883 goto internal_error;
25885 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25887 * SPEC PSVI Assessment Outcome (Attribute)
25888 * [validity] = "invalid"
25890 goto eval_idcs;
25893 if (fixed) {
25895 * SPEC Attribute Locally Valid (Use) (cvc-au)
25896 * "For an attribute information item to be `valid`
25897 * with respect to an attribute use its *normalized*
25898 * value must match the *canonical* lexical
25899 * representation of the attribute use's {value
25900 * constraint}value, if it is present and fixed."
25902 * VAL TODO: The requirement for the *canonical* value
25903 * will be removed in XML Schema 1.1.
25906 * SPEC Attribute Locally Valid (cvc-attribute)
25907 * (4) "The item's *actual* value must match the *value* of
25908 * the {value constraint}, if it is present and fixed."
25910 if (iattr->val == NULL) {
25911 /* VAL TODO: A value was not precomputed. */
25912 TODO
25913 goto eval_idcs;
25915 if ((iattr->use != NULL) &&
25916 (iattr->use->defValue != NULL)) {
25917 if (iattr->use->defVal == NULL) {
25918 /* VAL TODO: A default value was not precomputed. */
25919 TODO
25920 goto eval_idcs;
25922 iattr->vcValue = iattr->use->defValue;
25924 if (xmlSchemaCompareValuesWhtsp(attr->val,
25925 (xmlSchemaWhitespaceValueType) ws,
25926 attr->use->defVal,
25927 (xmlSchemaWhitespaceValueType) ws) != 0) {
25929 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25930 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25931 } else {
25932 if (iattr->decl->defVal == NULL) {
25933 /* VAL TODO: A default value was not precomputed. */
25934 TODO
25935 goto eval_idcs;
25937 iattr->vcValue = iattr->decl->defValue;
25939 if (xmlSchemaCompareValuesWhtsp(attr->val,
25940 (xmlSchemaWhitespaceValueType) ws,
25941 attrDecl->defVal,
25942 (xmlSchemaWhitespaceValueType) ws) != 0) {
25944 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25945 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25948 * [validity] = "valid"
25951 eval_idcs:
25953 * Evaluate IDCs.
25955 if (xpathRes) {
25956 if (xmlSchemaXPathProcessHistory(vctxt,
25957 vctxt->depth +1) == -1) {
25958 VERROR_INT("xmlSchemaVAttributesComplex",
25959 "calling xmlSchemaXPathEvaluate()");
25960 goto internal_error;
25962 } else if (vctxt->xpathStates != NULL)
25963 xmlSchemaXPathPop(vctxt);
25967 * Report errors.
25969 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25970 iattr = vctxt->attrInfos[i];
25971 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25972 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25973 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25974 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25975 continue;
25976 ACTIVATE_ATTRIBUTE(iattr);
25977 switch (iattr->state) {
25978 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25979 xmlChar *str = NULL;
25980 ACTIVATE_ELEM;
25981 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25982 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25983 "The attribute '%s' is required but missing",
25984 xmlSchemaFormatQName(&str,
25985 iattr->decl->targetNamespace,
25986 iattr->decl->name),
25987 NULL);
25988 FREE_AND_NULL(str)
25989 break;
25991 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25992 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25993 "The type definition is absent");
25994 break;
25995 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25996 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25997 XML_SCHEMAV_CVC_AU, NULL, NULL,
25998 "The value '%s' does not match the fixed "
25999 "value constraint '%s'",
26000 iattr->value, iattr->vcValue);
26001 break;
26002 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
26003 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
26004 "No matching global attribute declaration available, but "
26005 "demanded by the strict wildcard");
26006 break;
26007 case XML_SCHEMAS_ATTR_UNKNOWN:
26008 if (iattr->metaType)
26009 break;
26011 * MAYBE VAL TODO: One might report different error messages
26012 * for the following errors.
26014 if (type->attributeWildcard == NULL) {
26015 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
26016 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
26017 } else {
26018 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
26019 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
26021 break;
26022 default:
26023 break;
26027 ACTIVATE_ELEM;
26028 return (0);
26029 internal_error:
26030 ACTIVATE_ELEM;
26031 return (-1);
26034 static int
26035 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
26036 int *skip)
26038 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
26040 * The namespace of the element was already identified to be
26041 * matching the wildcard.
26043 if ((skip == NULL) || (wild == NULL) ||
26044 (wild->type != XML_SCHEMA_TYPE_ANY)) {
26045 VERROR_INT("xmlSchemaValidateElemWildcard",
26046 "bad arguments");
26047 return (-1);
26049 *skip = 0;
26050 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
26052 * URGENT VAL TODO: Either we need to position the stream to the
26053 * next sibling, or walk the whole subtree.
26055 *skip = 1;
26056 return (0);
26059 xmlSchemaElementPtr decl = NULL;
26061 decl = xmlSchemaGetElem(vctxt->schema,
26062 vctxt->inode->localName, vctxt->inode->nsName);
26063 if (decl != NULL) {
26064 vctxt->inode->decl = decl;
26065 return (0);
26068 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
26069 /* VAL TODO: Change to proper error code. */
26070 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
26071 "No matching global element declaration available, but "
26072 "demanded by the strict wildcard");
26073 return (vctxt->err);
26075 if (vctxt->nbAttrInfos != 0) {
26076 xmlSchemaAttrInfoPtr iattr;
26078 * SPEC Validation Rule: Schema-Validity Assessment (Element)
26079 * (1.2.1.2.1) - (1.2.1.2.3 )
26081 * Use the xsi:type attribute for the type definition.
26083 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26084 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26085 if (iattr != NULL) {
26086 if (xmlSchemaProcessXSIType(vctxt, iattr,
26087 &(vctxt->inode->typeDef), NULL) == -1) {
26088 VERROR_INT("xmlSchemaValidateElemWildcard",
26089 "calling xmlSchemaProcessXSIType() to "
26090 "process the attribute 'xsi:nil'");
26091 return (-1);
26094 * Don't return an error on purpose.
26096 return (0);
26100 * SPEC Validation Rule: Schema-Validity Assessment (Element)
26102 * Fallback to "anyType".
26104 vctxt->inode->typeDef =
26105 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26106 return (0);
26110 * xmlSchemaCheckCOSValidDefault:
26112 * This will be called if: not nilled, no content and a default/fixed
26113 * value is provided.
26116 static int
26117 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
26118 const xmlChar *value,
26119 xmlSchemaValPtr *val)
26121 int ret = 0;
26122 xmlSchemaNodeInfoPtr inode = vctxt->inode;
26125 * cos-valid-default:
26126 * Schema Component Constraint: Element Default Valid (Immediate)
26127 * For a string to be a valid default with respect to a type
26128 * definition the appropriate case among the following must be true:
26130 if WXS_IS_COMPLEX(inode->typeDef) {
26132 * Complex type.
26134 * SPEC (2.1) "its {content type} must be a simple type definition
26135 * or mixed."
26136 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
26137 * type}'s particle must be `emptiable` as defined by
26138 * Particle Emptiable ($3.9.6)."
26140 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
26141 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
26142 (! WXS_EMPTIABLE(inode->typeDef)))) {
26143 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
26144 /* NOTE that this covers (2.2.2) as well. */
26145 VERROR(ret, NULL,
26146 "For a string to be a valid default, the type definition "
26147 "must be a simple type or a complex type with simple content "
26148 "or mixed content and a particle emptiable");
26149 return(ret);
26153 * 1 If the type definition is a simple type definition, then the string
26154 * must be `valid` with respect to that definition as defined by String
26155 * Valid ($3.14.4).
26157 * AND
26159 * 2.2.1 If the {content type} is a simple type definition, then the
26160 * string must be `valid` with respect to that simple type definition
26161 * as defined by String Valid ($3.14.4).
26163 if (WXS_IS_SIMPLE(inode->typeDef)) {
26165 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26166 NULL, inode->typeDef, value, val, 1, 1, 0);
26168 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26170 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26171 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
26173 if (ret < 0) {
26174 VERROR_INT("xmlSchemaCheckCOSValidDefault",
26175 "calling xmlSchemaVCheckCVCSimpleType()");
26177 return (ret);
26180 static void
26181 xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
26182 const xmlChar * name ATTRIBUTE_UNUSED,
26183 void *transdata, void *inputdata)
26185 xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
26186 xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
26187 inode->decl = item;
26188 #ifdef DEBUG_CONTENT
26190 xmlChar *str = NULL;
26192 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
26193 xmlGenericError(xmlGenericErrorContext,
26194 "AUTOMATON callback for '%s' [declaration]\n",
26195 xmlSchemaFormatQName(&str,
26196 inode->localName, inode->nsName));
26197 } else {
26198 xmlGenericError(xmlGenericErrorContext,
26199 "AUTOMATON callback for '%s' [wildcard]\n",
26200 xmlSchemaFormatQName(&str,
26201 inode->localName, inode->nsName));
26204 FREE_AND_NULL(str)
26206 #endif
26209 static int
26210 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
26212 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
26213 if (vctxt->inode == NULL) {
26214 VERROR_INT("xmlSchemaValidatorPushElem",
26215 "calling xmlSchemaGetFreshElemInfo()");
26216 return (-1);
26218 vctxt->nbAttrInfos = 0;
26219 return (0);
26222 static int
26223 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
26224 xmlSchemaNodeInfoPtr inode,
26225 xmlSchemaTypePtr type,
26226 const xmlChar *value)
26228 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
26229 return (xmlSchemaVCheckCVCSimpleType(
26230 ACTXT_CAST vctxt, NULL,
26231 type, value, &(inode->val), 1, 1, 0));
26232 else
26233 return (xmlSchemaVCheckCVCSimpleType(
26234 ACTXT_CAST vctxt, NULL,
26235 type, value, NULL, 1, 0, 0));
26241 * Process END of element.
26243 static int
26244 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26246 int ret = 0;
26247 xmlSchemaNodeInfoPtr inode = vctxt->inode;
26249 if (vctxt->nbAttrInfos != 0)
26250 xmlSchemaClearAttrInfos(vctxt);
26251 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26253 * This element was not expected;
26254 * we will not validate child elements of broken parents.
26255 * Skip validation of all content of the parent.
26257 vctxt->skipDepth = vctxt->depth -1;
26258 goto end_elem;
26260 if ((inode->typeDef == NULL) ||
26261 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26263 * 1. the type definition might be missing if the element was
26264 * error prone
26265 * 2. it might be abstract.
26267 goto end_elem;
26270 * Check the content model.
26272 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26273 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26276 * Workaround for "anyType".
26278 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26279 goto character_content;
26281 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26282 xmlChar *values[10];
26283 int terminal, nbval = 10, nbneg;
26285 if (inode->regexCtxt == NULL) {
26287 * Create the regex context.
26289 inode->regexCtxt =
26290 xmlRegNewExecCtxt(inode->typeDef->contModel,
26291 xmlSchemaVContentModelCallback, vctxt);
26292 if (inode->regexCtxt == NULL) {
26293 VERROR_INT("xmlSchemaValidatorPopElem",
26294 "failed to create a regex context");
26295 goto internal_error;
26297 #ifdef DEBUG_AUTOMATA
26298 xmlGenericError(xmlGenericErrorContext,
26299 "AUTOMATON create on '%s'\n", inode->localName);
26300 #endif
26304 * Do not check further content if the node has been nilled
26306 if (INODE_NILLED(inode)) {
26307 ret = 0;
26308 #ifdef DEBUG_AUTOMATA
26309 xmlGenericError(xmlGenericErrorContext,
26310 "AUTOMATON succeeded on nilled '%s'\n",
26311 inode->localName);
26312 #endif
26313 goto skip_nilled;
26317 * Get hold of the still expected content, since a further
26318 * call to xmlRegExecPushString() will lose this information.
26320 xmlRegExecNextValues(inode->regexCtxt,
26321 &nbval, &nbneg, &values[0], &terminal);
26322 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26323 if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26325 * Still missing something.
26327 ret = 1;
26328 inode->flags |=
26329 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26330 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26331 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26332 "Missing child element(s)",
26333 nbval, nbneg, values);
26334 #ifdef DEBUG_AUTOMATA
26335 xmlGenericError(xmlGenericErrorContext,
26336 "AUTOMATON missing ERROR on '%s'\n",
26337 inode->localName);
26338 #endif
26339 } else {
26341 * Content model is satisfied.
26343 ret = 0;
26344 #ifdef DEBUG_AUTOMATA
26345 xmlGenericError(xmlGenericErrorContext,
26346 "AUTOMATON succeeded on '%s'\n",
26347 inode->localName);
26348 #endif
26354 skip_nilled:
26356 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26357 goto end_elem;
26359 character_content:
26361 if (vctxt->value != NULL) {
26362 xmlSchemaFreeValue(vctxt->value);
26363 vctxt->value = NULL;
26366 * Check character content.
26368 if (inode->decl == NULL) {
26370 * Speedup if no declaration exists.
26372 if (WXS_IS_SIMPLE(inode->typeDef)) {
26373 ret = xmlSchemaVCheckINodeDataType(vctxt,
26374 inode, inode->typeDef, inode->value);
26375 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26376 ret = xmlSchemaVCheckINodeDataType(vctxt,
26377 inode, inode->typeDef->contentTypeDef,
26378 inode->value);
26380 if (ret < 0) {
26381 VERROR_INT("xmlSchemaValidatorPopElem",
26382 "calling xmlSchemaVCheckCVCSimpleType()");
26383 goto internal_error;
26385 goto end_elem;
26388 * cvc-elt (3.3.4) : 5
26389 * The appropriate case among the following must be true:
26392 * cvc-elt (3.3.4) : 5.1
26393 * If the declaration has a {value constraint},
26394 * the item has neither element nor character [children] and
26395 * clause 3.2 has not applied, then all of the following must be true:
26397 if ((inode->decl->value != NULL) &&
26398 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26399 (! INODE_NILLED(inode))) {
26401 * cvc-elt (3.3.4) : 5.1.1
26402 * If the `actual type definition` is a `local type definition`
26403 * then the canonical lexical representation of the {value constraint}
26404 * value must be a valid default for the `actual type definition` as
26405 * defined in Element Default Valid (Immediate) ($3.3.6).
26408 * NOTE: 'local' above means types acquired by xsi:type.
26409 * NOTE: Although the *canonical* value is stated, it is not
26410 * relevant if canonical or not. Additionally XML Schema 1.1
26411 * will removed this requirement as well.
26413 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26415 ret = xmlSchemaCheckCOSValidDefault(vctxt,
26416 inode->decl->value, &(inode->val));
26417 if (ret != 0) {
26418 if (ret < 0) {
26419 VERROR_INT("xmlSchemaValidatorPopElem",
26420 "calling xmlSchemaCheckCOSValidDefault()");
26421 goto internal_error;
26423 goto end_elem;
26426 * Stop here, to avoid redundant validation of the value
26427 * (see following).
26429 goto default_psvi;
26432 * cvc-elt (3.3.4) : 5.1.2
26433 * The element information item with the canonical lexical
26434 * representation of the {value constraint} value used as its
26435 * `normalized value` must be `valid` with respect to the
26436 * `actual type definition` as defined by Element Locally Valid (Type)
26437 * ($3.3.4).
26439 if (WXS_IS_SIMPLE(inode->typeDef)) {
26440 ret = xmlSchemaVCheckINodeDataType(vctxt,
26441 inode, inode->typeDef, inode->decl->value);
26442 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26443 ret = xmlSchemaVCheckINodeDataType(vctxt,
26444 inode, inode->typeDef->contentTypeDef,
26445 inode->decl->value);
26447 if (ret != 0) {
26448 if (ret < 0) {
26449 VERROR_INT("xmlSchemaValidatorPopElem",
26450 "calling xmlSchemaVCheckCVCSimpleType()");
26451 goto internal_error;
26453 goto end_elem;
26456 default_psvi:
26458 * PSVI: Create a text node on the instance element.
26460 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26461 (inode->node != NULL)) {
26462 xmlNodePtr textChild;
26463 xmlChar *normValue;
26465 * VAL TODO: Normalize the value.
26467 normValue = xmlSchemaNormalizeValue(inode->typeDef,
26468 inode->decl->value);
26469 if (normValue != NULL) {
26470 textChild = xmlNewDocText(inode->node->doc,
26471 BAD_CAST normValue);
26472 xmlFree(normValue);
26473 } else
26474 textChild = xmlNewDocText(inode->node->doc,
26475 inode->decl->value);
26476 if (textChild == NULL) {
26477 VERROR_INT("xmlSchemaValidatorPopElem",
26478 "calling xmlNewDocText()");
26479 goto internal_error;
26480 } else
26481 xmlAddChild(inode->node, textChild);
26484 } else if (! INODE_NILLED(inode)) {
26486 * 5.2.1 The element information item must be `valid` with respect
26487 * to the `actual type definition` as defined by Element Locally
26488 * Valid (Type) ($3.3.4).
26490 if (WXS_IS_SIMPLE(inode->typeDef)) {
26492 * SPEC (cvc-type) (3.1)
26493 * "If the type definition is a simple type definition, ..."
26494 * (3.1.3) "If clause 3.2 of Element Locally Valid
26495 * (Element) ($3.3.4) did not apply, then the `normalized value`
26496 * must be `valid` with respect to the type definition as defined
26497 * by String Valid ($3.14.4).
26499 ret = xmlSchemaVCheckINodeDataType(vctxt,
26500 inode, inode->typeDef, inode->value);
26501 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26503 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26504 * definition, then the element information item must be
26505 * `valid` with respect to the type definition as per
26506 * Element Locally Valid (Complex Type) ($3.4.4);"
26508 * SPEC (cvc-complex-type) (2.2)
26509 * "If the {content type} is a simple type definition, ...
26510 * the `normalized value` of the element information item is
26511 * `valid` with respect to that simple type definition as
26512 * defined by String Valid ($3.14.4)."
26514 ret = xmlSchemaVCheckINodeDataType(vctxt,
26515 inode, inode->typeDef->contentTypeDef, inode->value);
26517 if (ret != 0) {
26518 if (ret < 0) {
26519 VERROR_INT("xmlSchemaValidatorPopElem",
26520 "calling xmlSchemaVCheckCVCSimpleType()");
26521 goto internal_error;
26523 goto end_elem;
26526 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26527 * not applied, all of the following must be true:
26529 if ((inode->decl->value != NULL) &&
26530 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26533 * TODO: We will need a computed value, when comparison is
26534 * done on computed values.
26537 * 5.2.2.1 The element information item must have no element
26538 * information item [children].
26540 if (inode->flags &
26541 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26542 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26543 VERROR(ret, NULL,
26544 "The content must not contain element nodes since "
26545 "there is a fixed value constraint");
26546 goto end_elem;
26547 } else {
26549 * 5.2.2.2 The appropriate case among the following must
26550 * be true:
26552 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26554 * 5.2.2.2.1 If the {content type} of the `actual type
26555 * definition` is mixed, then the *initial value* of the
26556 * item must match the canonical lexical representation
26557 * of the {value constraint} value.
26559 * ... the *initial value* of an element information
26560 * item is the string composed of, in order, the
26561 * [character code] of each character information item in
26562 * the [children] of that element information item.
26564 if (! xmlStrEqual(inode->value, inode->decl->value)){
26566 * VAL TODO: Report invalid & expected values as well.
26567 * VAL TODO: Implement the canonical stuff.
26569 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26570 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26571 ret, NULL, NULL,
26572 "The initial value '%s' does not match the fixed "
26573 "value constraint '%s'",
26574 inode->value, inode->decl->value);
26575 goto end_elem;
26577 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26579 * 5.2.2.2.2 If the {content type} of the `actual type
26580 * definition` is a simple type definition, then the
26581 * *actual value* of the item must match the canonical
26582 * lexical representation of the {value constraint} value.
26585 * VAL TODO: *actual value* is the normalized value, impl.
26586 * this.
26587 * VAL TODO: Report invalid & expected values as well.
26588 * VAL TODO: Implement a comparison with the computed values.
26590 if (! xmlStrEqual(inode->value,
26591 inode->decl->value)) {
26592 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26593 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26594 ret, NULL, NULL,
26595 "The actual value '%s' does not match the fixed "
26596 "value constraint '%s'",
26597 inode->value,
26598 inode->decl->value);
26599 goto end_elem;
26606 end_elem:
26607 if (vctxt->depth < 0) {
26608 /* TODO: raise error? */
26609 return (0);
26611 if (vctxt->depth == vctxt->skipDepth)
26612 vctxt->skipDepth = -1;
26614 * Evaluate the history of XPath state objects.
26616 if (inode->appliedXPath &&
26617 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26618 goto internal_error;
26620 * MAYBE TODO:
26621 * SPEC (6) "The element information item must be `valid` with
26622 * respect to each of the {identity-constraint definitions} as per
26623 * Identity-constraint Satisfied ($3.11.4)."
26626 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26627 * need to be built in any case.
26628 * We will currently build IDC node-tables and bubble them only if
26629 * keyrefs do exist.
26633 * Add the current IDC target-nodes to the IDC node-tables.
26635 if ((inode->idcMatchers != NULL) &&
26636 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26638 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26639 goto internal_error;
26642 * Validate IDC keyrefs.
26644 if (vctxt->inode->hasKeyrefs)
26645 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26646 goto internal_error;
26648 * Merge/free the IDC table.
26650 if (inode->idcTable != NULL) {
26651 #ifdef DEBUG_IDC_NODE_TABLE
26652 xmlSchemaDebugDumpIDCTable(stdout,
26653 inode->nsName,
26654 inode->localName,
26655 inode->idcTable);
26656 #endif
26657 if ((vctxt->depth > 0) &&
26658 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26661 * Merge the IDC node table with the table of the parent node.
26663 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26664 goto internal_error;
26668 * Clear the current ielem.
26669 * VAL TODO: Don't free the PSVI IDC tables if they are
26670 * requested for the PSVI.
26672 xmlSchemaClearElemInfo(vctxt, inode);
26674 * Skip further processing if we are on the validation root.
26676 if (vctxt->depth == 0) {
26677 vctxt->depth--;
26678 vctxt->inode = NULL;
26679 return (0);
26682 * Reset the keyrefDepth if needed.
26684 if (vctxt->aidcs != NULL) {
26685 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26686 do {
26687 if (aidc->keyrefDepth == vctxt->depth) {
26689 * A 'keyrefDepth' of a key/unique IDC matches the current
26690 * depth, this means that we are leaving the scope of the
26691 * top-most keyref IDC which refers to this IDC.
26693 aidc->keyrefDepth = -1;
26695 aidc = aidc->next;
26696 } while (aidc != NULL);
26698 vctxt->depth--;
26699 vctxt->inode = vctxt->elemInfos[vctxt->depth];
26701 * VAL TODO: 7 If the element information item is the `validation root`, it must be
26702 * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26704 return (ret);
26706 internal_error:
26707 vctxt->err = -1;
26708 return (-1);
26712 * 3.4.4 Complex Type Definition Validation Rules
26713 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26715 static int
26716 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26718 xmlSchemaNodeInfoPtr pielem;
26719 xmlSchemaTypePtr ptype;
26720 int ret = 0;
26722 if (vctxt->depth <= 0) {
26723 VERROR_INT("xmlSchemaValidateChildElem",
26724 "not intended for the validation root");
26725 return (-1);
26727 pielem = vctxt->elemInfos[vctxt->depth -1];
26728 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26729 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26731 * Handle 'nilled' elements.
26733 if (INODE_NILLED(pielem)) {
26735 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26737 ACTIVATE_PARENT_ELEM;
26738 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26739 VERROR(ret, NULL,
26740 "Neither character nor element content is allowed, "
26741 "because the element was 'nilled'");
26742 ACTIVATE_ELEM;
26743 goto unexpected_elem;
26746 ptype = pielem->typeDef;
26748 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26750 * Workaround for "anyType": we have currently no content model
26751 * assigned for "anyType", so handle it explicitly.
26752 * "anyType" has an unbounded, lax "any" wildcard.
26754 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26755 vctxt->inode->localName,
26756 vctxt->inode->nsName);
26758 if (vctxt->inode->decl == NULL) {
26759 xmlSchemaAttrInfoPtr iattr;
26761 * Process "xsi:type".
26762 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26764 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26765 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26766 if (iattr != NULL) {
26767 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26768 &(vctxt->inode->typeDef), NULL);
26769 if (ret != 0) {
26770 if (ret == -1) {
26771 VERROR_INT("xmlSchemaValidateChildElem",
26772 "calling xmlSchemaProcessXSIType() to "
26773 "process the attribute 'xsi:nil'");
26774 return (-1);
26776 return (ret);
26778 } else {
26780 * Fallback to "anyType".
26782 * SPEC (cvc-assess-elt)
26783 * "If the item cannot be `strictly assessed`, [...]
26784 * an element information item's schema validity may be laxly
26785 * assessed if its `context-determined declaration` is not
26786 * skip by `validating` with respect to the `ur-type
26787 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26789 vctxt->inode->typeDef =
26790 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26793 return (0);
26796 switch (ptype->contentType) {
26797 case XML_SCHEMA_CONTENT_EMPTY:
26799 * SPEC (2.1) "If the {content type} is empty, then the
26800 * element information item has no character or element
26801 * information item [children]."
26803 ACTIVATE_PARENT_ELEM
26804 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26805 VERROR(ret, NULL,
26806 "Element content is not allowed, "
26807 "because the content type is empty");
26808 ACTIVATE_ELEM
26809 goto unexpected_elem;
26810 break;
26812 case XML_SCHEMA_CONTENT_MIXED:
26813 case XML_SCHEMA_CONTENT_ELEMENTS: {
26814 xmlRegExecCtxtPtr regexCtxt;
26815 xmlChar *values[10];
26816 int terminal, nbval = 10, nbneg;
26818 /* VAL TODO: Optimized "anyType" validation.*/
26820 if (ptype->contModel == NULL) {
26821 VERROR_INT("xmlSchemaValidateChildElem",
26822 "type has elem content but no content model");
26823 return (-1);
26826 * Safety belt for evaluation if the cont. model was already
26827 * examined to be invalid.
26829 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26830 VERROR_INT("xmlSchemaValidateChildElem",
26831 "validating elem, but elem content is already invalid");
26832 return (-1);
26835 regexCtxt = pielem->regexCtxt;
26836 if (regexCtxt == NULL) {
26838 * Create the regex context.
26840 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26841 xmlSchemaVContentModelCallback, vctxt);
26842 if (regexCtxt == NULL) {
26843 VERROR_INT("xmlSchemaValidateChildElem",
26844 "failed to create a regex context");
26845 return (-1);
26847 pielem->regexCtxt = regexCtxt;
26848 #ifdef DEBUG_AUTOMATA
26849 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26850 pielem->localName);
26851 #endif
26855 * SPEC (2.4) "If the {content type} is element-only or mixed,
26856 * then the sequence of the element information item's
26857 * element information item [children], if any, taken in
26858 * order, is `valid` with respect to the {content type}'s
26859 * particle, as defined in Element Sequence Locally Valid
26860 * (Particle) ($3.9.4)."
26862 ret = xmlRegExecPushString2(regexCtxt,
26863 vctxt->inode->localName,
26864 vctxt->inode->nsName,
26865 vctxt->inode);
26866 #ifdef DEBUG_AUTOMATA
26867 if (ret < 0)
26868 xmlGenericError(xmlGenericErrorContext,
26869 "AUTOMATON push ERROR for '%s' on '%s'\n",
26870 vctxt->inode->localName, pielem->localName);
26871 else
26872 xmlGenericError(xmlGenericErrorContext,
26873 "AUTOMATON push OK for '%s' on '%s'\n",
26874 vctxt->inode->localName, pielem->localName);
26875 #endif
26876 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26877 VERROR_INT("xmlSchemaValidateChildElem",
26878 "calling xmlRegExecPushString2()");
26879 return (-1);
26881 if (ret < 0) {
26882 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26883 &values[0], &terminal);
26884 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26885 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26886 "This element is not expected",
26887 nbval, nbneg, values);
26888 ret = vctxt->err;
26889 goto unexpected_elem;
26890 } else
26891 ret = 0;
26893 break;
26894 case XML_SCHEMA_CONTENT_SIMPLE:
26895 case XML_SCHEMA_CONTENT_BASIC:
26896 ACTIVATE_PARENT_ELEM
26897 if (WXS_IS_COMPLEX(ptype)) {
26899 * SPEC (cvc-complex-type) (2.2)
26900 * "If the {content type} is a simple type definition, then
26901 * the element information item has no element information
26902 * item [children], ..."
26904 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26905 VERROR(ret, NULL, "Element content is not allowed, "
26906 "because the content type is a simple type definition");
26907 } else {
26909 * SPEC (cvc-type) (3.1.2) "The element information item must
26910 * have no element information item [children]."
26912 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26913 VERROR(ret, NULL, "Element content is not allowed, "
26914 "because the type definition is simple");
26916 ACTIVATE_ELEM
26917 ret = vctxt->err;
26918 goto unexpected_elem;
26919 break;
26921 default:
26922 break;
26924 return (ret);
26925 unexpected_elem:
26927 * Pop this element and set the skipDepth to skip
26928 * all further content of the parent element.
26930 vctxt->skipDepth = vctxt->depth;
26931 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26932 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26933 return (ret);
26936 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26937 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26938 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26940 static int
26941 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26942 int nodeType, const xmlChar *value, int len,
26943 int mode, int *consumed)
26946 * Unfortunately we have to duplicate the text sometimes.
26947 * OPTIMIZE: Maybe we could skip it, if:
26948 * 1. content type is simple
26949 * 2. whitespace is "collapse"
26950 * 3. it consists of whitespace only
26952 * Process character content.
26954 if (consumed != NULL)
26955 *consumed = 0;
26956 if (INODE_NILLED(vctxt->inode)) {
26958 * SPEC cvc-elt (3.3.4 - 3.2.1)
26959 * "The element information item must have no character or
26960 * element information item [children]."
26962 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26963 "Neither character nor element content is allowed "
26964 "because the element is 'nilled'");
26965 return (vctxt->err);
26968 * SPEC (2.1) "If the {content type} is empty, then the
26969 * element information item has no character or element
26970 * information item [children]."
26972 if (vctxt->inode->typeDef->contentType ==
26973 XML_SCHEMA_CONTENT_EMPTY) {
26974 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26975 "Character content is not allowed, "
26976 "because the content type is empty");
26977 return (vctxt->err);
26980 if (vctxt->inode->typeDef->contentType ==
26981 XML_SCHEMA_CONTENT_ELEMENTS) {
26982 if ((nodeType != XML_TEXT_NODE) ||
26983 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26985 * SPEC cvc-complex-type (2.3)
26986 * "If the {content type} is element-only, then the
26987 * element information item has no character information
26988 * item [children] other than those whose [character
26989 * code] is defined as a white space in [XML 1.0 (Second
26990 * Edition)]."
26992 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26993 "Character content other than whitespace is not allowed "
26994 "because the content type is 'element-only'");
26995 return (vctxt->err);
26997 return (0);
27000 if ((value == NULL) || (value[0] == 0))
27001 return (0);
27003 * Save the value.
27004 * NOTE that even if the content type is *mixed*, we need the
27005 * *initial value* for default/fixed value constraints.
27007 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
27008 ((vctxt->inode->decl == NULL) ||
27009 (vctxt->inode->decl->value == NULL)))
27010 return (0);
27012 if (vctxt->inode->value == NULL) {
27014 * Set the value.
27016 switch (mode) {
27017 case XML_SCHEMA_PUSH_TEXT_PERSIST:
27019 * When working on a tree.
27021 vctxt->inode->value = value;
27022 break;
27023 case XML_SCHEMA_PUSH_TEXT_CREATED:
27025 * When working with the reader.
27026 * The value will be freed by the element info.
27028 vctxt->inode->value = value;
27029 if (consumed != NULL)
27030 *consumed = 1;
27031 vctxt->inode->flags |=
27032 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27033 break;
27034 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
27036 * When working with SAX.
27037 * The value will be freed by the element info.
27039 if (len != -1)
27040 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
27041 else
27042 vctxt->inode->value = BAD_CAST xmlStrdup(value);
27043 vctxt->inode->flags |=
27044 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27045 break;
27046 default:
27047 break;
27049 } else {
27050 if (len < 0)
27051 len = xmlStrlen(value);
27053 * Concat the value.
27055 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
27056 vctxt->inode->value = BAD_CAST xmlStrncat(
27057 (xmlChar *) vctxt->inode->value, value, len);
27058 } else {
27059 vctxt->inode->value =
27060 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
27061 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27065 return (0);
27068 static int
27069 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
27071 int ret = 0;
27073 if ((vctxt->skipDepth != -1) &&
27074 (vctxt->depth >= vctxt->skipDepth)) {
27075 VERROR_INT("xmlSchemaValidateElem",
27076 "in skip-state");
27077 goto internal_error;
27079 if (vctxt->xsiAssemble) {
27081 * We will stop validation if there was an error during
27082 * dynamic schema construction.
27083 * Note that we simply set @skipDepth to 0, this could
27084 * mean that a streaming document via SAX would be
27085 * still read to the end but it won't be validated any more.
27086 * TODO: If we are sure how to stop the validation at once
27087 * for all input scenarios, then this should be changed to
27088 * instantly stop the validation.
27090 ret = xmlSchemaAssembleByXSI(vctxt);
27091 if (ret != 0) {
27092 if (ret == -1)
27093 goto internal_error;
27094 vctxt->skipDepth = 0;
27095 return(ret);
27098 * Augment the IDC definitions for the main schema and all imported ones
27099 * NOTE: main schema is the first in the imported list
27101 xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
27102 vctxt);
27104 if (vctxt->depth > 0) {
27106 * Validate this element against the content model
27107 * of the parent.
27109 ret = xmlSchemaValidateChildElem(vctxt);
27110 if (ret != 0) {
27111 if (ret < 0) {
27112 VERROR_INT("xmlSchemaValidateElem",
27113 "calling xmlSchemaStreamValidateChildElement()");
27114 goto internal_error;
27116 goto exit;
27118 if (vctxt->depth == vctxt->skipDepth)
27119 goto exit;
27120 if ((vctxt->inode->decl == NULL) &&
27121 (vctxt->inode->typeDef == NULL)) {
27122 VERROR_INT("xmlSchemaValidateElem",
27123 "the child element was valid but neither the "
27124 "declaration nor the type was set");
27125 goto internal_error;
27127 } else {
27129 * Get the declaration of the validation root.
27131 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
27132 vctxt->inode->localName,
27133 vctxt->inode->nsName);
27134 if (vctxt->inode->decl == NULL) {
27135 ret = XML_SCHEMAV_CVC_ELT_1;
27136 VERROR(ret, NULL,
27137 "No matching global declaration available "
27138 "for the validation root");
27139 goto exit;
27143 if (vctxt->inode->decl == NULL)
27144 goto type_validation;
27146 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
27147 int skip;
27149 * Wildcards.
27151 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
27152 if (ret != 0) {
27153 if (ret < 0) {
27154 VERROR_INT("xmlSchemaValidateElem",
27155 "calling xmlSchemaValidateElemWildcard()");
27156 goto internal_error;
27158 goto exit;
27160 if (skip) {
27161 vctxt->skipDepth = vctxt->depth;
27162 goto exit;
27165 * The declaration might be set by the wildcard validation,
27166 * when the processContents is "lax" or "strict".
27168 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
27170 * Clear the "decl" field to not confuse further processing.
27172 vctxt->inode->decl = NULL;
27173 goto type_validation;
27177 * Validate against the declaration.
27179 ret = xmlSchemaValidateElemDecl(vctxt);
27180 if (ret != 0) {
27181 if (ret < 0) {
27182 VERROR_INT("xmlSchemaValidateElem",
27183 "calling xmlSchemaValidateElemDecl()");
27184 goto internal_error;
27186 goto exit;
27189 * Validate against the type definition.
27191 type_validation:
27193 if (vctxt->inode->typeDef == NULL) {
27194 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27195 ret = XML_SCHEMAV_CVC_TYPE_1;
27196 VERROR(ret, NULL,
27197 "The type definition is absent");
27198 goto exit;
27200 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
27201 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27202 ret = XML_SCHEMAV_CVC_TYPE_2;
27203 VERROR(ret, NULL,
27204 "The type definition is abstract");
27205 goto exit;
27208 * Evaluate IDCs. Do it here, since new IDC matchers are registered
27209 * during validation against the declaration. This must be done
27210 * _before_ attribute validation.
27212 if (vctxt->xpathStates != NULL) {
27213 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
27214 vctxt->inode->appliedXPath = 1;
27215 if (ret == -1) {
27216 VERROR_INT("xmlSchemaValidateElem",
27217 "calling xmlSchemaXPathEvaluate()");
27218 goto internal_error;
27222 * Validate attributes.
27224 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
27225 if ((vctxt->nbAttrInfos != 0) ||
27226 (vctxt->inode->typeDef->attrUses != NULL)) {
27228 ret = xmlSchemaVAttributesComplex(vctxt);
27230 } else if (vctxt->nbAttrInfos != 0) {
27232 ret = xmlSchemaVAttributesSimple(vctxt);
27235 * Clear registered attributes.
27237 if (vctxt->nbAttrInfos != 0)
27238 xmlSchemaClearAttrInfos(vctxt);
27239 if (ret == -1) {
27240 VERROR_INT("xmlSchemaValidateElem",
27241 "calling attributes validation");
27242 goto internal_error;
27245 * Don't return an error if attributes are invalid on purpose.
27247 ret = 0;
27249 exit:
27250 if (ret != 0)
27251 vctxt->skipDepth = vctxt->depth;
27252 return (ret);
27253 internal_error:
27254 return (-1);
27257 #ifdef XML_SCHEMA_READER_ENABLED
27258 static int
27259 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27261 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27262 int depth, nodeType, ret = 0, consumed;
27263 xmlSchemaNodeInfoPtr ielem;
27265 vctxt->depth = -1;
27266 ret = xmlTextReaderRead(vctxt->reader);
27268 * Move to the document element.
27270 while (ret == 1) {
27271 nodeType = xmlTextReaderNodeType(vctxt->reader);
27272 if (nodeType == XML_ELEMENT_NODE)
27273 goto root_found;
27274 ret = xmlTextReaderRead(vctxt->reader);
27276 goto exit;
27278 root_found:
27280 do {
27281 depth = xmlTextReaderDepth(vctxt->reader);
27282 nodeType = xmlTextReaderNodeType(vctxt->reader);
27284 if (nodeType == XML_ELEMENT_NODE) {
27286 vctxt->depth++;
27287 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27288 VERROR_INT("xmlSchemaVReaderWalk",
27289 "calling xmlSchemaValidatorPushElem()");
27290 goto internal_error;
27292 ielem = vctxt->inode;
27293 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27294 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27295 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27297 * Is the element empty?
27299 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27300 if (ret == -1) {
27301 VERROR_INT("xmlSchemaVReaderWalk",
27302 "calling xmlTextReaderIsEmptyElement()");
27303 goto internal_error;
27305 if (ret) {
27306 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27309 * Register attributes.
27311 vctxt->nbAttrInfos = 0;
27312 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27313 if (ret == -1) {
27314 VERROR_INT("xmlSchemaVReaderWalk",
27315 "calling xmlTextReaderMoveToFirstAttribute()");
27316 goto internal_error;
27318 if (ret == 1) {
27319 do {
27321 * VAL TODO: How do we know that the reader works on a
27322 * node tree, to be able to pass a node here?
27324 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27325 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27326 xmlTextReaderNamespaceUri(vctxt->reader), 1,
27327 xmlTextReaderValue(vctxt->reader), 1) == -1) {
27329 VERROR_INT("xmlSchemaVReaderWalk",
27330 "calling xmlSchemaValidatorPushAttribute()");
27331 goto internal_error;
27333 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27334 if (ret == -1) {
27335 VERROR_INT("xmlSchemaVReaderWalk",
27336 "calling xmlTextReaderMoveToFirstAttribute()");
27337 goto internal_error;
27339 } while (ret == 1);
27341 * Back to element position.
27343 ret = xmlTextReaderMoveToElement(vctxt->reader);
27344 if (ret == -1) {
27345 VERROR_INT("xmlSchemaVReaderWalk",
27346 "calling xmlTextReaderMoveToElement()");
27347 goto internal_error;
27351 * Validate the element.
27353 ret= xmlSchemaValidateElem(vctxt);
27354 if (ret != 0) {
27355 if (ret == -1) {
27356 VERROR_INT("xmlSchemaVReaderWalk",
27357 "calling xmlSchemaValidateElem()");
27358 goto internal_error;
27360 goto exit;
27362 if (vctxt->depth == vctxt->skipDepth) {
27363 int curDepth;
27365 * Skip all content.
27367 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27368 ret = xmlTextReaderRead(vctxt->reader);
27369 curDepth = xmlTextReaderDepth(vctxt->reader);
27370 while ((ret == 1) && (curDepth != depth)) {
27371 ret = xmlTextReaderRead(vctxt->reader);
27372 curDepth = xmlTextReaderDepth(vctxt->reader);
27374 if (ret < 0) {
27376 * VAL TODO: A reader error occurred; what to do here?
27378 ret = 1;
27379 goto exit;
27382 goto leave_elem;
27385 * READER VAL TODO: Is an END_ELEM really never called
27386 * if the elem is empty?
27388 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27389 goto leave_elem;
27390 } else if (nodeType == END_ELEM) {
27392 * Process END of element.
27394 leave_elem:
27395 ret = xmlSchemaValidatorPopElem(vctxt);
27396 if (ret != 0) {
27397 if (ret < 0) {
27398 VERROR_INT("xmlSchemaVReaderWalk",
27399 "calling xmlSchemaValidatorPopElem()");
27400 goto internal_error;
27402 goto exit;
27404 if (vctxt->depth >= 0)
27405 ielem = vctxt->inode;
27406 else
27407 ielem = NULL;
27408 } else if ((nodeType == XML_TEXT_NODE) ||
27409 (nodeType == XML_CDATA_SECTION_NODE) ||
27410 (nodeType == WHTSP) ||
27411 (nodeType == SIGN_WHTSP)) {
27413 * Process character content.
27415 xmlChar *value;
27417 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27418 nodeType = XML_TEXT_NODE;
27420 value = xmlTextReaderValue(vctxt->reader);
27421 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27422 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27423 if (! consumed)
27424 xmlFree(value);
27425 if (ret == -1) {
27426 VERROR_INT("xmlSchemaVReaderWalk",
27427 "calling xmlSchemaVPushText()");
27428 goto internal_error;
27430 } else if ((nodeType == XML_ENTITY_NODE) ||
27431 (nodeType == XML_ENTITY_REF_NODE)) {
27433 * VAL TODO: What to do with entities?
27435 TODO
27438 * Read next node.
27440 ret = xmlTextReaderRead(vctxt->reader);
27441 } while (ret == 1);
27443 exit:
27444 return (ret);
27445 internal_error:
27446 return (-1);
27448 #endif
27450 /************************************************************************
27452 * SAX validation handlers *
27454 ************************************************************************/
27457 * Process text content.
27459 static void
27460 xmlSchemaSAXHandleText(void *ctx,
27461 const xmlChar * ch,
27462 int len)
27464 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27466 if (vctxt->depth < 0)
27467 return;
27468 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27469 return;
27470 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27471 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27472 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27473 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27474 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27475 "calling xmlSchemaVPushText()");
27476 vctxt->err = -1;
27477 xmlStopParser(vctxt->parserCtxt);
27482 * Process CDATA content.
27484 static void
27485 xmlSchemaSAXHandleCDataSection(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_CDATA_SECTION_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);
27506 static void
27507 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27508 const xmlChar * name ATTRIBUTE_UNUSED)
27510 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27512 if (vctxt->depth < 0)
27513 return;
27514 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27515 return;
27516 /* SAX VAL TODO: What to do here? */
27517 TODO
27520 static void
27521 xmlSchemaSAXHandleStartElementNs(void *ctx,
27522 const xmlChar * localname,
27523 const xmlChar * prefix ATTRIBUTE_UNUSED,
27524 const xmlChar * URI,
27525 int nb_namespaces,
27526 const xmlChar ** namespaces,
27527 int nb_attributes,
27528 int nb_defaulted ATTRIBUTE_UNUSED,
27529 const xmlChar ** attributes)
27531 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27532 int ret;
27533 xmlSchemaNodeInfoPtr ielem;
27534 int i, j;
27537 * SAX VAL TODO: What to do with nb_defaulted?
27540 * Skip elements if inside a "skip" wildcard or invalid.
27542 vctxt->depth++;
27543 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27544 return;
27546 * Push the element.
27548 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27549 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27550 "calling xmlSchemaValidatorPushElem()");
27551 goto internal_error;
27553 ielem = vctxt->inode;
27555 * TODO: Is this OK?
27557 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27558 ielem->localName = localname;
27559 ielem->nsName = URI;
27560 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27562 * Register namespaces on the elem info.
27564 if (nb_namespaces != 0) {
27566 * Although the parser builds its own namespace list,
27567 * we have no access to it, so we'll use an own one.
27569 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27571 * Store prefix and namespace name.
27573 if (ielem->nsBindings == NULL) {
27574 ielem->nsBindings =
27575 (const xmlChar **) xmlMalloc(10 *
27576 sizeof(const xmlChar *));
27577 if (ielem->nsBindings == NULL) {
27578 xmlSchemaVErrMemory(vctxt,
27579 "allocating namespace bindings for SAX validation",
27580 NULL);
27581 goto internal_error;
27583 ielem->nbNsBindings = 0;
27584 ielem->sizeNsBindings = 5;
27585 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27586 ielem->sizeNsBindings *= 2;
27587 ielem->nsBindings =
27588 (const xmlChar **) xmlRealloc(
27589 (void *) ielem->nsBindings,
27590 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27591 if (ielem->nsBindings == NULL) {
27592 xmlSchemaVErrMemory(vctxt,
27593 "re-allocating namespace bindings for SAX validation",
27594 NULL);
27595 goto internal_error;
27599 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27600 if (namespaces[j+1][0] == 0) {
27602 * Handle xmlns="".
27604 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27605 } else
27606 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27607 namespaces[j+1];
27608 ielem->nbNsBindings++;
27612 * Register attributes.
27613 * SAX VAL TODO: We are not adding namespace declaration
27614 * attributes yet.
27616 if (nb_attributes != 0) {
27617 int valueLen, k, l;
27618 xmlChar *value;
27620 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27622 * Duplicate the value, changing any &#38; to a literal ampersand.
27624 * libxml2 differs from normal SAX here in that it escapes all ampersands
27625 * as &#38; instead of delivering the raw converted string. Changing the
27626 * behavior at this point would break applications that use this API, so
27627 * we are forced to work around it.
27629 valueLen = attributes[j+4] - attributes[j+3];
27630 value = xmlMallocAtomic(valueLen + 1);
27631 if (value == NULL) {
27632 xmlSchemaVErrMemory(vctxt,
27633 "allocating string for decoded attribute",
27634 NULL);
27635 goto internal_error;
27637 for (k = 0, l = 0; k < valueLen; l++) {
27638 if (k < valueLen - 4 &&
27639 attributes[j+3][k+0] == '&' &&
27640 attributes[j+3][k+1] == '#' &&
27641 attributes[j+3][k+2] == '3' &&
27642 attributes[j+3][k+3] == '8' &&
27643 attributes[j+3][k+4] == ';') {
27644 value[l] = '&';
27645 k += 5;
27646 } else {
27647 value[l] = attributes[j+3][k];
27648 k++;
27651 value[l] = '\0';
27653 * TODO: Set the node line.
27655 ret = xmlSchemaValidatorPushAttribute(vctxt,
27656 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27657 value, 1);
27658 if (ret == -1) {
27659 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27660 "calling xmlSchemaValidatorPushAttribute()");
27661 goto internal_error;
27666 * Validate the element.
27668 ret = xmlSchemaValidateElem(vctxt);
27669 if (ret != 0) {
27670 if (ret == -1) {
27671 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27672 "calling xmlSchemaValidateElem()");
27673 goto internal_error;
27675 goto exit;
27678 exit:
27679 return;
27680 internal_error:
27681 vctxt->err = -1;
27682 xmlStopParser(vctxt->parserCtxt);
27683 return;
27686 static void
27687 xmlSchemaSAXHandleEndElementNs(void *ctx,
27688 const xmlChar * localname ATTRIBUTE_UNUSED,
27689 const xmlChar * prefix ATTRIBUTE_UNUSED,
27690 const xmlChar * URI ATTRIBUTE_UNUSED)
27692 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27693 int res;
27696 * Skip elements if inside a "skip" wildcard or if invalid.
27698 if (vctxt->skipDepth != -1) {
27699 if (vctxt->depth > vctxt->skipDepth) {
27700 vctxt->depth--;
27701 return;
27702 } else
27703 vctxt->skipDepth = -1;
27706 * SAX VAL TODO: Just a temporary check.
27708 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27709 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27710 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27711 "elem pop mismatch");
27713 res = xmlSchemaValidatorPopElem(vctxt);
27714 if (res != 0) {
27715 if (res < 0) {
27716 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27717 "calling xmlSchemaValidatorPopElem()");
27718 goto internal_error;
27720 goto exit;
27722 exit:
27723 return;
27724 internal_error:
27725 vctxt->err = -1;
27726 xmlStopParser(vctxt->parserCtxt);
27727 return;
27730 /************************************************************************
27732 * Validation interfaces *
27734 ************************************************************************/
27737 * xmlSchemaNewValidCtxt:
27738 * @schema: a precompiled XML Schemas
27740 * Create an XML Schemas validation context based on the given schema.
27742 * Returns the validation context or NULL in case of error
27744 xmlSchemaValidCtxtPtr
27745 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27747 xmlSchemaValidCtxtPtr ret;
27749 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27750 if (ret == NULL) {
27751 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27752 return (NULL);
27754 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27755 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27756 ret->dict = xmlDictCreate();
27757 ret->nodeQNames = xmlSchemaItemListCreate();
27758 ret->schema = schema;
27759 return (ret);
27763 * xmlSchemaValidateSetFilename:
27764 * @vctxt: the schema validation context
27765 * @filename: the file name
27767 * Workaround to provide file error reporting information when this is
27768 * not provided by current APIs
27770 void
27771 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27772 if (vctxt == NULL)
27773 return;
27774 if (vctxt->filename != NULL)
27775 xmlFree(vctxt->filename);
27776 if (filename != NULL)
27777 vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27778 else
27779 vctxt->filename = NULL;
27783 * xmlSchemaClearValidCtxt:
27784 * @vctxt: the schema validation context
27786 * Free the resources associated to the schema validation context;
27787 * leaves some fields alive intended for reuse of the context.
27789 static void
27790 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27792 if (vctxt == NULL)
27793 return;
27796 * TODO: Should we clear the flags?
27797 * Might be problematic if one reuses the context
27798 * and assumes that the options remain the same.
27800 vctxt->flags = 0;
27801 vctxt->validationRoot = NULL;
27802 vctxt->doc = NULL;
27803 #ifdef LIBXML_READER_ENABLED
27804 vctxt->reader = NULL;
27805 #endif
27806 vctxt->hasKeyrefs = 0;
27808 if (vctxt->value != NULL) {
27809 xmlSchemaFreeValue(vctxt->value);
27810 vctxt->value = NULL;
27813 * Augmented IDC information.
27815 if (vctxt->aidcs != NULL) {
27816 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27817 do {
27818 next = cur->next;
27819 xmlFree(cur);
27820 cur = next;
27821 } while (cur != NULL);
27822 vctxt->aidcs = NULL;
27825 if (vctxt->idcNodes != NULL) {
27826 int i;
27827 xmlSchemaPSVIIDCNodePtr item;
27829 for (i = 0; i < vctxt->nbIdcNodes; i++) {
27830 item = vctxt->idcNodes[i];
27831 xmlFree(item->keys);
27832 xmlFree(item);
27834 xmlFree(vctxt->idcNodes);
27835 vctxt->idcNodes = NULL;
27836 vctxt->nbIdcNodes = 0;
27837 vctxt->sizeIdcNodes = 0;
27840 if (vctxt->idcKeys != NULL) {
27841 int i;
27842 for (i = 0; i < vctxt->nbIdcKeys; i++)
27843 xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27844 xmlFree(vctxt->idcKeys);
27845 vctxt->idcKeys = NULL;
27846 vctxt->nbIdcKeys = 0;
27847 vctxt->sizeIdcKeys = 0;
27851 * Note that we won't delete the XPath state pool here.
27853 if (vctxt->xpathStates != NULL) {
27854 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27855 vctxt->xpathStates = NULL;
27858 * Attribute info.
27860 if (vctxt->nbAttrInfos != 0) {
27861 xmlSchemaClearAttrInfos(vctxt);
27864 * Element info.
27866 if (vctxt->elemInfos != NULL) {
27867 int i;
27868 xmlSchemaNodeInfoPtr ei;
27870 for (i = 0; i < vctxt->sizeElemInfos; i++) {
27871 ei = vctxt->elemInfos[i];
27872 if (ei == NULL)
27873 break;
27874 xmlSchemaClearElemInfo(vctxt, ei);
27877 xmlSchemaItemListClear(vctxt->nodeQNames);
27878 /* Recreate the dict. */
27879 xmlDictFree(vctxt->dict);
27881 * TODO: Is is save to recreate it? Do we have a scenario
27882 * where the user provides the dict?
27884 vctxt->dict = xmlDictCreate();
27886 if (vctxt->filename != NULL) {
27887 xmlFree(vctxt->filename);
27888 vctxt->filename = NULL;
27892 * Note that some cleanup functions can move items to the cache,
27893 * so the cache shouldn't be freed too early.
27895 if (vctxt->idcMatcherCache != NULL) {
27896 xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27898 while (matcher) {
27899 tmp = matcher;
27900 matcher = matcher->nextCached;
27901 xmlSchemaIDCFreeMatcherList(tmp);
27903 vctxt->idcMatcherCache = NULL;
27908 * xmlSchemaFreeValidCtxt:
27909 * @ctxt: the schema validation context
27911 * Free the resources associated to the schema validation context
27913 void
27914 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27916 if (ctxt == NULL)
27917 return;
27918 if (ctxt->value != NULL)
27919 xmlSchemaFreeValue(ctxt->value);
27920 if (ctxt->pctxt != NULL)
27921 xmlSchemaFreeParserCtxt(ctxt->pctxt);
27922 if (ctxt->idcNodes != NULL) {
27923 int i;
27924 xmlSchemaPSVIIDCNodePtr item;
27926 for (i = 0; i < ctxt->nbIdcNodes; i++) {
27927 item = ctxt->idcNodes[i];
27928 xmlFree(item->keys);
27929 xmlFree(item);
27931 xmlFree(ctxt->idcNodes);
27933 if (ctxt->idcKeys != NULL) {
27934 int i;
27935 for (i = 0; i < ctxt->nbIdcKeys; i++)
27936 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27937 xmlFree(ctxt->idcKeys);
27940 if (ctxt->xpathStates != NULL) {
27941 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27942 ctxt->xpathStates = NULL;
27944 if (ctxt->xpathStatePool != NULL) {
27945 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27946 ctxt->xpathStatePool = NULL;
27950 * Augmented IDC information.
27952 if (ctxt->aidcs != NULL) {
27953 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27954 do {
27955 next = cur->next;
27956 xmlFree(cur);
27957 cur = next;
27958 } while (cur != NULL);
27960 if (ctxt->attrInfos != NULL) {
27961 int i;
27962 xmlSchemaAttrInfoPtr attr;
27964 /* Just a paranoid call to the cleanup. */
27965 if (ctxt->nbAttrInfos != 0)
27966 xmlSchemaClearAttrInfos(ctxt);
27967 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27968 attr = ctxt->attrInfos[i];
27969 xmlFree(attr);
27971 xmlFree(ctxt->attrInfos);
27973 if (ctxt->elemInfos != NULL) {
27974 int i;
27975 xmlSchemaNodeInfoPtr ei;
27977 for (i = 0; i < ctxt->sizeElemInfos; i++) {
27978 ei = ctxt->elemInfos[i];
27979 if (ei == NULL)
27980 break;
27981 xmlSchemaClearElemInfo(ctxt, ei);
27982 xmlFree(ei);
27984 xmlFree(ctxt->elemInfos);
27986 if (ctxt->nodeQNames != NULL)
27987 xmlSchemaItemListFree(ctxt->nodeQNames);
27988 if (ctxt->dict != NULL)
27989 xmlDictFree(ctxt->dict);
27990 if (ctxt->filename != NULL)
27991 xmlFree(ctxt->filename);
27992 xmlFree(ctxt);
27996 * xmlSchemaIsValid:
27997 * @ctxt: the schema validation context
27999 * Check if any error was detected during validation.
28001 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
28002 * of internal error.
28005 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
28007 if (ctxt == NULL)
28008 return(-1);
28009 return(ctxt->err == 0);
28013 * xmlSchemaSetValidErrors:
28014 * @ctxt: a schema validation context
28015 * @err: the error function
28016 * @warn: the warning function
28017 * @ctx: the functions context
28019 * Set the error and warning callback information
28021 void
28022 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
28023 xmlSchemaValidityErrorFunc err,
28024 xmlSchemaValidityWarningFunc warn, void *ctx)
28026 if (ctxt == NULL)
28027 return;
28028 ctxt->error = err;
28029 ctxt->warning = warn;
28030 ctxt->errCtxt = ctx;
28031 if (ctxt->pctxt != NULL)
28032 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
28036 * xmlSchemaSetValidStructuredErrors:
28037 * @ctxt: a schema validation context
28038 * @serror: the structured error function
28039 * @ctx: the functions context
28041 * Set the structured error callback
28043 void
28044 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
28045 xmlStructuredErrorFunc serror, void *ctx)
28047 if (ctxt == NULL)
28048 return;
28049 ctxt->serror = serror;
28050 ctxt->error = NULL;
28051 ctxt->warning = NULL;
28052 ctxt->errCtxt = ctx;
28053 if (ctxt->pctxt != NULL)
28054 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
28058 * xmlSchemaGetValidErrors:
28059 * @ctxt: a XML-Schema validation context
28060 * @err: the error function result
28061 * @warn: the warning function result
28062 * @ctx: the functions context result
28064 * Get the error and warning callback information
28066 * Returns -1 in case of error and 0 otherwise
28069 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
28070 xmlSchemaValidityErrorFunc * err,
28071 xmlSchemaValidityWarningFunc * warn, void **ctx)
28073 if (ctxt == NULL)
28074 return (-1);
28075 if (err != NULL)
28076 *err = ctxt->error;
28077 if (warn != NULL)
28078 *warn = ctxt->warning;
28079 if (ctx != NULL)
28080 *ctx = ctxt->errCtxt;
28081 return (0);
28086 * xmlSchemaSetValidOptions:
28087 * @ctxt: a schema validation context
28088 * @options: a combination of xmlSchemaValidOption
28090 * Sets the options to be used during the validation.
28092 * Returns 0 in case of success, -1 in case of an
28093 * API error.
28096 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
28097 int options)
28100 int i;
28102 if (ctxt == NULL)
28103 return (-1);
28105 * WARNING: Change the start value if adding to the
28106 * xmlSchemaValidOption.
28107 * TODO: Is there an other, more easy to maintain,
28108 * way?
28110 for (i = 1; i < (int) sizeof(int) * 8; i++) {
28111 if (options & 1<<i)
28112 return (-1);
28114 ctxt->options = options;
28115 return (0);
28119 * xmlSchemaValidCtxtGetOptions:
28120 * @ctxt: a schema validation context
28122 * Get the validation context options.
28124 * Returns the option combination or -1 on error.
28127 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
28130 if (ctxt == NULL)
28131 return (-1);
28132 else
28133 return (ctxt->options);
28136 static int
28137 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
28139 xmlAttrPtr attr;
28140 int ret = 0;
28141 xmlSchemaNodeInfoPtr ielem = NULL;
28142 xmlNodePtr node, valRoot;
28143 const xmlChar *nsName;
28145 /* DOC VAL TODO: Move this to the start function. */
28146 if (vctxt->validationRoot != NULL)
28147 valRoot = vctxt->validationRoot;
28148 else
28149 valRoot = xmlDocGetRootElement(vctxt->doc);
28150 if (valRoot == NULL) {
28151 /* VAL TODO: Error code? */
28152 VERROR(1, NULL, "The document has no document element");
28153 return (1);
28155 vctxt->depth = -1;
28156 vctxt->validationRoot = valRoot;
28157 node = valRoot;
28158 while (node != NULL) {
28159 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
28160 goto next_sibling;
28161 if (node->type == XML_ELEMENT_NODE) {
28164 * Init the node-info.
28166 vctxt->depth++;
28167 if (xmlSchemaValidatorPushElem(vctxt) == -1)
28168 goto internal_error;
28169 ielem = vctxt->inode;
28170 ielem->node = node;
28171 ielem->nodeLine = node->line;
28172 ielem->localName = node->name;
28173 if (node->ns != NULL)
28174 ielem->nsName = node->ns->href;
28175 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
28177 * Register attributes.
28178 * DOC VAL TODO: We do not register namespace declaration
28179 * attributes yet.
28181 vctxt->nbAttrInfos = 0;
28182 if (node->properties != NULL) {
28183 attr = node->properties;
28184 do {
28185 if (attr->ns != NULL)
28186 nsName = attr->ns->href;
28187 else
28188 nsName = NULL;
28189 ret = xmlSchemaValidatorPushAttribute(vctxt,
28190 (xmlNodePtr) attr,
28192 * Note that we give it the line number of the
28193 * parent element.
28195 ielem->nodeLine,
28196 attr->name, nsName, 0,
28197 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
28198 if (ret == -1) {
28199 VERROR_INT("xmlSchemaDocWalk",
28200 "calling xmlSchemaValidatorPushAttribute()");
28201 goto internal_error;
28203 attr = attr->next;
28204 } while (attr);
28207 * Validate the element.
28209 ret = xmlSchemaValidateElem(vctxt);
28210 if (ret != 0) {
28211 if (ret == -1) {
28212 VERROR_INT("xmlSchemaDocWalk",
28213 "calling xmlSchemaValidateElem()");
28214 goto internal_error;
28217 * Don't stop validation; just skip the content
28218 * of this element.
28220 goto leave_node;
28222 if ((vctxt->skipDepth != -1) &&
28223 (vctxt->depth >= vctxt->skipDepth))
28224 goto leave_node;
28225 } else if ((node->type == XML_TEXT_NODE) ||
28226 (node->type == XML_CDATA_SECTION_NODE)) {
28228 * Process character content.
28230 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
28231 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
28232 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
28233 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
28234 if (ret < 0) {
28235 VERROR_INT("xmlSchemaVDocWalk",
28236 "calling xmlSchemaVPushText()");
28237 goto internal_error;
28240 * DOC VAL TODO: Should we skip further validation of the
28241 * element content here?
28243 } else if ((node->type == XML_ENTITY_NODE) ||
28244 (node->type == XML_ENTITY_REF_NODE)) {
28246 * DOC VAL TODO: What to do with entities?
28248 VERROR_INT("xmlSchemaVDocWalk",
28249 "there is at least one entity reference in the node-tree "
28250 "currently being validated. Processing of entities with "
28251 "this XML Schema processor is not supported (yet). Please "
28252 "substitute entities before validation.");
28253 goto internal_error;
28254 } else {
28255 goto leave_node;
28257 * DOC VAL TODO: XInclude nodes, etc.
28261 * Walk the doc.
28263 if (node->children != NULL) {
28264 node = node->children;
28265 continue;
28267 leave_node:
28268 if (node->type == XML_ELEMENT_NODE) {
28270 * Leaving the scope of an element.
28272 if (node != vctxt->inode->node) {
28273 VERROR_INT("xmlSchemaVDocWalk",
28274 "element position mismatch");
28275 goto internal_error;
28277 ret = xmlSchemaValidatorPopElem(vctxt);
28278 if (ret != 0) {
28279 if (ret < 0) {
28280 VERROR_INT("xmlSchemaVDocWalk",
28281 "calling xmlSchemaValidatorPopElem()");
28282 goto internal_error;
28285 if (node == valRoot)
28286 goto exit;
28288 next_sibling:
28289 if (node->next != NULL)
28290 node = node->next;
28291 else {
28292 node = node->parent;
28293 goto leave_node;
28297 exit:
28298 return (ret);
28299 internal_error:
28300 return (-1);
28303 static int
28304 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28306 * Some initialization.
28308 vctxt->err = 0;
28309 vctxt->nberrors = 0;
28310 vctxt->depth = -1;
28311 vctxt->skipDepth = -1;
28312 vctxt->hasKeyrefs = 0;
28313 #ifdef ENABLE_IDC_NODE_TABLES_TEST
28314 vctxt->createIDCNodeTables = 1;
28315 #else
28316 vctxt->createIDCNodeTables = 0;
28317 #endif
28319 * Create a schema + parser if necessary.
28321 if (vctxt->schema == NULL) {
28322 xmlSchemaParserCtxtPtr pctxt;
28324 vctxt->xsiAssemble = 1;
28326 * If not schema was given then we will create a schema
28327 * dynamically using XSI schema locations.
28329 * Create the schema parser context.
28331 if ((vctxt->pctxt == NULL) &&
28332 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28333 return (-1);
28334 pctxt = vctxt->pctxt;
28335 pctxt->xsiAssemble = 1;
28337 * Create the schema.
28339 vctxt->schema = xmlSchemaNewSchema(pctxt);
28340 if (vctxt->schema == NULL)
28341 return (-1);
28343 * Create the schema construction context.
28345 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28346 if (pctxt->constructor == NULL)
28347 return(-1);
28348 pctxt->constructor->mainSchema = vctxt->schema;
28350 * Take ownership of the constructor to be able to free it.
28352 pctxt->ownsConstructor = 1;
28355 * Augment the IDC definitions for the main schema and all imported ones
28356 * NOTE: main schema if the first in the imported list
28358 xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28359 vctxt);
28361 return(0);
28364 static void
28365 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28366 if (vctxt->xsiAssemble) {
28367 if (vctxt->schema != NULL) {
28368 xmlSchemaFree(vctxt->schema);
28369 vctxt->schema = NULL;
28372 xmlSchemaClearValidCtxt(vctxt);
28375 static int
28376 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28378 int ret = 0;
28380 if (xmlSchemaPreRun(vctxt) < 0)
28381 return(-1);
28383 if (vctxt->doc != NULL) {
28385 * Tree validation.
28387 ret = xmlSchemaVDocWalk(vctxt);
28388 #ifdef LIBXML_READER_ENABLED
28389 } else if (vctxt->reader != NULL) {
28391 * XML Reader validation.
28393 #ifdef XML_SCHEMA_READER_ENABLED
28394 ret = xmlSchemaVReaderWalk(vctxt);
28395 #endif
28396 #endif
28397 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28399 * SAX validation.
28401 ret = xmlParseDocument(vctxt->parserCtxt);
28402 } else {
28403 VERROR_INT("xmlSchemaVStart",
28404 "no instance to validate");
28405 ret = -1;
28408 xmlSchemaPostRun(vctxt);
28409 if (ret == 0)
28410 ret = vctxt->err;
28411 return (ret);
28415 * xmlSchemaValidateOneElement:
28416 * @ctxt: a schema validation context
28417 * @elem: an element node
28419 * Validate a branch of a tree, starting with the given @elem.
28421 * Returns 0 if the element and its subtree is valid, a positive error
28422 * code number otherwise and -1 in case of an internal or API error.
28425 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28427 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28428 return (-1);
28430 if (ctxt->schema == NULL)
28431 return (-1);
28433 ctxt->doc = elem->doc;
28434 ctxt->node = elem;
28435 ctxt->validationRoot = elem;
28436 return(xmlSchemaVStart(ctxt));
28440 * xmlSchemaValidateDoc:
28441 * @ctxt: a schema validation context
28442 * @doc: a parsed document tree
28444 * Validate a document tree in memory.
28446 * Returns 0 if the document is schemas valid, a positive error code
28447 * number otherwise and -1 in case of internal or API error.
28450 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28452 if ((ctxt == NULL) || (doc == NULL))
28453 return (-1);
28455 ctxt->doc = doc;
28456 ctxt->node = xmlDocGetRootElement(doc);
28457 if (ctxt->node == NULL) {
28458 xmlSchemaCustomErr(ACTXT_CAST ctxt,
28459 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28460 (xmlNodePtr) doc, NULL,
28461 "The document has no document element", NULL, NULL);
28462 return (ctxt->err);
28464 ctxt->validationRoot = ctxt->node;
28465 return (xmlSchemaVStart(ctxt));
28469 /************************************************************************
28471 * Function and data for SAX streaming API *
28473 ************************************************************************/
28474 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28475 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28477 struct _xmlSchemaSplitSAXData {
28478 xmlSAXHandlerPtr user_sax;
28479 void *user_data;
28480 xmlSchemaValidCtxtPtr ctxt;
28481 xmlSAXHandlerPtr schemas_sax;
28484 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28486 struct _xmlSchemaSAXPlug {
28487 unsigned int magic;
28489 /* the original callbacks information */
28490 xmlSAXHandlerPtr *user_sax_ptr;
28491 xmlSAXHandlerPtr user_sax;
28492 void **user_data_ptr;
28493 void *user_data;
28495 /* the block plugged back and validation information */
28496 xmlSAXHandler schemas_sax;
28497 xmlSchemaValidCtxtPtr ctxt;
28500 /* All those functions just bounces to the user provided SAX handlers */
28501 static void
28502 internalSubsetSplit(void *ctx, const xmlChar *name,
28503 const xmlChar *ExternalID, const xmlChar *SystemID)
28505 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28506 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28507 (ctxt->user_sax->internalSubset != NULL))
28508 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28509 SystemID);
28512 static int
28513 isStandaloneSplit(void *ctx)
28515 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28516 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28517 (ctxt->user_sax->isStandalone != NULL))
28518 return(ctxt->user_sax->isStandalone(ctxt->user_data));
28519 return(0);
28522 static int
28523 hasInternalSubsetSplit(void *ctx)
28525 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28526 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28527 (ctxt->user_sax->hasInternalSubset != NULL))
28528 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28529 return(0);
28532 static int
28533 hasExternalSubsetSplit(void *ctx)
28535 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28536 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28537 (ctxt->user_sax->hasExternalSubset != NULL))
28538 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28539 return(0);
28542 static void
28543 externalSubsetSplit(void *ctx, const xmlChar *name,
28544 const xmlChar *ExternalID, const xmlChar *SystemID)
28546 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28547 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28548 (ctxt->user_sax->externalSubset != NULL))
28549 ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28550 SystemID);
28553 static xmlParserInputPtr
28554 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28556 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28557 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28558 (ctxt->user_sax->resolveEntity != NULL))
28559 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28560 systemId));
28561 return(NULL);
28564 static xmlEntityPtr
28565 getEntitySplit(void *ctx, const xmlChar *name)
28567 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28568 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28569 (ctxt->user_sax->getEntity != NULL))
28570 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28571 return(NULL);
28574 static xmlEntityPtr
28575 getParameterEntitySplit(void *ctx, const xmlChar *name)
28577 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28578 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28579 (ctxt->user_sax->getParameterEntity != NULL))
28580 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28581 return(NULL);
28585 static void
28586 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28587 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28589 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28590 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28591 (ctxt->user_sax->entityDecl != NULL))
28592 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28593 systemId, content);
28596 static void
28597 attributeDeclSplit(void *ctx, const xmlChar * elem,
28598 const xmlChar * name, int type, int def,
28599 const xmlChar * defaultValue, xmlEnumerationPtr tree)
28601 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28602 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28603 (ctxt->user_sax->attributeDecl != NULL)) {
28604 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28605 def, defaultValue, tree);
28606 } else {
28607 xmlFreeEnumeration(tree);
28611 static void
28612 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28613 xmlElementContentPtr content)
28615 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28616 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28617 (ctxt->user_sax->elementDecl != NULL))
28618 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28621 static void
28622 notationDeclSplit(void *ctx, const xmlChar *name,
28623 const xmlChar *publicId, const xmlChar *systemId)
28625 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28626 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28627 (ctxt->user_sax->notationDecl != NULL))
28628 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28629 systemId);
28632 static void
28633 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28634 const xmlChar *publicId, const xmlChar *systemId,
28635 const xmlChar *notationName)
28637 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28638 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28639 (ctxt->user_sax->unparsedEntityDecl != NULL))
28640 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28641 systemId, notationName);
28644 static void
28645 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28647 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28648 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28649 (ctxt->user_sax->setDocumentLocator != NULL))
28650 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28653 static void
28654 startDocumentSplit(void *ctx)
28656 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28657 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28658 (ctxt->user_sax->startDocument != NULL))
28659 ctxt->user_sax->startDocument(ctxt->user_data);
28662 static void
28663 endDocumentSplit(void *ctx)
28665 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28666 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28667 (ctxt->user_sax->endDocument != NULL))
28668 ctxt->user_sax->endDocument(ctxt->user_data);
28671 static void
28672 processingInstructionSplit(void *ctx, const xmlChar *target,
28673 const xmlChar *data)
28675 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28676 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28677 (ctxt->user_sax->processingInstruction != NULL))
28678 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28681 static void
28682 commentSplit(void *ctx, const xmlChar *value)
28684 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28685 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28686 (ctxt->user_sax->comment != NULL))
28687 ctxt->user_sax->comment(ctxt->user_data, value);
28691 * Varargs error callbacks to the user application, harder ...
28694 static void XMLCDECL
28695 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28696 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28697 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28698 (ctxt->user_sax->warning != NULL)) {
28699 TODO
28702 static void XMLCDECL
28703 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28704 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28705 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28706 (ctxt->user_sax->error != NULL)) {
28707 TODO
28710 static void XMLCDECL
28711 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28712 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28713 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28714 (ctxt->user_sax->fatalError != NULL)) {
28715 TODO
28720 * Those are function where both the user handler and the schemas handler
28721 * need to be called.
28723 static void
28724 charactersSplit(void *ctx, const xmlChar *ch, int len)
28726 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28727 if (ctxt == NULL)
28728 return;
28729 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28730 ctxt->user_sax->characters(ctxt->user_data, ch, len);
28731 if (ctxt->ctxt != NULL)
28732 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28735 static void
28736 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28738 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28739 if (ctxt == NULL)
28740 return;
28741 if ((ctxt->user_sax != NULL) &&
28742 (ctxt->user_sax->ignorableWhitespace != NULL))
28743 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28744 if (ctxt->ctxt != NULL)
28745 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28748 static void
28749 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28751 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28752 if (ctxt == NULL)
28753 return;
28754 if ((ctxt->user_sax != NULL) &&
28755 (ctxt->user_sax->cdataBlock != NULL))
28756 ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28757 if (ctxt->ctxt != NULL)
28758 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28761 static void
28762 referenceSplit(void *ctx, const xmlChar *name)
28764 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28765 if (ctxt == NULL)
28766 return;
28767 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28768 (ctxt->user_sax->reference != NULL))
28769 ctxt->user_sax->reference(ctxt->user_data, name);
28770 if (ctxt->ctxt != NULL)
28771 xmlSchemaSAXHandleReference(ctxt->user_data, name);
28774 static void
28775 startElementNsSplit(void *ctx, const xmlChar * localname,
28776 const xmlChar * prefix, const xmlChar * URI,
28777 int nb_namespaces, const xmlChar ** namespaces,
28778 int nb_attributes, int nb_defaulted,
28779 const xmlChar ** attributes) {
28780 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28781 if (ctxt == NULL)
28782 return;
28783 if ((ctxt->user_sax != NULL) &&
28784 (ctxt->user_sax->startElementNs != NULL))
28785 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28786 URI, nb_namespaces, namespaces,
28787 nb_attributes, nb_defaulted,
28788 attributes);
28789 if (ctxt->ctxt != NULL)
28790 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28791 URI, nb_namespaces, namespaces,
28792 nb_attributes, nb_defaulted,
28793 attributes);
28796 static void
28797 endElementNsSplit(void *ctx, const xmlChar * localname,
28798 const xmlChar * prefix, const xmlChar * URI) {
28799 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28800 if (ctxt == NULL)
28801 return;
28802 if ((ctxt->user_sax != NULL) &&
28803 (ctxt->user_sax->endElementNs != NULL))
28804 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28805 if (ctxt->ctxt != NULL)
28806 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28810 * xmlSchemaSAXPlug:
28811 * @ctxt: a schema validation context
28812 * @sax: a pointer to the original xmlSAXHandlerPtr
28813 * @user_data: a pointer to the original SAX user data pointer
28815 * Plug a SAX based validation layer in a SAX parsing event flow.
28816 * The original @saxptr and @dataptr data are replaced by new pointers
28817 * but the calls to the original will be maintained.
28819 * Returns a pointer to a data structure needed to unplug the validation layer
28820 * or NULL in case of errors.
28822 xmlSchemaSAXPlugPtr
28823 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28824 xmlSAXHandlerPtr *sax, void **user_data)
28826 xmlSchemaSAXPlugPtr ret;
28827 xmlSAXHandlerPtr old_sax;
28829 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28830 return(NULL);
28833 * We only allow to plug into SAX2 event streams
28835 old_sax = *sax;
28836 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28837 return(NULL);
28838 if ((old_sax != NULL) &&
28839 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28840 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28841 return(NULL);
28844 * everything seems right allocate the local data needed for that layer
28846 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28847 if (ret == NULL) {
28848 return(NULL);
28850 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28851 ret->magic = XML_SAX_PLUG_MAGIC;
28852 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28853 ret->ctxt = ctxt;
28854 ret->user_sax_ptr = sax;
28855 ret->user_sax = old_sax;
28856 if (old_sax == NULL) {
28858 * go direct, no need for the split block and functions.
28860 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28861 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28863 * Note that we use the same text-function for both, to prevent
28864 * the parser from testing for ignorable whitespace.
28866 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28867 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28869 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28870 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28872 ret->user_data = ctxt;
28873 *user_data = ctxt;
28874 } else {
28876 * for each callback unused by Schemas initialize it to the Split
28877 * routine only if non NULL in the user block, this can speed up
28878 * things at the SAX level.
28880 if (old_sax->internalSubset != NULL)
28881 ret->schemas_sax.internalSubset = internalSubsetSplit;
28882 if (old_sax->isStandalone != NULL)
28883 ret->schemas_sax.isStandalone = isStandaloneSplit;
28884 if (old_sax->hasInternalSubset != NULL)
28885 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28886 if (old_sax->hasExternalSubset != NULL)
28887 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28888 if (old_sax->resolveEntity != NULL)
28889 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28890 if (old_sax->getEntity != NULL)
28891 ret->schemas_sax.getEntity = getEntitySplit;
28892 if (old_sax->entityDecl != NULL)
28893 ret->schemas_sax.entityDecl = entityDeclSplit;
28894 if (old_sax->notationDecl != NULL)
28895 ret->schemas_sax.notationDecl = notationDeclSplit;
28896 if (old_sax->attributeDecl != NULL)
28897 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28898 if (old_sax->elementDecl != NULL)
28899 ret->schemas_sax.elementDecl = elementDeclSplit;
28900 if (old_sax->unparsedEntityDecl != NULL)
28901 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28902 if (old_sax->setDocumentLocator != NULL)
28903 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28904 if (old_sax->startDocument != NULL)
28905 ret->schemas_sax.startDocument = startDocumentSplit;
28906 if (old_sax->endDocument != NULL)
28907 ret->schemas_sax.endDocument = endDocumentSplit;
28908 if (old_sax->processingInstruction != NULL)
28909 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28910 if (old_sax->comment != NULL)
28911 ret->schemas_sax.comment = commentSplit;
28912 if (old_sax->warning != NULL)
28913 ret->schemas_sax.warning = warningSplit;
28914 if (old_sax->error != NULL)
28915 ret->schemas_sax.error = errorSplit;
28916 if (old_sax->fatalError != NULL)
28917 ret->schemas_sax.fatalError = fatalErrorSplit;
28918 if (old_sax->getParameterEntity != NULL)
28919 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28920 if (old_sax->externalSubset != NULL)
28921 ret->schemas_sax.externalSubset = externalSubsetSplit;
28924 * the 6 schemas callback have to go to the splitter functions
28925 * Note that we use the same text-function for ignorableWhitespace
28926 * if possible, to prevent the parser from testing for ignorable
28927 * whitespace.
28929 ret->schemas_sax.characters = charactersSplit;
28930 if ((old_sax->ignorableWhitespace != NULL) &&
28931 (old_sax->ignorableWhitespace != old_sax->characters))
28932 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28933 else
28934 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28935 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28936 ret->schemas_sax.reference = referenceSplit;
28937 ret->schemas_sax.startElementNs = startElementNsSplit;
28938 ret->schemas_sax.endElementNs = endElementNsSplit;
28940 ret->user_data_ptr = user_data;
28941 ret->user_data = *user_data;
28942 *user_data = ret;
28946 * plug the pointers back.
28948 *sax = &(ret->schemas_sax);
28949 ctxt->sax = *sax;
28950 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28951 xmlSchemaPreRun(ctxt);
28952 return(ret);
28956 * xmlSchemaSAXUnplug:
28957 * @plug: a data structure returned by xmlSchemaSAXPlug
28959 * Unplug a SAX based validation layer in a SAX parsing event flow.
28960 * The original pointers used in the call are restored.
28962 * Returns 0 in case of success and -1 in case of failure.
28965 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28967 xmlSAXHandlerPtr *sax;
28968 void **user_data;
28970 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28971 return(-1);
28972 plug->magic = 0;
28974 xmlSchemaPostRun(plug->ctxt);
28975 /* restore the data */
28976 sax = plug->user_sax_ptr;
28977 *sax = plug->user_sax;
28978 if (plug->user_sax != NULL) {
28979 user_data = plug->user_data_ptr;
28980 *user_data = plug->user_data;
28983 /* free and return */
28984 xmlFree(plug);
28985 return(0);
28989 * xmlSchemaValidateSetLocator:
28990 * @vctxt: a schema validation context
28991 * @f: the locator function pointer
28992 * @ctxt: the locator context
28994 * Allows to set a locator function to the validation context,
28995 * which will be used to provide file and line information since
28996 * those are not provided as part of the SAX validation flow
28997 * Setting @f to NULL disable the locator.
29000 void
29001 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
29002 xmlSchemaValidityLocatorFunc f,
29003 void *ctxt)
29005 if (vctxt == NULL) return;
29006 vctxt->locFunc = f;
29007 vctxt->locCtxt = ctxt;
29011 * xmlSchemaValidateStreamLocator:
29012 * @ctx: the xmlTextReaderPtr used
29013 * @file: returned file information
29014 * @line: returned line information
29016 * Internal locator function for the readers
29018 * Returns 0 in case the Schema validation could be (de)activated and
29019 * -1 in case of error.
29021 static int
29022 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
29023 unsigned long *line) {
29024 xmlParserCtxtPtr ctxt;
29026 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
29027 return(-1);
29029 if (file != NULL)
29030 *file = NULL;
29031 if (line != NULL)
29032 *line = 0;
29034 ctxt = (xmlParserCtxtPtr) ctx;
29035 if (ctxt->input != NULL) {
29036 if (file != NULL)
29037 *file = ctxt->input->filename;
29038 if (line != NULL)
29039 *line = ctxt->input->line;
29040 return(0);
29042 return(-1);
29046 * xmlSchemaValidateStream:
29047 * @ctxt: a schema validation context
29048 * @input: the input to use for reading the data
29049 * @enc: an optional encoding information
29050 * @sax: a SAX handler for the resulting events
29051 * @user_data: the context to provide to the SAX handler.
29053 * Validate an input based on a flow of SAX event from the parser
29054 * and forward the events to the @sax handler with the provided @user_data
29055 * the user provided @sax handler must be a SAX2 one.
29057 * Returns 0 if the document is schemas valid, a positive error code
29058 * number otherwise and -1 in case of internal or API error.
29061 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
29062 xmlParserInputBufferPtr input, xmlCharEncoding enc,
29063 xmlSAXHandlerPtr sax, void *user_data)
29065 xmlSchemaSAXPlugPtr plug = NULL;
29066 xmlSAXHandlerPtr old_sax = NULL;
29067 xmlParserCtxtPtr pctxt = NULL;
29068 xmlParserInputPtr inputStream = NULL;
29069 int ret;
29071 if ((ctxt == NULL) || (input == NULL))
29072 return (-1);
29075 * prepare the parser
29077 pctxt = xmlNewParserCtxt();
29078 if (pctxt == NULL)
29079 return (-1);
29080 old_sax = pctxt->sax;
29081 pctxt->sax = sax;
29082 pctxt->userData = user_data;
29083 #if 0
29084 if (options)
29085 xmlCtxtUseOptions(pctxt, options);
29086 #endif
29087 pctxt->linenumbers = 1;
29088 xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
29090 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
29091 if (inputStream == NULL) {
29092 ret = -1;
29093 goto done;
29095 inputPush(pctxt, inputStream);
29096 ctxt->parserCtxt = pctxt;
29097 ctxt->input = input;
29100 * Plug the validation and launch the parsing
29102 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
29103 if (plug == NULL) {
29104 ret = -1;
29105 goto done;
29107 ctxt->input = input;
29108 ctxt->enc = enc;
29109 ctxt->sax = pctxt->sax;
29110 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
29111 ret = xmlSchemaVStart(ctxt);
29113 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
29114 ret = ctxt->parserCtxt->errNo;
29115 if (ret == 0)
29116 ret = 1;
29119 done:
29120 ctxt->parserCtxt = NULL;
29121 ctxt->sax = NULL;
29122 ctxt->input = NULL;
29123 if (plug != NULL) {
29124 xmlSchemaSAXUnplug(plug);
29126 /* cleanup */
29127 if (pctxt != NULL) {
29128 pctxt->sax = old_sax;
29129 xmlFreeParserCtxt(pctxt);
29131 return (ret);
29135 * xmlSchemaValidateFile:
29136 * @ctxt: a schema validation context
29137 * @filename: the URI of the instance
29138 * @options: a future set of options, currently unused
29140 * Do a schemas validation of the given resource, it will use the
29141 * SAX streamable validation internally.
29143 * Returns 0 if the document is valid, a positive error code
29144 * number otherwise and -1 in case of an internal or API error.
29147 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
29148 const char * filename,
29149 int options ATTRIBUTE_UNUSED)
29151 int ret;
29152 xmlParserInputBufferPtr input;
29154 if ((ctxt == NULL) || (filename == NULL))
29155 return (-1);
29157 input = xmlParserInputBufferCreateFilename(filename,
29158 XML_CHAR_ENCODING_NONE);
29159 if (input == NULL)
29160 return (-1);
29161 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
29162 NULL, NULL);
29163 return (ret);
29167 * xmlSchemaValidCtxtGetParserCtxt:
29168 * @ctxt: a schema validation context
29170 * allow access to the parser context of the schema validation context
29172 * Returns the parser context of the schema validation context or NULL
29173 * in case of error.
29175 xmlParserCtxtPtr
29176 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
29178 if (ctxt == NULL)
29179 return(NULL);
29180 return (ctxt->parserCtxt);
29183 #endif /* LIBXML_SCHEMAS_ENABLED */