1 /*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <[email protected]>
8 */
9
10 /*
11 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
15 * - if we don't intend to use the schema for schemas, we
16 * need to validate all schema attributes (ref, type, name)
17 * against their types.
18 * - Eliminate item creation for: ??
19 *
20 * URGENT TODO:
21 * - For xsi-driven schema acquisition, augment the IDCs after every
22 * acquisition episode (xmlSchemaAugmentIDC).
23 *
24 * NOTES:
25 * - Eliminated item creation for: <restriction>, <extension>,
26 * <simpleContent>, <complexContent>, <list>, <union>
27 *
28 * PROBLEMS:
29 * - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30 * IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31 * XPath will have trouble to resolve to this namespace, since not known.
32 *
33 *
34 * CONSTRAINTS:
35 *
36 * Schema Component Constraint:
37 * All Group Limited (cos-all-limited)
38 * Status: complete
39 * (1.2)
40 * In xmlSchemaGroupDefReferenceTermFixup() and
41 * (2)
42 * In xmlSchemaParseModelGroup()
43 * TODO: Actually this should go to component-level checks,
44 * but is done here due to performance. Move it to an other layer
45 * is schema construction via an API is implemented.
46 */
47
48 /* To avoid EBCDIC trouble when parsing on zOS */
49 #if defined(__MVS__)
50 #pragma convert("ISO8859-1")
51 #endif
52
53 #define IN_LIBXML
54 #include "libxml.h"
55
56 #ifdef LIBXML_SCHEMAS_ENABLED
57
58 #include <string.h>
59 #include <libxml/xmlmemory.h>
60 #include <libxml/parser.h>
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
78
79 #include "private/error.h"
80 #include "private/string.h"
81
82 /* #define WXS_ELEM_DECL_CONS_ENABLED */
83
84 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
85
86 #define ENABLE_REDEFINE
87
88 /* #define ENABLE_NAMED_LOCALS */
89
90 /* #define ENABLE_IDC_NODE_TABLES_TEST */
91
92 #define DUMP_CONTENT_MODEL
93
94 #ifdef LIBXML_READER_ENABLED
95 /* #define XML_SCHEMA_READER_ENABLED */
96 #endif
97
98 #define UNBOUNDED (1 << 30)
99
100 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
101
102 /*
103 * The XML Schemas namespaces
104 */
105 static const xmlChar *xmlSchemaNs = (const xmlChar *)
106 "http://www.w3.org/2001/XMLSchema";
107
108 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
109 "http://www.w3.org/2001/XMLSchema-instance";
110
111 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
112 "http://www.w3.org/2000/xmlns/";
113
114 /*
115 * Come casting macros.
116 */
117 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
118 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
119 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
120 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
121 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
122 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
123 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
124 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
125 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
126 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
127 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
128 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
129 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
130 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
131 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
132 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
133 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
134
135 /*
136 * Macros to query common properties of components.
137 */
138 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
139
140 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
141 /*
142 * Macros for element declarations.
143 */
144 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
145
146 #define WXS_SUBST_HEAD(item) (item)->refDecl
147 /*
148 * Macros for attribute declarations.
149 */
150 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
151 /*
152 * Macros for attribute uses.
153 */
154 #define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
155
156 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
157
158 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
159
160 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
161 /*
162 * Macros for attribute groups.
163 */
164 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
165 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
166 /*
167 * Macros for particles.
168 */
169 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
170
171 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
172
173 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
174
175 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
176 /*
177 * Macros for model groups definitions.
178 */
179 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
180 /*
181 * Macros for model groups.
182 */
183 #define WXS_IS_MODEL_GROUP(i) \
184 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
185 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
186 ((i)->type == XML_SCHEMA_TYPE_ALL))
187
188 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
189 /*
190 * Macros for schema buckets.
191 */
192 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
193 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
194
195 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
196 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
197
198 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
199
200 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
201 /*
202 * Macros for complex/simple types.
203 */
204 #define WXS_IS_ANYTYPE(i) \
205 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
206 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
207
208 #define WXS_IS_COMPLEX(i) \
209 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
210 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
211
212 #define WXS_IS_SIMPLE(item) \
213 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
214 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
215 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
216
217 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
218 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
219 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
220
221 #define WXS_IS_RESTRICTION(t) \
222 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
223
224 #define WXS_IS_EXTENSION(t) \
225 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
226
227 #define WXS_IS_TYPE_NOT_FIXED(i) \
228 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
229 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
230
231 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
232 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
233 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
234
235 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
236
237 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
238 /*
239 * Macros for exclusively for complex types.
240 */
241 #define WXS_HAS_COMPLEX_CONTENT(item) \
242 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
243 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
244 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
245
246 #define WXS_HAS_SIMPLE_CONTENT(item) \
247 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
248 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
249
250 #define WXS_HAS_MIXED_CONTENT(item) \
251 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
252
253 #define WXS_EMPTIABLE(t) \
254 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
255
256 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
257
258 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
259
260 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
261 /*
262 * Macros for exclusively for simple types.
263 */
264 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
265
266 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
267
268 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
269
270 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
271 /*
272 * Misc parser context macros.
273 */
274 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
275
276 #define WXS_HAS_BUCKETS(ctx) \
277 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
278 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
279
280 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
281
282 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
283
284 #define WXS_SCHEMA(ctx) (ctx)->schema
285
286 #define WXS_ADD_LOCAL(ctx, item) \
287 do { \
288 if (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item) < 0) { \
289 xmlFree(item); \
290 item = NULL; \
291 } \
292 } while (0)
293
294 #define WXS_ADD_GLOBAL(ctx, item) \
295 do { \
296 if (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item) < 0) { \
297 xmlFree(item); \
298 item = NULL; \
299 } \
300 } while (0)
301
302 #define WXS_ADD_PENDING(ctx, item) \
303 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
304 /*
305 * xmlSchemaItemList macros.
306 */
307 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
308 /*
309 * Misc macros.
310 */
311 #define IS_SCHEMA(node, type) \
312 ((node != NULL) && (node->ns != NULL) && \
313 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
314 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
315
316 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
317
318 /*
319 * Since we put the default/fixed values into the dict, we can
320 * use pointer comparison for those values.
321 * REMOVED: (xmlStrEqual((v1), (v2)))
322 */
323 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
324
325 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
326
327 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
328
329 #define HFAILURE if (res == -1) goto exit_failure;
330
331 #define HERROR if (res != 0) goto exit_error;
332
333 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
334 /*
335 * Some flags used for various schema constraints.
336 */
337 #define SUBSET_RESTRICTION 1<<0
338 #define SUBSET_EXTENSION 1<<1
339 #define SUBSET_SUBSTITUTION 1<<2
340 #define SUBSET_LIST 1<<3
341 #define SUBSET_UNION 1<<4
342
343 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
344 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
345
346 typedef struct _xmlSchemaItemList xmlSchemaItemList;
347 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
348 struct _xmlSchemaItemList {
349 void **items; /* used for dynamic addition of schemata */
350 int nbItems; /* used for dynamic addition of schemata */
351 int sizeItems; /* used for dynamic addition of schemata */
352 };
353
354 #define XML_SCHEMA_CTXT_PARSER 1
355 #define XML_SCHEMA_CTXT_VALIDATOR 2
356
357 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
358 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
359 struct _xmlSchemaAbstractCtxt {
360 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
361 void *dummy; /* Fix alignment issues */
362 };
363
364 typedef struct _xmlSchemaBucket xmlSchemaBucket;
365 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
366
367 #define XML_SCHEMA_SCHEMA_MAIN 0
368 #define XML_SCHEMA_SCHEMA_IMPORT 1
369 #define XML_SCHEMA_SCHEMA_INCLUDE 2
370 #define XML_SCHEMA_SCHEMA_REDEFINE 3
371
372 /**
373 * xmlSchemaSchemaRelation:
374 *
375 * Used to create a graph of schema relationships.
376 */
377 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
378 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
379 struct _xmlSchemaSchemaRelation {
380 xmlSchemaSchemaRelationPtr next;
381 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
382 const xmlChar *importNamespace;
383 xmlSchemaBucketPtr bucket;
384 };
385
386 #define XML_SCHEMA_BUCKET_MARKED 1<<0
387 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
388
389 struct _xmlSchemaBucket {
390 int type;
391 int flags;
392 const xmlChar *schemaLocation;
393 const xmlChar *origTargetNamespace;
394 const xmlChar *targetNamespace;
395 xmlDocPtr doc;
396 xmlSchemaSchemaRelationPtr relations;
397 int located;
398 int parsed;
399 int imported;
400 int preserveDoc;
401 xmlSchemaItemListPtr globals; /* Global components. */
402 xmlSchemaItemListPtr locals; /* Local components. */
403 };
404
405 /**
406 * xmlSchemaImport:
407 * (extends xmlSchemaBucket)
408 *
409 * Reflects a schema. Holds some information
410 * about the schema and its toplevel components. Duplicate
411 * toplevel components are not checked at this level.
412 */
413 typedef struct _xmlSchemaImport xmlSchemaImport;
414 typedef xmlSchemaImport *xmlSchemaImportPtr;
415 struct _xmlSchemaImport {
416 int type; /* Main OR import OR include. */
417 int flags;
418 const xmlChar *schemaLocation; /* The URI of the schema document. */
419 /* For chameleon includes, @origTargetNamespace will be NULL */
420 const xmlChar *origTargetNamespace;
421 /*
422 * For chameleon includes, @targetNamespace will be the
423 * targetNamespace of the including schema.
424 */
425 const xmlChar *targetNamespace;
426 xmlDocPtr doc; /* The schema node-tree. */
427 /* @relations will hold any included/imported/redefined schemas. */
428 xmlSchemaSchemaRelationPtr relations;
429 int located;
430 int parsed;
431 int imported;
432 int preserveDoc;
433 xmlSchemaItemListPtr globals;
434 xmlSchemaItemListPtr locals;
435 /* The imported schema. */
436 xmlSchemaPtr schema;
437 };
438
439 /*
440 * (extends xmlSchemaBucket)
441 */
442 typedef struct _xmlSchemaInclude xmlSchemaInclude;
443 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
444 struct _xmlSchemaInclude {
445 int type;
446 int flags;
447 const xmlChar *schemaLocation;
448 const xmlChar *origTargetNamespace;
449 const xmlChar *targetNamespace;
450 xmlDocPtr doc;
451 xmlSchemaSchemaRelationPtr relations;
452 int located;
453 int parsed;
454 int imported;
455 int preserveDoc;
456 xmlSchemaItemListPtr globals; /* Global components. */
457 xmlSchemaItemListPtr locals; /* Local components. */
458
459 /* The owning main or import schema bucket. */
460 xmlSchemaImportPtr ownerImport;
461 };
462
463 /**
464 * xmlSchemaBasicItem:
465 *
466 * The abstract base type for schema components.
467 */
468 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
469 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
470 struct _xmlSchemaBasicItem {
471 xmlSchemaTypeType type;
472 void *dummy; /* Fix alignment issues */
473 };
474
475 /**
476 * xmlSchemaAnnotItem:
477 *
478 * The abstract base type for annotated schema components.
479 * (Extends xmlSchemaBasicItem)
480 */
481 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
482 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
483 struct _xmlSchemaAnnotItem {
484 xmlSchemaTypeType type;
485 xmlSchemaAnnotPtr annot;
486 };
487
488 /**
489 * xmlSchemaTreeItem:
490 *
491 * The abstract base type for tree-like structured schema components.
492 * (Extends xmlSchemaAnnotItem)
493 */
494 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
495 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
496 struct _xmlSchemaTreeItem {
497 xmlSchemaTypeType type;
498 xmlSchemaAnnotPtr annot;
499 xmlSchemaTreeItemPtr next;
500 xmlSchemaTreeItemPtr children;
501 };
502
503
504 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
505 /**
506 * xmlSchemaAttributeUsePtr:
507 *
508 * The abstract base type for tree-like structured schema components.
509 * (Extends xmlSchemaTreeItem)
510 */
511 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
512 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
513 struct _xmlSchemaAttributeUse {
514 xmlSchemaTypeType type;
515 xmlSchemaAnnotPtr annot;
516 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
517 /*
518 * The attr. decl. OR a QName-ref. to an attr. decl. OR
519 * a QName-ref. to an attribute group definition.
520 */
521 xmlSchemaAttributePtr attrDecl;
522
523 int flags;
524 xmlNodePtr node;
525 int occurs; /* required, optional */
526 const xmlChar * defValue;
527 xmlSchemaValPtr defVal;
528 };
529
530 /**
531 * xmlSchemaAttributeUseProhibPtr:
532 *
533 * A helper component to reflect attribute prohibitions.
534 * (Extends xmlSchemaBasicItem)
535 */
536 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
537 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
538 struct _xmlSchemaAttributeUseProhib {
539 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
540 xmlNodePtr node;
541 const xmlChar *name;
542 const xmlChar *targetNamespace;
543 int isRef;
544 };
545
546 /**
547 * xmlSchemaRedef:
548 */
549 typedef struct _xmlSchemaRedef xmlSchemaRedef;
550 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
551 struct _xmlSchemaRedef {
552 xmlSchemaRedefPtr next;
553 xmlSchemaBasicItemPtr item; /* The redefining component. */
554 xmlSchemaBasicItemPtr reference; /* The referencing component. */
555 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
556 const xmlChar *refName; /* The name of the to-be-redefined component. */
557 const xmlChar *refTargetNs; /* The target namespace of the
558 to-be-redefined comp. */
559 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
560 };
561
562 /**
563 * xmlSchemaConstructionCtxt:
564 */
565 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
566 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
567 struct _xmlSchemaConstructionCtxt {
568 xmlSchemaPtr mainSchema; /* The main schema. */
569 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
570 xmlDictPtr dict;
571 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
572 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
573 xmlSchemaBucketPtr bucket; /* The current schema bucket */
574 xmlSchemaItemListPtr pending; /* All Components of all schemas that
575 need to be fixed. */
576 xmlHashTablePtr substGroups;
577 xmlSchemaRedefPtr redefs;
578 xmlSchemaRedefPtr lastRedef;
579 };
580
581 #define XML_SCHEMAS_PARSE_ERROR 1
582 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
583
584 struct _xmlSchemaParserCtxt {
585 int type;
586 void *errCtxt; /* user specific error context */
587 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
588 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
589 int err;
590 int nberrors;
591 xmlStructuredErrorFunc serror;
592
593 xmlSchemaConstructionCtxtPtr constructor;
594 int ownsConstructor; /* TODO: Move this to parser *flags*. */
595
596 /* xmlSchemaPtr topschema; */
597 /* xmlHashTablePtr namespaces; */
598
599 xmlSchemaPtr schema; /* The main schema in use */
600 int counter;
601
602 const xmlChar *URL;
603 xmlDocPtr doc;
604 int preserve; /* Whether the doc should be freed */
605
606 const char *buffer;
607 int size;
608
609 /*
610 * Used to build complex element content models
611 */
612 xmlAutomataPtr am;
613 xmlAutomataStatePtr start;
614 xmlAutomataStatePtr end;
615 xmlAutomataStatePtr state;
616
617 xmlDictPtr dict; /* dictionary for interned string names */
618 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
619 int options;
620 xmlSchemaValidCtxtPtr vctxt;
621 int isS4S;
622 int isRedefine;
623 int xsiAssemble;
624 int stop; /* If the parser should stop; i.e. a critical error. */
625 const xmlChar *targetNamespace;
626 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
627
628 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
629 int redefCounter; /* Used for redefinitions. */
630 xmlSchemaItemListPtr attrProhibs;
631
632 xmlResourceLoader resourceLoader;
633 void *resourceCtxt;
634 };
635
636 /**
637 * xmlSchemaQNameRef:
638 *
639 * A component reference item (not a schema component)
640 * (Extends xmlSchemaBasicItem)
641 */
642 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
643 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
644 struct _xmlSchemaQNameRef {
645 xmlSchemaTypeType type;
646 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
647 xmlSchemaTypeType itemType;
648 const xmlChar *name;
649 const xmlChar *targetNamespace;
650 xmlNodePtr node;
651 };
652
653 /**
654 * xmlSchemaParticle:
655 *
656 * A particle component.
657 * (Extends xmlSchemaTreeItem)
658 */
659 typedef struct _xmlSchemaParticle xmlSchemaParticle;
660 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
661 struct _xmlSchemaParticle {
662 xmlSchemaTypeType type;
663 xmlSchemaAnnotPtr annot;
664 xmlSchemaTreeItemPtr next; /* next particle */
665 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
666 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
667 etc.) */
668 int minOccurs;
669 int maxOccurs;
670 xmlNodePtr node;
671 };
672
673 /**
674 * xmlSchemaModelGroup:
675 *
676 * A model group component.
677 * (Extends xmlSchemaTreeItem)
678 */
679 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
680 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
681 struct _xmlSchemaModelGroup {
682 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
683 xmlSchemaAnnotPtr annot;
684 xmlSchemaTreeItemPtr next; /* not used */
685 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
686 xmlNodePtr node;
687 };
688
689 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
690 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
691 /**
692 * xmlSchemaModelGroupDef:
693 *
694 * A model group definition component.
695 * (Extends xmlSchemaTreeItem)
696 */
697 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
698 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
699 struct _xmlSchemaModelGroupDef {
700 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
701 xmlSchemaAnnotPtr annot;
702 xmlSchemaTreeItemPtr next; /* not used */
703 xmlSchemaTreeItemPtr children; /* the "model group" */
704 const xmlChar *name;
705 const xmlChar *targetNamespace;
706 xmlNodePtr node;
707 int flags;
708 };
709
710 typedef struct _xmlSchemaIDC xmlSchemaIDC;
711 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
712
713 /**
714 * xmlSchemaIDCSelect:
715 *
716 * The identity-constraint "field" and "selector" item, holding the
717 * XPath expression.
718 */
719 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
720 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
721 struct _xmlSchemaIDCSelect {
722 xmlSchemaIDCSelectPtr next;
723 xmlSchemaIDCPtr idc;
724 int index; /* an index position if significant for IDC key-sequences */
725 const xmlChar *xpath; /* the XPath expression */
726 void *xpathComp; /* the compiled XPath expression */
727 };
728
729 /**
730 * xmlSchemaIDC:
731 *
732 * The identity-constraint definition component.
733 * (Extends xmlSchemaAnnotItem)
734 */
735
736 struct _xmlSchemaIDC {
737 xmlSchemaTypeType type;
738 xmlSchemaAnnotPtr annot;
739 xmlSchemaIDCPtr next;
740 xmlNodePtr node;
741 const xmlChar *name;
742 const xmlChar *targetNamespace;
743 xmlSchemaIDCSelectPtr selector;
744 xmlSchemaIDCSelectPtr fields;
745 int nbFields;
746 xmlSchemaQNameRefPtr ref;
747 };
748
749 /**
750 * xmlSchemaIDCAug:
751 *
752 * The augmented IDC information used for validation.
753 */
754 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
755 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
756 struct _xmlSchemaIDCAug {
757 xmlSchemaIDCAugPtr next; /* next in a list */
758 xmlSchemaIDCPtr def; /* the IDC definition */
759 int keyrefDepth; /* the lowest tree level to which IDC
760 tables need to be bubbled upwards */
761 };
762
763 /**
764 * xmlSchemaPSVIIDCKeySequence:
765 *
766 * The key sequence of a node table item.
767 */
768 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
769 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
770 struct _xmlSchemaPSVIIDCKey {
771 xmlSchemaTypePtr type;
772 xmlSchemaValPtr val;
773 };
774
775 /**
776 * xmlSchemaPSVIIDCNode:
777 *
778 * The node table item of a node table.
779 */
780 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
781 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
782 struct _xmlSchemaPSVIIDCNode {
783 xmlNodePtr node;
784 xmlSchemaPSVIIDCKeyPtr *keys;
785 int nodeLine;
786 int nodeQNameID;
787
788 };
789
790 /**
791 * xmlSchemaPSVIIDCBinding:
792 *
793 * The identity-constraint binding item of the [identity-constraint table].
794 */
795 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
796 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
797 struct _xmlSchemaPSVIIDCBinding {
798 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
799 xmlSchemaIDCPtr definition; /* the IDC definition */
800 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
801 int nbNodes; /* number of entries in the node table */
802 int sizeNodes; /* size of the node table */
803 xmlSchemaItemListPtr dupls;
804 };
805
806
807 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
808 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
809
810 #define XPATH_STATE_OBJ_MATCHES -2
811 #define XPATH_STATE_OBJ_BLOCKED -3
812
813 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
814 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
815
816 /**
817 * xmlSchemaIDCStateObj:
818 *
819 * The state object used to evaluate XPath expressions.
820 */
821 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
822 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
823 struct _xmlSchemaIDCStateObj {
824 int type;
825 xmlSchemaIDCStateObjPtr next; /* next if in a list */
826 int depth; /* depth of creation */
827 int *history; /* list of (depth, state-id) tuples */
828 int nbHistory;
829 int sizeHistory;
830 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
831 matcher */
832 xmlSchemaIDCSelectPtr sel;
833 void *xpathCtxt;
834 };
835
836 #define IDC_MATCHER 0
837
838 /**
839 * xmlSchemaIDCMatcher:
840 *
841 * Used to evaluate IDC selectors (and fields).
842 */
843 struct _xmlSchemaIDCMatcher {
844 int type;
845 int depth; /* the tree depth at creation time */
846 xmlSchemaIDCMatcherPtr next; /* next in the list */
847 xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
848 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
849 int idcType;
850 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
851 elements */
852 int sizeKeySeqs;
853 xmlSchemaItemListPtr targets; /* list of target-node
854 (xmlSchemaPSVIIDCNodePtr) entries */
855 xmlHashTablePtr htab;
856 };
857
858 /*
859 * Element info flags.
860 */
861 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
862 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
863 #define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
864 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
865
866 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
867 #define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
868 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
869
870 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
871 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
872 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
873 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
874
875 /**
876 * xmlSchemaNodeInfo:
877 *
878 * Holds information of an element node.
879 */
880 struct _xmlSchemaNodeInfo {
881 int nodeType;
882 xmlNodePtr node;
883 int nodeLine;
884 const xmlChar *localName;
885 const xmlChar *nsName;
886 const xmlChar *value;
887 xmlSchemaValPtr val; /* the pre-computed value if any */
888 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
889
890 int flags; /* combination of node info flags */
891
892 int valNeeded;
893 int normVal;
894
895 xmlSchemaElementPtr decl; /* the element/attribute declaration */
896 int depth;
897 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
898 for the scope element*/
899 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
900 element */
901 xmlRegExecCtxtPtr regexCtxt;
902
903 const xmlChar **nsBindings; /* Namespace bindings on this element */
904 int nbNsBindings;
905 int sizeNsBindings;
906
907 int hasKeyrefs;
908 int appliedXPath; /* Indicates that an XPath has been applied. */
909 };
910
911 #define XML_SCHEMAS_ATTR_UNKNOWN 1
912 #define XML_SCHEMAS_ATTR_ASSESSED 2
913 #define XML_SCHEMAS_ATTR_PROHIBITED 3
914 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
915 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
916 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
917 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
918 #define XML_SCHEMAS_ATTR_DEFAULT 8
919 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
920 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
921 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
922 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
923 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
924 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
925 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
926 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
927 #define XML_SCHEMAS_ATTR_META 17
928 /*
929 * @metaType values of xmlSchemaAttrInfo.
930 */
931 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
932 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
933 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
934 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
935 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
936
937 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
938 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
939 struct _xmlSchemaAttrInfo {
940 int nodeType;
941 xmlNodePtr node;
942 int nodeLine;
943 const xmlChar *localName;
944 const xmlChar *nsName;
945 const xmlChar *value;
946 xmlSchemaValPtr val; /* the pre-computed value if any */
947 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
948 int flags; /* combination of node info flags */
949
950 xmlSchemaAttributePtr decl; /* the attribute declaration */
951 xmlSchemaAttributeUsePtr use; /* the attribute use */
952 int state;
953 int metaType;
954 const xmlChar *vcValue; /* the value constraint value */
955 xmlSchemaNodeInfoPtr parent;
956 };
957
958
959 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
960 /**
961 * xmlSchemaValidCtxt:
962 *
963 * A Schemas validation context
964 */
965 struct _xmlSchemaValidCtxt {
966 int type;
967 void *errCtxt; /* user specific data block */
968 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
969 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
970 xmlStructuredErrorFunc serror;
971
972 xmlSchemaPtr schema; /* The schema in use */
973 xmlDocPtr doc;
974 xmlParserInputBufferPtr input;
975 xmlCharEncoding enc;
976 xmlSAXHandlerPtr sax;
977 xmlParserCtxtPtr parserCtxt;
978 void *user_data; /* TODO: What is this for? */
979 char *filename;
980
981 int err;
982 int nberrors;
983
984 xmlNodePtr node;
985 xmlNodePtr cur;
986 /* xmlSchemaTypePtr type; */
987
988 xmlRegExecCtxtPtr regexp;
989 xmlSchemaValPtr value;
990
991 int valueWS;
992 int options;
993 xmlNodePtr validationRoot;
994 xmlSchemaParserCtxtPtr pctxt;
995 int xsiAssemble;
996
997 int depth;
998 xmlSchemaNodeInfoPtr *elemInfos; /* array of element information */
999 int sizeElemInfos;
1000 xmlSchemaNodeInfoPtr inode; /* the current element information */
1001
1002 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC information */
1003
1004 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1005 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1006 xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1007
1008 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1009 int nbIdcNodes;
1010 int sizeIdcNodes;
1011
1012 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1013 int nbIdcKeys;
1014 int sizeIdcKeys;
1015
1016 int flags;
1017
1018 xmlDictPtr dict;
1019
1020 #ifdef LIBXML_READER_ENABLED
1021 xmlTextReaderPtr reader;
1022 #endif
1023
1024 xmlSchemaAttrInfoPtr *attrInfos;
1025 int nbAttrInfos;
1026 int sizeAttrInfos;
1027
1028 int skipDepth;
1029 xmlSchemaItemListPtr nodeQNames;
1030 int hasKeyrefs;
1031 int createIDCNodeTables;
1032 int psviExposeIDCNodeTables;
1033
1034 /* Locator for error reporting in streaming mode */
1035 xmlSchemaValidityLocatorFunc locFunc;
1036 void *locCtxt;
1037 };
1038
1039 /**
1040 * xmlSchemaSubstGroup:
1041 *
1042 *
1043 */
1044 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1045 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1046 struct _xmlSchemaSubstGroup {
1047 xmlSchemaElementPtr head;
1048 xmlSchemaItemListPtr members;
1049 };
1050
1051 /**
1052 * xmlIDCHashEntry:
1053 *
1054 * an entry in hash tables to quickly look up keys/uniques
1055 */
1056 typedef struct _xmlIDCHashEntry xmlIDCHashEntry;
1057 typedef xmlIDCHashEntry *xmlIDCHashEntryPtr;
1058 struct _xmlIDCHashEntry {
1059 xmlIDCHashEntryPtr next; /* next item with same hash */
1060 int index; /* index into associated item list */
1061 };
1062
1063 /************************************************************************
1064 * *
1065 * Some predeclarations *
1066 * *
1067 ************************************************************************/
1068
1069 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1070 xmlSchemaPtr schema,
1071 xmlNodePtr node);
1072 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1073 xmlSchemaPtr schema,
1074 xmlNodePtr node);
1075 static int
1076 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1077 xmlSchemaAbstractCtxtPtr ctxt);
1078 static const xmlChar *
1079 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1080 static int
1081 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1082 xmlNodePtr node);
1083 static int
1084 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1085 xmlSchemaParserCtxtPtr ctxt);
1086 static void
1087 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1088 static xmlSchemaWhitespaceValueType
1089 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1090 static xmlSchemaTreeItemPtr
1091 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1092 xmlNodePtr node, xmlSchemaTypeType type,
1093 int withParticle);
1094 static const xmlChar *
1095 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1096 static xmlSchemaTypeLinkPtr
1097 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1098 static void
1099 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1100 const char *funcName,
1101 const char *message) LIBXML_ATTR_FORMAT(3,0);
1102 static int
1103 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1104 xmlSchemaTypePtr type,
1105 xmlSchemaTypePtr baseType,
1106 int subset);
1107 static void
1108 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1109 xmlSchemaParserCtxtPtr ctxt);
1110 static void
1111 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1112 static xmlSchemaQNameRefPtr
1113 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1114 xmlSchemaPtr schema,
1115 xmlNodePtr node);
1116
1117 /************************************************************************
1118 * *
1119 * Helper functions *
1120 * *
1121 ************************************************************************/
1122
1123 /**
1124 * xmlSchemaItemTypeToStr:
1125 * @type: the type of the schema item
1126 *
1127 * Returns the component name of a schema item.
1128 */
1129 static const xmlChar *
xmlSchemaItemTypeToStr(xmlSchemaTypeType type)1130 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1131 {
1132 switch (type) {
1133 case XML_SCHEMA_TYPE_BASIC:
1134 return(BAD_CAST "simple type definition");
1135 case XML_SCHEMA_TYPE_SIMPLE:
1136 return(BAD_CAST "simple type definition");
1137 case XML_SCHEMA_TYPE_COMPLEX:
1138 return(BAD_CAST "complex type definition");
1139 case XML_SCHEMA_TYPE_ELEMENT:
1140 return(BAD_CAST "element declaration");
1141 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1142 return(BAD_CAST "attribute use");
1143 case XML_SCHEMA_TYPE_ATTRIBUTE:
1144 return(BAD_CAST "attribute declaration");
1145 case XML_SCHEMA_TYPE_GROUP:
1146 return(BAD_CAST "model group definition");
1147 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1148 return(BAD_CAST "attribute group definition");
1149 case XML_SCHEMA_TYPE_NOTATION:
1150 return(BAD_CAST "notation declaration");
1151 case XML_SCHEMA_TYPE_SEQUENCE:
1152 return(BAD_CAST "model group (sequence)");
1153 case XML_SCHEMA_TYPE_CHOICE:
1154 return(BAD_CAST "model group (choice)");
1155 case XML_SCHEMA_TYPE_ALL:
1156 return(BAD_CAST "model group (all)");
1157 case XML_SCHEMA_TYPE_PARTICLE:
1158 return(BAD_CAST "particle");
1159 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1160 return(BAD_CAST "unique identity-constraint");
1161 /* return(BAD_CAST "IDC (unique)"); */
1162 case XML_SCHEMA_TYPE_IDC_KEY:
1163 return(BAD_CAST "key identity-constraint");
1164 /* return(BAD_CAST "IDC (key)"); */
1165 case XML_SCHEMA_TYPE_IDC_KEYREF:
1166 return(BAD_CAST "keyref identity-constraint");
1167 /* return(BAD_CAST "IDC (keyref)"); */
1168 case XML_SCHEMA_TYPE_ANY:
1169 return(BAD_CAST "wildcard (any)");
1170 case XML_SCHEMA_EXTRA_QNAMEREF:
1171 return(BAD_CAST "[helper component] QName reference");
1172 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1173 return(BAD_CAST "[helper component] attribute use prohibition");
1174 default:
1175 return(BAD_CAST "Not a schema component");
1176 }
1177 }
1178
1179 /**
1180 * xmlSchemaGetComponentTypeStr:
1181 * @type: the type of the schema item
1182 *
1183 * Returns the component name of a schema item.
1184 */
1185 static const xmlChar *
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)1186 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1187 {
1188 switch (item->type) {
1189 case XML_SCHEMA_TYPE_BASIC:
1190 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1191 return(BAD_CAST "complex type definition");
1192 else
1193 return(BAD_CAST "simple type definition");
1194 default:
1195 return(xmlSchemaItemTypeToStr(item->type));
1196 }
1197 }
1198
1199 /**
1200 * xmlSchemaGetComponentNode:
1201 * @item: a schema component
1202 *
1203 * Returns node associated with the schema component.
1204 * NOTE that such a node need not be available; plus, a component's
1205 * node need not to reflect the component directly, since there is no
1206 * one-to-one relationship between the XML Schema representation and
1207 * the component representation.
1208 */
1209 static xmlNodePtr
xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)1210 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1211 {
1212 switch (item->type) {
1213 case XML_SCHEMA_TYPE_ELEMENT:
1214 return (((xmlSchemaElementPtr) item)->node);
1215 case XML_SCHEMA_TYPE_ATTRIBUTE:
1216 return (((xmlSchemaAttributePtr) item)->node);
1217 case XML_SCHEMA_TYPE_COMPLEX:
1218 case XML_SCHEMA_TYPE_SIMPLE:
1219 return (((xmlSchemaTypePtr) item)->node);
1220 case XML_SCHEMA_TYPE_ANY:
1221 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1222 return (((xmlSchemaWildcardPtr) item)->node);
1223 case XML_SCHEMA_TYPE_PARTICLE:
1224 return (((xmlSchemaParticlePtr) item)->node);
1225 case XML_SCHEMA_TYPE_SEQUENCE:
1226 case XML_SCHEMA_TYPE_CHOICE:
1227 case XML_SCHEMA_TYPE_ALL:
1228 return (((xmlSchemaModelGroupPtr) item)->node);
1229 case XML_SCHEMA_TYPE_GROUP:
1230 return (((xmlSchemaModelGroupDefPtr) item)->node);
1231 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1232 return (((xmlSchemaAttributeGroupPtr) item)->node);
1233 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1234 case XML_SCHEMA_TYPE_IDC_KEY:
1235 case XML_SCHEMA_TYPE_IDC_KEYREF:
1236 return (((xmlSchemaIDCPtr) item)->node);
1237 case XML_SCHEMA_EXTRA_QNAMEREF:
1238 return(((xmlSchemaQNameRefPtr) item)->node);
1239 /* TODO: What to do with NOTATIONs?
1240 case XML_SCHEMA_TYPE_NOTATION:
1241 return (((xmlSchemaNotationPtr) item)->node);
1242 */
1243 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1244 return (((xmlSchemaAttributeUsePtr) item)->node);
1245 default:
1246 return (NULL);
1247 }
1248 }
1249
1250 #if 0
1251 /**
1252 * xmlSchemaGetNextComponent:
1253 * @item: a schema component
1254 *
1255 * Returns the next sibling of the schema component.
1256 */
1257 static xmlSchemaBasicItemPtr
1258 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1259 {
1260 switch (item->type) {
1261 case XML_SCHEMA_TYPE_ELEMENT:
1262 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1263 case XML_SCHEMA_TYPE_ATTRIBUTE:
1264 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1265 case XML_SCHEMA_TYPE_COMPLEX:
1266 case XML_SCHEMA_TYPE_SIMPLE:
1267 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1268 case XML_SCHEMA_TYPE_ANY:
1269 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1270 return (NULL);
1271 case XML_SCHEMA_TYPE_PARTICLE:
1272 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1273 case XML_SCHEMA_TYPE_SEQUENCE:
1274 case XML_SCHEMA_TYPE_CHOICE:
1275 case XML_SCHEMA_TYPE_ALL:
1276 return (NULL);
1277 case XML_SCHEMA_TYPE_GROUP:
1278 return (NULL);
1279 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1280 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1281 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1282 case XML_SCHEMA_TYPE_IDC_KEY:
1283 case XML_SCHEMA_TYPE_IDC_KEYREF:
1284 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1285 default:
1286 return (NULL);
1287 }
1288 }
1289 #endif
1290
1291
1292 /**
1293 * xmlSchemaFormatQName:
1294 * @buf: the string buffer
1295 * @namespaceName: the namespace name
1296 * @localName: the local name
1297 *
1298 * Returns the given QName in the format "{namespaceName}localName" or
1299 * just "localName" if @namespaceName is NULL.
1300 *
1301 * Returns the localName if @namespaceName is NULL, a formatted
1302 * string otherwise.
1303 */
1304 static const xmlChar*
xmlSchemaFormatQName(xmlChar ** buf,const xmlChar * namespaceName,const xmlChar * localName)1305 xmlSchemaFormatQName(xmlChar **buf,
1306 const xmlChar *namespaceName,
1307 const xmlChar *localName)
1308 {
1309 FREE_AND_NULL(*buf)
1310 if (namespaceName != NULL) {
1311 *buf = xmlStrdup(BAD_CAST "{");
1312 *buf = xmlStrcat(*buf, namespaceName);
1313 *buf = xmlStrcat(*buf, BAD_CAST "}");
1314 }
1315 if (localName != NULL) {
1316 if (namespaceName == NULL)
1317 return(localName);
1318 *buf = xmlStrcat(*buf, localName);
1319 } else {
1320 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1321 }
1322 return ((const xmlChar *) *buf);
1323 }
1324
1325 static const xmlChar*
xmlSchemaFormatQNameNs(xmlChar ** buf,xmlNsPtr ns,const xmlChar * localName)1326 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1327 {
1328 if (ns != NULL)
1329 return (xmlSchemaFormatQName(buf, ns->href, localName));
1330 else
1331 return (xmlSchemaFormatQName(buf, NULL, localName));
1332 }
1333
1334 static const xmlChar *
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)1335 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1336 {
1337 if (item == NULL) {
1338 return (NULL);
1339 }
1340 switch (item->type) {
1341 case XML_SCHEMA_TYPE_ELEMENT:
1342 return (((xmlSchemaElementPtr) item)->name);
1343 case XML_SCHEMA_TYPE_ATTRIBUTE:
1344 return (((xmlSchemaAttributePtr) item)->name);
1345 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1346 return (((xmlSchemaAttributeGroupPtr) item)->name);
1347 case XML_SCHEMA_TYPE_BASIC:
1348 case XML_SCHEMA_TYPE_SIMPLE:
1349 case XML_SCHEMA_TYPE_COMPLEX:
1350 return (((xmlSchemaTypePtr) item)->name);
1351 case XML_SCHEMA_TYPE_GROUP:
1352 return (((xmlSchemaModelGroupDefPtr) item)->name);
1353 case XML_SCHEMA_TYPE_IDC_KEY:
1354 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1355 case XML_SCHEMA_TYPE_IDC_KEYREF:
1356 return (((xmlSchemaIDCPtr) item)->name);
1357 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1358 if (WXS_ATTRUSE_DECL(item) != NULL) {
1359 return(xmlSchemaGetComponentName(
1360 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1361 } else
1362 return(NULL);
1363 case XML_SCHEMA_EXTRA_QNAMEREF:
1364 return (((xmlSchemaQNameRefPtr) item)->name);
1365 case XML_SCHEMA_TYPE_NOTATION:
1366 return (((xmlSchemaNotationPtr) item)->name);
1367 default:
1368 /*
1369 * Other components cannot have names.
1370 */
1371 break;
1372 }
1373 return (NULL);
1374 }
1375
1376 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1377 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1378 /*
1379 static const xmlChar *
1380 xmlSchemaGetQNameRefName(void *ref)
1381 {
1382 return(((xmlSchemaQNameRefPtr) ref)->name);
1383 }
1384
1385 static const xmlChar *
1386 xmlSchemaGetQNameRefTargetNs(void *ref)
1387 {
1388 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1389 }
1390 */
1391
1392 static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)1393 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1394 {
1395 if (item == NULL) {
1396 return (NULL);
1397 }
1398 switch (item->type) {
1399 case XML_SCHEMA_TYPE_ELEMENT:
1400 return (((xmlSchemaElementPtr) item)->targetNamespace);
1401 case XML_SCHEMA_TYPE_ATTRIBUTE:
1402 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1403 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1404 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1405 case XML_SCHEMA_TYPE_BASIC:
1406 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1407 case XML_SCHEMA_TYPE_SIMPLE:
1408 case XML_SCHEMA_TYPE_COMPLEX:
1409 return (((xmlSchemaTypePtr) item)->targetNamespace);
1410 case XML_SCHEMA_TYPE_GROUP:
1411 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1412 case XML_SCHEMA_TYPE_IDC_KEY:
1413 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1414 case XML_SCHEMA_TYPE_IDC_KEYREF:
1415 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1416 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1417 if (WXS_ATTRUSE_DECL(item) != NULL) {
1418 return(xmlSchemaGetComponentTargetNs(
1419 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1420 }
1421 /* TODO: Will returning NULL break something? */
1422 break;
1423 case XML_SCHEMA_EXTRA_QNAMEREF:
1424 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1425 case XML_SCHEMA_TYPE_NOTATION:
1426 return (((xmlSchemaNotationPtr) item)->targetNamespace);
1427 default:
1428 /*
1429 * Other components cannot have names.
1430 */
1431 break;
1432 }
1433 return (NULL);
1434 }
1435
1436 static const xmlChar*
xmlSchemaGetComponentQName(xmlChar ** buf,void * item)1437 xmlSchemaGetComponentQName(xmlChar **buf,
1438 void *item)
1439 {
1440 return (xmlSchemaFormatQName(buf,
1441 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1442 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1443 }
1444
1445 static const xmlChar*
xmlSchemaGetComponentDesignation(xmlChar ** buf,void * item)1446 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1447 {
1448 xmlChar *str = NULL;
1449
1450 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1451 *buf = xmlStrcat(*buf, BAD_CAST " '");
1452 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1453 (xmlSchemaBasicItemPtr) item));
1454 *buf = xmlStrcat(*buf, BAD_CAST "'");
1455 FREE_AND_NULL(str);
1456 return(*buf);
1457 }
1458
1459 static const xmlChar*
xmlSchemaGetIDCDesignation(xmlChar ** buf,xmlSchemaIDCPtr idc)1460 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1461 {
1462 return(xmlSchemaGetComponentDesignation(buf, idc));
1463 }
1464
1465 /**
1466 * xmlSchemaWildcardPCToString:
1467 * @pc: the type of processContents
1468 *
1469 * Returns a string representation of the type of
1470 * processContents.
1471 */
1472 static const xmlChar *
xmlSchemaWildcardPCToString(int pc)1473 xmlSchemaWildcardPCToString(int pc)
1474 {
1475 switch (pc) {
1476 case XML_SCHEMAS_ANY_SKIP:
1477 return (BAD_CAST "skip");
1478 case XML_SCHEMAS_ANY_LAX:
1479 return (BAD_CAST "lax");
1480 case XML_SCHEMAS_ANY_STRICT:
1481 return (BAD_CAST "strict");
1482 default:
1483 return (BAD_CAST "invalid process contents");
1484 }
1485 }
1486
1487 /**
1488 * xmlSchemaGetCanonValueWhtspExt:
1489 * @val: the precomputed value
1490 * @retValue: the returned value
1491 * @ws: the whitespace type of the value
1492 * @for_hash: non-zero if this is supposed to generate a string for hashing
1493 *
1494 * Get a the canonical representation of the value.
1495 * The caller has to free the returned retValue.
1496 *
1497 * Returns 0 if the value could be built and -1 in case of
1498 * API errors or if the value type is not supported yet.
1499 */
1500 static int
xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue,int for_hash)1501 xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
1502 xmlSchemaWhitespaceValueType ws,
1503 xmlChar **retValue,
1504 int for_hash)
1505 {
1506 int list;
1507 xmlSchemaValType valType;
1508 const xmlChar *value, *value2 = NULL;
1509
1510
1511 if ((retValue == NULL) || (val == NULL))
1512 return (-1);
1513 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1514 *retValue = NULL;
1515 do {
1516 value = NULL;
1517 valType = xmlSchemaGetValType(val);
1518 switch (valType) {
1519 case XML_SCHEMAS_STRING:
1520 case XML_SCHEMAS_NORMSTRING:
1521 case XML_SCHEMAS_ANYSIMPLETYPE:
1522 value = xmlSchemaValueGetAsString(val);
1523 if (value != NULL) {
1524 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1525 value2 = xmlSchemaCollapseString(value);
1526 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1527 value2 = xmlSchemaWhiteSpaceReplace(value);
1528 if (value2 != NULL)
1529 value = value2;
1530 }
1531 break;
1532 default:
1533 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1534 if (value2 != NULL)
1535 xmlFree((xmlChar *) value2);
1536 goto internal_error;
1537 }
1538 if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
1539 /* We can mostly use the canonical value for hashing,
1540 except in the case of decimal. There the canonical
1541 representation requires a trailing '.0' even for
1542 non-fractional numbers, but for the derived integer
1543 types it forbids any decimal point. Nevertheless they
1544 compare equal if the value is equal. We need to generate
1545 the same hash value for this to work, and it's easiest
1546 to just cut off the useless '.0' suffix for the
1547 decimal type. */
1548 int len = xmlStrlen(value2);
1549 if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
1550 ((xmlChar*)value2)[len-2] = 0;
1551 }
1552 value = value2;
1553 }
1554 if (*retValue == NULL)
1555 if (value == NULL) {
1556 if (! list)
1557 *retValue = xmlStrdup(BAD_CAST "");
1558 } else
1559 *retValue = xmlStrdup(value);
1560 else if (value != NULL) {
1561 /* List. */
1562 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1563 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1564 }
1565 FREE_AND_NULL(value2)
1566 val = xmlSchemaValueGetNext(val);
1567 } while (val != NULL);
1568
1569 return (0);
1570 internal_error:
1571 if (*retValue != NULL)
1572 xmlFree((xmlChar *) (*retValue));
1573 if (value2 != NULL)
1574 xmlFree((xmlChar *) value2);
1575 return (-1);
1576 }
1577
1578 static int
xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue)1579 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1580 xmlSchemaWhitespaceValueType ws,
1581 xmlChar **retValue)
1582 {
1583 return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
1584 }
1585
1586 static int
xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,xmlChar ** retValue)1587 xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
1588 xmlChar **retValue)
1589 {
1590 return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
1591 retValue, 1);
1592 }
1593
1594 /**
1595 * xmlSchemaFormatItemForReport:
1596 * @buf: the string buffer
1597 * @itemDes: the designation of the item
1598 * @itemName: the name of the item
1599 * @item: the item as an object
1600 * @itemNode: the node of the item
1601 * @local: the local name
1602 * @parsing: if the function is used during the parse
1603 *
1604 * Returns a representation of the given item used
1605 * for error reports.
1606 *
1607 * The following order is used to build the resulting
1608 * designation if the arguments are not NULL:
1609 * 1a. If itemDes not NULL -> itemDes
1610 * 1b. If (itemDes not NULL) and (itemName not NULL)
1611 * -> itemDes + itemName
1612 * 2. If the preceding was NULL and (item not NULL) -> item
1613 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1614 *
1615 * If the itemNode is an attribute node, the name of the attribute
1616 * will be appended to the result.
1617 *
1618 * Returns the formatted string and sets @buf to the resulting value.
1619 */
1620 static xmlChar*
xmlSchemaFormatItemForReport(xmlChar ** buf,const xmlChar * itemDes,xmlSchemaBasicItemPtr item,xmlNodePtr itemNode)1621 xmlSchemaFormatItemForReport(xmlChar **buf,
1622 const xmlChar *itemDes,
1623 xmlSchemaBasicItemPtr item,
1624 xmlNodePtr itemNode)
1625 {
1626 xmlChar *str = NULL;
1627 int named = 1;
1628
1629 if (*buf != NULL) {
1630 xmlFree(*buf);
1631 *buf = NULL;
1632 }
1633
1634 if (itemDes != NULL) {
1635 *buf = xmlStrdup(itemDes);
1636 } else if (item != NULL) {
1637 switch (item->type) {
1638 case XML_SCHEMA_TYPE_BASIC: {
1639 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1640
1641 if (WXS_IS_ATOMIC(type))
1642 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1643 else if (WXS_IS_LIST(type))
1644 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1645 else if (WXS_IS_UNION(type))
1646 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1647 else
1648 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1649 *buf = xmlStrcat(*buf, type->name);
1650 *buf = xmlStrcat(*buf, BAD_CAST "'");
1651 }
1652 break;
1653 case XML_SCHEMA_TYPE_SIMPLE: {
1654 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1655
1656 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1657 *buf = xmlStrdup(BAD_CAST"");
1658 } else {
1659 *buf = xmlStrdup(BAD_CAST "local ");
1660 }
1661 if (WXS_IS_ATOMIC(type))
1662 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1663 else if (WXS_IS_LIST(type))
1664 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1665 else if (WXS_IS_UNION(type))
1666 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1667 else
1668 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1669 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1670 *buf = xmlStrcat(*buf, BAD_CAST " '");
1671 *buf = xmlStrcat(*buf, type->name);
1672 *buf = xmlStrcat(*buf, BAD_CAST "'");
1673 }
1674 }
1675 break;
1676 case XML_SCHEMA_TYPE_COMPLEX: {
1677 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1678
1679 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1680 *buf = xmlStrdup(BAD_CAST "");
1681 else
1682 *buf = xmlStrdup(BAD_CAST "local ");
1683 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1684 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1685 *buf = xmlStrcat(*buf, BAD_CAST " '");
1686 *buf = xmlStrcat(*buf, type->name);
1687 *buf = xmlStrcat(*buf, BAD_CAST "'");
1688 }
1689 }
1690 break;
1691 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1692 xmlSchemaAttributeUsePtr ause;
1693
1694 ause = WXS_ATTR_USE_CAST item;
1695 *buf = xmlStrdup(BAD_CAST "attribute use ");
1696 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1697 *buf = xmlStrcat(*buf, BAD_CAST "'");
1698 *buf = xmlStrcat(*buf,
1699 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1700 FREE_AND_NULL(str)
1701 *buf = xmlStrcat(*buf, BAD_CAST "'");
1702 } else {
1703 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1704 }
1705 }
1706 break;
1707 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1708 xmlSchemaAttributePtr attr;
1709
1710 attr = (xmlSchemaAttributePtr) item;
1711 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1712 *buf = xmlStrcat(*buf, BAD_CAST " '");
1713 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1714 attr->targetNamespace, attr->name));
1715 FREE_AND_NULL(str)
1716 *buf = xmlStrcat(*buf, BAD_CAST "'");
1717 }
1718 break;
1719 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1720 xmlSchemaGetComponentDesignation(buf, item);
1721 break;
1722 case XML_SCHEMA_TYPE_ELEMENT: {
1723 xmlSchemaElementPtr elem;
1724
1725 elem = (xmlSchemaElementPtr) item;
1726 *buf = xmlStrdup(BAD_CAST "element decl.");
1727 *buf = xmlStrcat(*buf, BAD_CAST " '");
1728 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1729 elem->targetNamespace, elem->name));
1730 *buf = xmlStrcat(*buf, BAD_CAST "'");
1731 }
1732 break;
1733 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1734 case XML_SCHEMA_TYPE_IDC_KEY:
1735 case XML_SCHEMA_TYPE_IDC_KEYREF:
1736 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1737 *buf = xmlStrdup(BAD_CAST "unique '");
1738 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1739 *buf = xmlStrdup(BAD_CAST "key '");
1740 else
1741 *buf = xmlStrdup(BAD_CAST "keyRef '");
1742 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1743 *buf = xmlStrcat(*buf, BAD_CAST "'");
1744 break;
1745 case XML_SCHEMA_TYPE_ANY:
1746 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1747 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1748 ((xmlSchemaWildcardPtr) item)->processContents));
1749 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1750 break;
1751 case XML_SCHEMA_FACET_MININCLUSIVE:
1752 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1753 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1754 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1755 case XML_SCHEMA_FACET_TOTALDIGITS:
1756 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1757 case XML_SCHEMA_FACET_PATTERN:
1758 case XML_SCHEMA_FACET_ENUMERATION:
1759 case XML_SCHEMA_FACET_WHITESPACE:
1760 case XML_SCHEMA_FACET_LENGTH:
1761 case XML_SCHEMA_FACET_MAXLENGTH:
1762 case XML_SCHEMA_FACET_MINLENGTH:
1763 *buf = xmlStrdup(BAD_CAST "facet '");
1764 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1765 *buf = xmlStrcat(*buf, BAD_CAST "'");
1766 break;
1767 case XML_SCHEMA_TYPE_GROUP: {
1768 *buf = xmlStrdup(BAD_CAST "model group def.");
1769 *buf = xmlStrcat(*buf, BAD_CAST " '");
1770 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1771 *buf = xmlStrcat(*buf, BAD_CAST "'");
1772 FREE_AND_NULL(str)
1773 }
1774 break;
1775 case XML_SCHEMA_TYPE_SEQUENCE:
1776 case XML_SCHEMA_TYPE_CHOICE:
1777 case XML_SCHEMA_TYPE_ALL:
1778 case XML_SCHEMA_TYPE_PARTICLE:
1779 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1780 break;
1781 case XML_SCHEMA_TYPE_NOTATION: {
1782 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1783 *buf = xmlStrcat(*buf, BAD_CAST " '");
1784 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1785 *buf = xmlStrcat(*buf, BAD_CAST "'");
1786 FREE_AND_NULL(str);
1787 }
1788 /* Falls through. */
1789 default:
1790 named = 0;
1791 }
1792 } else
1793 named = 0;
1794
1795 if ((named == 0) && (itemNode != NULL)) {
1796 xmlNodePtr elem;
1797
1798 if (itemNode->type == XML_ATTRIBUTE_NODE)
1799 elem = itemNode->parent;
1800 else
1801 elem = itemNode;
1802 *buf = xmlStrdup(BAD_CAST "Element '");
1803 if (elem->ns != NULL) {
1804 *buf = xmlStrcat(*buf,
1805 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1806 FREE_AND_NULL(str)
1807 } else
1808 *buf = xmlStrcat(*buf, elem->name);
1809 *buf = xmlStrcat(*buf, BAD_CAST "'");
1810
1811 }
1812 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1813 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1814 if (itemNode->ns != NULL) {
1815 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1816 itemNode->ns->href, itemNode->name));
1817 FREE_AND_NULL(str)
1818 } else
1819 *buf = xmlStrcat(*buf, itemNode->name);
1820 *buf = xmlStrcat(*buf, BAD_CAST "'");
1821 }
1822 FREE_AND_NULL(str)
1823
1824 return (xmlEscapeFormatString(buf));
1825 }
1826
1827 /**
1828 * xmlSchemaFormatFacetEnumSet:
1829 * @buf: the string buffer
1830 * @type: the type holding the enumeration facets
1831 *
1832 * Builds a string consisting of all enumeration elements.
1833 *
1834 * Returns a string of all enumeration elements.
1835 */
1836 static const xmlChar *
xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,xmlChar ** buf,xmlSchemaTypePtr type)1837 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1838 xmlChar **buf, xmlSchemaTypePtr type)
1839 {
1840 xmlSchemaFacetPtr facet;
1841 xmlSchemaWhitespaceValueType ws;
1842 xmlChar *value = NULL;
1843 int res, found = 0;
1844
1845 if (*buf != NULL)
1846 xmlFree(*buf);
1847 *buf = NULL;
1848
1849 do {
1850 /*
1851 * Use the whitespace type of the base type.
1852 */
1853 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1854 for (facet = type->facets; facet != NULL; facet = facet->next) {
1855 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1856 continue;
1857 found = 1;
1858 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1859 ws, &value);
1860 if (res == -1) {
1861 xmlSchemaInternalErr(actxt,
1862 "xmlSchemaFormatFacetEnumSet",
1863 "compute the canonical lexical representation");
1864 if (*buf != NULL)
1865 xmlFree(*buf);
1866 *buf = NULL;
1867 return (NULL);
1868 }
1869 if (*buf == NULL)
1870 *buf = xmlStrdup(BAD_CAST "'");
1871 else
1872 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1873 *buf = xmlStrcat(*buf, BAD_CAST value);
1874 *buf = xmlStrcat(*buf, BAD_CAST "'");
1875 if (value != NULL) {
1876 xmlFree((xmlChar *)value);
1877 value = NULL;
1878 }
1879 }
1880 /*
1881 * The enumeration facet of a type restricts the enumeration
1882 * facet of the ancestor type; i.e., such restricted enumerations
1883 * do not belong to the set of the given type. Thus we break
1884 * on the first found enumeration.
1885 */
1886 if (found)
1887 break;
1888 type = type->baseType;
1889 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1890
1891 return ((const xmlChar *) *buf);
1892 }
1893
1894 /************************************************************************
1895 * *
1896 * Error functions *
1897 * *
1898 ************************************************************************/
1899
1900 /**
1901 * xmlSchemaPErrMemory:
1902 * @node: a context node
1903 * @extra: extra information
1904 *
1905 * Handle an out of memory condition
1906 */
1907 static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt)1908 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt)
1909 {
1910 xmlGenericErrorFunc channel = NULL;
1911 xmlStructuredErrorFunc schannel = NULL;
1912 void *data = NULL;
1913
1914 if (ctxt != NULL) {
1915 ctxt->nberrors++;
1916 ctxt->err = XML_ERR_NO_MEMORY;
1917 channel = ctxt->error;
1918 schannel = ctxt->serror;
1919 data = ctxt->errCtxt;
1920 }
1921
1922 xmlRaiseMemoryError(schannel, channel, data, XML_FROM_SCHEMASP, NULL);
1923 }
1924
1925 static void LIBXML_ATTR_FORMAT(11,12)
xmlSchemaPErrFull(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int code,xmlErrorLevel level,const char * file,int line,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,int col,const char * msg,...)1926 xmlSchemaPErrFull(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code,
1927 xmlErrorLevel level, const char *file, int line,
1928 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
1929 int col, const char *msg, ...) {
1930 xmlGenericErrorFunc channel = NULL;
1931 xmlStructuredErrorFunc schannel = NULL;
1932 void *data = NULL;
1933 int res;
1934 va_list ap;
1935
1936 if (ctxt != NULL) {
1937 /* Don't overwrite memory errors */
1938 if (ctxt->err == XML_ERR_NO_MEMORY)
1939 return;
1940
1941 if (level == XML_ERR_WARNING) {
1942 channel = ctxt->warning;
1943 } else {
1944 ctxt->nberrors++;
1945 ctxt->err = code;
1946 channel = ctxt->error;
1947 }
1948 data = ctxt->errCtxt;
1949 schannel = ctxt->serror;
1950 }
1951
1952 if ((channel == NULL) && (schannel == NULL)) {
1953 channel = xmlGenericError;
1954 data = xmlGenericErrorContext;
1955 }
1956
1957 va_start(ap, msg);
1958 res = xmlVRaiseError(schannel, channel, data, ctxt, node,
1959 XML_FROM_SCHEMASP, code, level, file, line,
1960 (const char *) str1,
1961 (const char *) str2,
1962 (const char *) str3,
1963 0, col, msg, ap);
1964 va_end(ap);
1965
1966 if (res < 0)
1967 xmlSchemaPErrMemory(ctxt);
1968 }
1969
1970 /**
1971 * xmlSchemaPErr:
1972 * @ctxt: the parsing context
1973 * @node: the context node
1974 * @error: the error code
1975 * @msg: the error message
1976 * @str1: extra data
1977 * @str2: extra data
1978 *
1979 * Handle a parser error
1980 */
1981 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int code,const char * msg,const xmlChar * str1,const xmlChar * str2)1982 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code,
1983 const char *msg, const xmlChar * str1, const xmlChar * str2)
1984 {
1985 xmlSchemaPErrFull(ctxt, node, code, XML_ERR_ERROR, NULL, 0,
1986 str1, str2, NULL, 0, msg, str1, str2);
1987 }
1988
1989 /**
1990 * xmlSchemaPErr2:
1991 * @ctxt: the parsing context
1992 * @node: the context node
1993 * @node: the current child
1994 * @error: the error code
1995 * @msg: the error message
1996 * @str1: extra data
1997 * @str2: extra data
1998 *
1999 * Handle a parser error
2000 */
2001 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,xmlNodePtr child,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)2002 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2003 xmlNodePtr child, int error,
2004 const char *msg, const xmlChar * str1, const xmlChar * str2)
2005 {
2006 if (child != NULL)
2007 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
2008 else
2009 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
2010 }
2011
2012
2013 /**
2014 * xmlSchemaPErrExt:
2015 * @ctxt: the parsing context
2016 * @node: the context node
2017 * @error: the error code
2018 * @strData1: extra data
2019 * @strData2: extra data
2020 * @strData3: extra data
2021 * @msg: the message
2022 * @str1: extra parameter for the message display
2023 * @str2: extra parameter for the message display
2024 * @str3: extra parameter for the message display
2025 * @str4: extra parameter for the message display
2026 * @str5: extra parameter for the message display
2027 *
2028 * Handle a parser error
2029 */
2030 static void LIBXML_ATTR_FORMAT(7,0)
xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int code,const xmlChar * strData1,const xmlChar * strData2,const xmlChar * strData3,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4,const xmlChar * str5)2031 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code,
2032 const xmlChar * strData1, const xmlChar * strData2,
2033 const xmlChar * strData3, const char *msg, const xmlChar * str1,
2034 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
2035 const xmlChar * str5)
2036 {
2037 xmlSchemaPErrFull(ctxt, node, code, XML_ERR_ERROR, NULL, 0,
2038 strData1, strData2, strData3, 0,
2039 msg, str1, str2, str3, str4, str5);
2040 }
2041
2042 /************************************************************************
2043 * *
2044 * Allround error functions *
2045 * *
2046 ************************************************************************/
2047
2048 /**
2049 * xmlSchemaVTypeErrMemory:
2050 * @node: a context node
2051 * @extra: extra information
2052 *
2053 * Handle an out of memory condition
2054 */
2055 static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt)2056 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt)
2057 {
2058 xmlGenericErrorFunc channel = NULL;
2059 xmlStructuredErrorFunc schannel = NULL;
2060 void *data = NULL;
2061
2062 if (ctxt != NULL) {
2063 ctxt->nberrors++;
2064 ctxt->err = XML_ERR_NO_MEMORY;
2065 channel = ctxt->error;
2066 schannel = ctxt->serror;
2067 data = ctxt->errCtxt;
2068 }
2069
2070 xmlRaiseMemoryError(schannel, channel, data, XML_FROM_SCHEMASV, NULL);
2071 }
2072
2073 static void LIBXML_ATTR_FORMAT(11,12)
xmlSchemaVErrFull(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node,int code,xmlErrorLevel level,const char * file,int line,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,int col,const char * msg,...)2074 xmlSchemaVErrFull(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int code,
2075 xmlErrorLevel level, const char *file, int line,
2076 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
2077 int col, const char *msg, ...) {
2078 xmlGenericErrorFunc channel = NULL;
2079 xmlStructuredErrorFunc schannel = NULL;
2080 void *data = NULL;
2081 int res;
2082 va_list ap;
2083
2084 if (ctxt != NULL) {
2085 /* Don't overwrite memory errors */
2086 if (ctxt->err == XML_ERR_NO_MEMORY)
2087 return;
2088
2089 if (level == XML_ERR_WARNING) {
2090 channel = ctxt->warning;
2091 } else {
2092 ctxt->nberrors++;
2093 ctxt->err = code;
2094 channel = ctxt->error;
2095 }
2096 data = ctxt->errCtxt;
2097 schannel = ctxt->serror;
2098 }
2099
2100 if ((channel == NULL) && (schannel == NULL)) {
2101 channel = xmlGenericError;
2102 data = xmlGenericErrorContext;
2103 }
2104
2105 va_start(ap, msg);
2106 res = xmlVRaiseError(schannel, channel, data, ctxt, node,
2107 XML_FROM_SCHEMASV, code, level, file, line,
2108 (const char *) str1,
2109 (const char *) str2,
2110 (const char *) str3,
2111 0, col, msg, ap);
2112 va_end(ap);
2113
2114 if (res < 0)
2115 xmlSchemaVErrMemory(ctxt);
2116 }
2117
2118 #define WXS_ERROR_TYPE_ERROR 1
2119 #define WXS_ERROR_TYPE_WARNING 2
2120 /**
2121 * xmlSchemaErr4Line:
2122 * @ctxt: the validation context
2123 * @errorLevel: the error level
2124 * @error: the error code
2125 * @node: the context node
2126 * @line: the line number
2127 * @msg: the error message
2128 * @str1: extra data
2129 * @str2: extra data
2130 * @str3: extra data
2131 * @str4: extra data
2132 *
2133 * Handle a validation error
2134 */
2135 static void LIBXML_ATTR_FORMAT(6,0)
xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,xmlErrorLevel errorLevel,int code,xmlNodePtr node,int line,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2136 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2137 xmlErrorLevel errorLevel,
2138 int code, xmlNodePtr node, int line, const char *msg,
2139 const xmlChar *str1, const xmlChar *str2,
2140 const xmlChar *str3, const xmlChar *str4)
2141 {
2142 if (ctxt != NULL) {
2143 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2144 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2145 const char *file = NULL;
2146 int col = 0;
2147
2148 /*
2149 * Error node. If we specify a line number, then
2150 * do not channel any node to the error function.
2151 */
2152 if (line == 0) {
2153 if ((node == NULL) &&
2154 (vctxt->depth >= 0) &&
2155 (vctxt->inode != NULL)) {
2156 node = vctxt->inode->node;
2157 }
2158 /*
2159 * Get filename and line if no node-tree.
2160 */
2161 if ((node == NULL) &&
2162 (vctxt->parserCtxt != NULL) &&
2163 (vctxt->parserCtxt->input != NULL)) {
2164 file = vctxt->parserCtxt->input->filename;
2165 if (vctxt->inode != NULL) {
2166 line = vctxt->inode->nodeLine;
2167 col = 0;
2168 } else {
2169 /* This is inaccurate. */
2170 line = vctxt->parserCtxt->input->line;
2171 col = vctxt->parserCtxt->input->col;
2172 }
2173 }
2174 } else {
2175 /*
2176 * Override the given node's (if any) position
2177 * and channel only the given line number.
2178 */
2179 node = NULL;
2180 /*
2181 * Get filename.
2182 */
2183 if (vctxt->doc != NULL)
2184 file = (const char *) vctxt->doc->URL;
2185 else if ((vctxt->parserCtxt != NULL) &&
2186 (vctxt->parserCtxt->input != NULL))
2187 file = vctxt->parserCtxt->input->filename;
2188 }
2189 if (vctxt->locFunc != NULL) {
2190 if ((file == NULL) || (line == 0)) {
2191 unsigned long l;
2192 const char *f;
2193 vctxt->locFunc(vctxt->locCtxt, &f, &l);
2194 if (file == NULL)
2195 file = f;
2196 if (line == 0)
2197 line = (int) l;
2198 }
2199 }
2200 if ((file == NULL) && (vctxt->filename != NULL))
2201 file = vctxt->filename;
2202
2203 xmlSchemaVErrFull(vctxt, node, code, errorLevel,
2204 file, line, str1, str2, str3, col,
2205 msg, str1, str2, str3, str4);
2206 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2207 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2208
2209 xmlSchemaPErrFull(pctxt, node, code, errorLevel,
2210 NULL, 0, str1, str2, str3, 0,
2211 msg, str1, str2, str3, str4);
2212 }
2213 }
2214 }
2215
2216 /**
2217 * xmlSchemaErr3:
2218 * @ctxt: the validation context
2219 * @node: the context node
2220 * @error: the error code
2221 * @msg: the error message
2222 * @str1: extra data
2223 * @str2: extra data
2224 * @str3: extra data
2225 *
2226 * Handle a validation error
2227 */
2228 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)2229 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2230 int error, xmlNodePtr node, const char *msg,
2231 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2232 {
2233 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2234 msg, str1, str2, str3, NULL);
2235 }
2236
2237 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2238 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2239 int error, xmlNodePtr node, const char *msg,
2240 const xmlChar *str1, const xmlChar *str2,
2241 const xmlChar *str3, const xmlChar *str4)
2242 {
2243 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2244 msg, str1, str2, str3, str4);
2245 }
2246
2247 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2)2248 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2249 int error, xmlNodePtr node, const char *msg,
2250 const xmlChar *str1, const xmlChar *str2)
2251 {
2252 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2253 }
2254
2255 static xmlChar *
xmlSchemaFormatNodeForError(xmlChar ** msg,xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2256 xmlSchemaFormatNodeForError(xmlChar ** msg,
2257 xmlSchemaAbstractCtxtPtr actxt,
2258 xmlNodePtr node)
2259 {
2260 xmlChar *str = NULL;
2261
2262 *msg = NULL;
2263 if ((node != NULL) &&
2264 (node->type != XML_ELEMENT_NODE) &&
2265 (node->type != XML_ATTRIBUTE_NODE))
2266 {
2267 /*
2268 * Don't try to format other nodes than element and
2269 * attribute nodes.
2270 * Play safe and return an empty string.
2271 */
2272 *msg = xmlStrdup(BAD_CAST "");
2273 return(*msg);
2274 }
2275 if (node != NULL) {
2276 /*
2277 * Work on tree nodes.
2278 */
2279 if (node->type == XML_ATTRIBUTE_NODE) {
2280 xmlNodePtr elem = node->parent;
2281
2282 *msg = xmlStrdup(BAD_CAST "Element '");
2283 if (elem->ns != NULL)
2284 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2285 elem->ns->href, elem->name));
2286 else
2287 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2288 NULL, elem->name));
2289 FREE_AND_NULL(str);
2290 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2291 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2292 } else {
2293 *msg = xmlStrdup(BAD_CAST "Element '");
2294 }
2295 if (node->ns != NULL)
2296 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2297 node->ns->href, node->name));
2298 else
2299 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2300 NULL, node->name));
2301 FREE_AND_NULL(str);
2302 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2303 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2304 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2305 /*
2306 * Work on node infos.
2307 */
2308 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2309 xmlSchemaNodeInfoPtr ielem =
2310 vctxt->elemInfos[vctxt->depth];
2311
2312 *msg = xmlStrdup(BAD_CAST "Element '");
2313 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2314 ielem->nsName, ielem->localName));
2315 FREE_AND_NULL(str);
2316 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2317 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2318 } else {
2319 *msg = xmlStrdup(BAD_CAST "Element '");
2320 }
2321 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2322 vctxt->inode->nsName, vctxt->inode->localName));
2323 FREE_AND_NULL(str);
2324 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2325 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2326 /*
2327 * Hmm, no node while parsing?
2328 * Return an empty string, in case NULL will break something.
2329 */
2330 *msg = xmlStrdup(BAD_CAST "");
2331 } else {
2332 /* TODO */
2333 return (NULL);
2334 }
2335
2336 /*
2337 * xmlSchemaFormatItemForReport() also returns an escaped format
2338 * string, so do this before calling it below (in the future).
2339 */
2340 xmlEscapeFormatString(msg);
2341
2342 /*
2343 * VAL TODO: The output of the given schema component is currently
2344 * disabled.
2345 */
2346 #if 0
2347 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2348 *msg = xmlStrcat(*msg, BAD_CAST " [");
2349 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2350 NULL, type, NULL, 0));
2351 FREE_AND_NULL(str)
2352 *msg = xmlStrcat(*msg, BAD_CAST "]");
2353 }
2354 #endif
2355 return (*msg);
2356 }
2357
2358 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message,const xmlChar * str1,const xmlChar * str2)2359 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2360 const char *funcName,
2361 const char *message,
2362 const xmlChar *str1,
2363 const xmlChar *str2)
2364 {
2365 xmlChar *msg = NULL;
2366
2367 if (actxt == NULL)
2368 return;
2369 msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2370 msg = xmlStrcat(msg, BAD_CAST message);
2371 msg = xmlStrcat(msg, BAD_CAST ".\n");
2372
2373 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2374 xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2375 (const char *) msg, (const xmlChar *) funcName, str1, str2);
2376 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2377 xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2378 (const char *) msg, (const xmlChar *) funcName, str1, str2);
2379
2380 FREE_AND_NULL(msg)
2381 }
2382
2383 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message)2384 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2385 const char *funcName,
2386 const char *message)
2387 {
2388 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2389 }
2390
2391 #if 0
2392 static void LIBXML_ATTR_FORMAT(3,0)
2393 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2394 const char *funcName,
2395 const char *message,
2396 const xmlChar *str1,
2397 const xmlChar *str2)
2398 {
2399 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2400 str1, str2);
2401 }
2402 #endif
2403
2404 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaBasicItemPtr item,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2405 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2406 xmlParserErrors error,
2407 xmlNodePtr node,
2408 xmlSchemaBasicItemPtr item,
2409 const char *message,
2410 const xmlChar *str1, const xmlChar *str2,
2411 const xmlChar *str3, const xmlChar *str4)
2412 {
2413 xmlChar *msg = NULL;
2414
2415 if ((node == NULL) && (item != NULL) &&
2416 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2417 node = WXS_ITEM_NODE(item);
2418 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2419 msg = xmlStrcat(msg, BAD_CAST ": ");
2420 } else
2421 xmlSchemaFormatNodeForError(&msg, actxt, node);
2422 msg = xmlStrcat(msg, (const xmlChar *) message);
2423 msg = xmlStrcat(msg, BAD_CAST ".\n");
2424 xmlSchemaErr4(actxt, error, node,
2425 (const char *) msg, str1, str2, str3, str4);
2426 FREE_AND_NULL(msg)
2427 }
2428
2429 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaBasicItemPtr item,const char * message,const xmlChar * str1,const xmlChar * str2)2430 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2431 xmlParserErrors error,
2432 xmlNodePtr node,
2433 xmlSchemaBasicItemPtr item,
2434 const char *message,
2435 const xmlChar *str1,
2436 const xmlChar *str2)
2437 {
2438 xmlSchemaCustomErr4(actxt, error, node, item,
2439 message, str1, str2, NULL, NULL);
2440 }
2441
2442
2443
2444 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)2445 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2446 xmlParserErrors error,
2447 xmlNodePtr node,
2448 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2449 const char *message,
2450 const xmlChar *str1,
2451 const xmlChar *str2,
2452 const xmlChar *str3)
2453 {
2454 xmlChar *msg = NULL;
2455
2456 xmlSchemaFormatNodeForError(&msg, actxt, node);
2457 msg = xmlStrcat(msg, (const xmlChar *) message);
2458 msg = xmlStrcat(msg, BAD_CAST ".\n");
2459
2460 /* URGENT TODO: Set the error code to something sane. */
2461 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2462 (const char *) msg, str1, str2, str3, NULL);
2463
2464 FREE_AND_NULL(msg)
2465 }
2466
2467
2468
2469 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,xmlParserErrors error,xmlSchemaPSVIIDCNodePtr idcNode,xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const char * message,const xmlChar * str1,const xmlChar * str2)2470 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2471 xmlParserErrors error,
2472 xmlSchemaPSVIIDCNodePtr idcNode,
2473 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2474 const char *message,
2475 const xmlChar *str1,
2476 const xmlChar *str2)
2477 {
2478 xmlChar *msg = NULL, *qname = NULL;
2479
2480 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2481 msg = xmlStrcat(msg, (const xmlChar *) message);
2482 msg = xmlStrcat(msg, BAD_CAST ".\n");
2483 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2484 error, NULL, idcNode->nodeLine, (const char *) msg,
2485 xmlSchemaFormatQName(&qname,
2486 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2487 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2488 str1, str2, NULL);
2489 FREE_AND_NULL(qname);
2490 FREE_AND_NULL(msg);
2491 }
2492
2493 static int
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2494 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2495 xmlNodePtr node)
2496 {
2497 if (node != NULL)
2498 return (node->type);
2499 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2500 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2501 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2502 return (-1);
2503 }
2504
2505 static int
xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)2506 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2507 {
2508 switch (item->type) {
2509 case XML_SCHEMA_TYPE_COMPLEX:
2510 case XML_SCHEMA_TYPE_SIMPLE:
2511 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2512 return(1);
2513 break;
2514 case XML_SCHEMA_TYPE_GROUP:
2515 return (1);
2516 case XML_SCHEMA_TYPE_ELEMENT:
2517 if ( ((xmlSchemaElementPtr) item)->flags &
2518 XML_SCHEMAS_ELEM_GLOBAL)
2519 return(1);
2520 break;
2521 case XML_SCHEMA_TYPE_ATTRIBUTE:
2522 if ( ((xmlSchemaAttributePtr) item)->flags &
2523 XML_SCHEMAS_ATTR_GLOBAL)
2524 return(1);
2525 break;
2526 /* Note that attribute groups are always global. */
2527 default:
2528 return(1);
2529 }
2530 return (0);
2531 }
2532
2533 static void
xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,xmlSchemaTypePtr type,int displayValue)2534 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2535 xmlParserErrors error,
2536 xmlNodePtr node,
2537 const xmlChar *value,
2538 xmlSchemaTypePtr type,
2539 int displayValue)
2540 {
2541 xmlChar *msg = NULL;
2542
2543 xmlSchemaFormatNodeForError(&msg, actxt, node);
2544
2545 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2546 XML_ATTRIBUTE_NODE))
2547 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2548 else
2549 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2550 "value of ");
2551
2552 if (! xmlSchemaIsGlobalItem(type))
2553 msg = xmlStrcat(msg, BAD_CAST "the local ");
2554 else
2555 msg = xmlStrcat(msg, BAD_CAST "the ");
2556
2557 if (WXS_IS_ATOMIC(type))
2558 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2559 else if (WXS_IS_LIST(type))
2560 msg = xmlStrcat(msg, BAD_CAST "list type");
2561 else if (WXS_IS_UNION(type))
2562 msg = xmlStrcat(msg, BAD_CAST "union type");
2563
2564 if (xmlSchemaIsGlobalItem(type)) {
2565 xmlChar *str = NULL;
2566 msg = xmlStrcat(msg, BAD_CAST " '");
2567 if (type->builtInType != 0) {
2568 msg = xmlStrcat(msg, BAD_CAST "xs:");
2569 str = xmlStrdup(type->name);
2570 } else {
2571 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2572 if (!str)
2573 str = xmlStrdup(qName);
2574 }
2575 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2576 msg = xmlStrcat(msg, BAD_CAST "'");
2577 FREE_AND_NULL(str);
2578 }
2579 msg = xmlStrcat(msg, BAD_CAST ".\n");
2580 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2581 XML_ATTRIBUTE_NODE))
2582 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2583 else
2584 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2585 FREE_AND_NULL(msg)
2586 }
2587
2588 static const xmlChar *
xmlSchemaFormatErrorNodeQName(xmlChar ** str,xmlSchemaNodeInfoPtr ni,xmlNodePtr node)2589 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2590 xmlSchemaNodeInfoPtr ni,
2591 xmlNodePtr node)
2592 {
2593 if (node != NULL) {
2594 if (node->ns != NULL)
2595 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2596 else
2597 return (xmlSchemaFormatQName(str, NULL, node->name));
2598 } else if (ni != NULL)
2599 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2600 return (NULL);
2601 }
2602
2603 static void
xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlSchemaAttrInfoPtr ni,xmlNodePtr node)2604 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2605 xmlParserErrors error,
2606 xmlSchemaAttrInfoPtr ni,
2607 xmlNodePtr node)
2608 {
2609 xmlChar *msg = NULL, *str = NULL;
2610
2611 xmlSchemaFormatNodeForError(&msg, actxt, node);
2612 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2613 xmlSchemaErr(actxt, error, node, (const char *) msg,
2614 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2615 NULL);
2616 FREE_AND_NULL(str)
2617 FREE_AND_NULL(msg)
2618 }
2619
2620 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const char * message,int nbval,int nbneg,xmlChar ** values)2621 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2622 xmlParserErrors error,
2623 xmlNodePtr node,
2624 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2625 const char *message,
2626 int nbval,
2627 int nbneg,
2628 xmlChar **values)
2629 {
2630 xmlChar *str = NULL, *msg = NULL;
2631 xmlChar *localName, *nsName;
2632 const xmlChar *cur, *end;
2633 int i;
2634
2635 xmlSchemaFormatNodeForError(&msg, actxt, node);
2636 msg = xmlStrcat(msg, (const xmlChar *) message);
2637 msg = xmlStrcat(msg, BAD_CAST ".");
2638 /*
2639 * Note that is does not make sense to report that we have a
2640 * wildcard here, since the wildcard might be unfolded into
2641 * multiple transitions.
2642 */
2643 if (nbval + nbneg > 0) {
2644 if (nbval + nbneg > 1) {
2645 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2646 } else
2647 str = xmlStrdup(BAD_CAST " Expected is ( ");
2648 nsName = NULL;
2649
2650 for (i = 0; i < nbval + nbneg; i++) {
2651 cur = values[i];
2652 if (cur == NULL)
2653 continue;
2654 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2655 (cur[3] == ' ')) {
2656 cur += 4;
2657 str = xmlStrcat(str, BAD_CAST "##other");
2658 }
2659 /*
2660 * Get the local name.
2661 */
2662 localName = NULL;
2663
2664 end = cur;
2665 if (*end == '*') {
2666 localName = xmlStrdup(BAD_CAST "*");
2667 end++;
2668 } else {
2669 while ((*end != 0) && (*end != '|'))
2670 end++;
2671 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2672 }
2673 if (*end != 0) {
2674 end++;
2675 /*
2676 * Skip "*|*" if they come with negated expressions, since
2677 * they represent the same negated wildcard.
2678 */
2679 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2680 /*
2681 * Get the namespace name.
2682 */
2683 cur = end;
2684 if (*end == '*') {
2685 nsName = xmlStrdup(BAD_CAST "{*}");
2686 } else {
2687 while (*end != 0)
2688 end++;
2689
2690 if (i >= nbval)
2691 nsName = xmlStrdup(BAD_CAST "{##other:");
2692 else
2693 nsName = xmlStrdup(BAD_CAST "{");
2694
2695 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2696 nsName = xmlStrcat(nsName, BAD_CAST "}");
2697 }
2698 str = xmlStrcat(str, BAD_CAST nsName);
2699 FREE_AND_NULL(nsName)
2700 } else {
2701 FREE_AND_NULL(localName);
2702 continue;
2703 }
2704 }
2705 str = xmlStrcat(str, BAD_CAST localName);
2706 FREE_AND_NULL(localName);
2707
2708 if (i < nbval + nbneg -1)
2709 str = xmlStrcat(str, BAD_CAST ", ");
2710 }
2711 str = xmlStrcat(str, BAD_CAST " ).\n");
2712 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2713 FREE_AND_NULL(str)
2714 } else
2715 msg = xmlStrcat(msg, BAD_CAST "\n");
2716 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2717 xmlFree(msg);
2718 }
2719
2720 static void LIBXML_ATTR_FORMAT(8,0)
xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,unsigned long length,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet,const char * message,const xmlChar * str1,const xmlChar * str2)2721 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2722 xmlParserErrors error,
2723 xmlNodePtr node,
2724 const xmlChar *value,
2725 unsigned long length,
2726 xmlSchemaTypePtr type,
2727 xmlSchemaFacetPtr facet,
2728 const char *message,
2729 const xmlChar *str1,
2730 const xmlChar *str2)
2731 {
2732 xmlChar *str = NULL, *msg = NULL;
2733 xmlSchemaTypeType facetType;
2734 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2735
2736 xmlSchemaFormatNodeForError(&msg, actxt, node);
2737 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2738 facetType = XML_SCHEMA_FACET_ENUMERATION;
2739 /*
2740 * If enumerations are validated, one must not expect the
2741 * facet to be given.
2742 */
2743 } else
2744 facetType = facet->type;
2745 msg = xmlStrcat(msg, BAD_CAST "[");
2746 msg = xmlStrcat(msg, BAD_CAST "facet '");
2747 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2748 msg = xmlStrcat(msg, BAD_CAST "'] ");
2749 if (message == NULL) {
2750 /*
2751 * Use a default message.
2752 */
2753 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2754 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2755 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2756
2757 char len[25], actLen[25];
2758
2759 /* FIXME, TODO: What is the max expected string length of the
2760 * this value?
2761 */
2762 if (nodeType == XML_ATTRIBUTE_NODE)
2763 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2764 else
2765 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2766
2767 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2768 snprintf(actLen, 24, "%lu", length);
2769
2770 if (facetType == XML_SCHEMA_FACET_LENGTH)
2771 msg = xmlStrcat(msg,
2772 BAD_CAST "this differs from the allowed length of '%s'.\n");
2773 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2774 msg = xmlStrcat(msg,
2775 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2776 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2777 msg = xmlStrcat(msg,
2778 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2779
2780 if (nodeType == XML_ATTRIBUTE_NODE)
2781 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2782 value, (const xmlChar *) actLen, (const xmlChar *) len);
2783 else
2784 xmlSchemaErr(actxt, error, node, (const char *) msg,
2785 (const xmlChar *) actLen, (const xmlChar *) len);
2786
2787 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2788 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2789 "of the set {%s}.\n");
2790 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2791 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2792 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2793 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2794 "by the pattern '%s'.\n");
2795 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2796 facet->value);
2797 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2798 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2799 "minimum value allowed ('%s').\n");
2800 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2801 facet->value);
2802 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2803 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2804 "maximum value allowed ('%s').\n");
2805 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2806 facet->value);
2807 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2808 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2809 "'%s'.\n");
2810 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2811 facet->value);
2812 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2813 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2814 "'%s'.\n");
2815 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2816 facet->value);
2817 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2818 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2819 "digits than are allowed ('%s').\n");
2820 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2821 facet->value);
2822 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2823 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2824 "digits than are allowed ('%s').\n");
2825 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2826 facet->value);
2827 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2828 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2829 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2830 } else {
2831 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2832 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2833 }
2834 } else {
2835 msg = xmlStrcat(msg, (const xmlChar *) message);
2836 msg = xmlStrcat(msg, BAD_CAST ".\n");
2837 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2838 }
2839 FREE_AND_NULL(str)
2840 xmlFree(msg);
2841 }
2842
2843 #define VERROR(err, type, msg) \
2844 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2845
2846 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2847
2848 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2849 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2850
2851 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2852
2853
2854 /**
2855 * xmlSchemaPMissingAttrErr:
2856 * @ctxt: the schema validation context
2857 * @ownerItem: the owner as a schema object
2858 * @ownerElem: the owner as an element node
2859 * @node: the parent element node of the missing attribute node
2860 * @type: the corresponding type of the attribute node
2861 *
2862 * Reports an illegal attribute.
2863 */
2864 static void
xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const char * message)2865 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2866 xmlParserErrors error,
2867 xmlSchemaBasicItemPtr ownerItem,
2868 xmlNodePtr ownerElem,
2869 const char *name,
2870 const char *message)
2871 {
2872 xmlChar *des = NULL;
2873
2874 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2875
2876 if (message != NULL)
2877 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2878 else
2879 xmlSchemaPErr(ctxt, ownerElem, error,
2880 "%s: The attribute '%s' is required but missing.\n",
2881 BAD_CAST des, BAD_CAST name);
2882 FREE_AND_NULL(des);
2883 }
2884
2885
2886 /**
2887 * xmlSchemaPResCompAttrErr:
2888 * @ctxt: the schema validation context
2889 * @error: the error code
2890 * @ownerItem: the owner as a schema object
2891 * @ownerElem: the owner as an element node
2892 * @name: the name of the attribute holding the QName
2893 * @refName: the referenced local name
2894 * @refURI: the referenced namespace URI
2895 * @message: optional message
2896 *
2897 * Used to report QName attribute values that failed to resolve
2898 * to schema components.
2899 */
2900 static void
xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar * refName,const xmlChar * refURI,xmlSchemaTypeType refType,const char * refTypeStr)2901 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2902 xmlParserErrors error,
2903 xmlSchemaBasicItemPtr ownerItem,
2904 xmlNodePtr ownerElem,
2905 const char *name,
2906 const xmlChar *refName,
2907 const xmlChar *refURI,
2908 xmlSchemaTypeType refType,
2909 const char *refTypeStr)
2910 {
2911 xmlChar *des = NULL, *strA = NULL;
2912
2913 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2914 if (refTypeStr == NULL)
2915 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2916 xmlSchemaPErrExt(ctxt, ownerElem, error,
2917 NULL, NULL, NULL,
2918 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2919 "%s.\n", BAD_CAST des, BAD_CAST name,
2920 xmlSchemaFormatQName(&strA, refURI, refName),
2921 BAD_CAST refTypeStr, NULL);
2922 FREE_AND_NULL(des)
2923 FREE_AND_NULL(strA)
2924 }
2925
2926 /**
2927 * xmlSchemaPCustomAttrErr:
2928 * @ctxt: the schema parser context
2929 * @error: the error code
2930 * @ownerDes: the designation of the owner
2931 * @ownerItem: the owner as a schema object
2932 * @attr: the illegal attribute node
2933 *
2934 * Reports an illegal attribute during the parse.
2935 */
2936 static void
xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlChar ** ownerDes,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * msg)2937 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2938 xmlParserErrors error,
2939 xmlChar **ownerDes,
2940 xmlSchemaBasicItemPtr ownerItem,
2941 xmlAttrPtr attr,
2942 const char *msg)
2943 {
2944 xmlChar *des = NULL;
2945
2946 if (ownerDes == NULL)
2947 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2948 else if (*ownerDes == NULL) {
2949 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2950 des = *ownerDes;
2951 } else
2952 des = *ownerDes;
2953 if (attr == NULL) {
2954 xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2955 "%s, attribute '%s': %s.\n",
2956 BAD_CAST des, (const xmlChar *) "Unknown",
2957 (const xmlChar *) msg, NULL, NULL);
2958 } else {
2959 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2960 "%s, attribute '%s': %s.\n",
2961 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2962 }
2963 if (ownerDes == NULL)
2964 FREE_AND_NULL(des);
2965 }
2966
2967 /**
2968 * xmlSchemaPIllegalAttrErr:
2969 * @ctxt: the schema parser context
2970 * @error: the error code
2971 * @ownerItem: the attribute's owner item
2972 * @attr: the illegal attribute node
2973 *
2974 * Reports an illegal attribute during the parse.
2975 */
2976 static void
xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,xmlAttrPtr attr)2977 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2978 xmlParserErrors error,
2979 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2980 xmlAttrPtr attr)
2981 {
2982 xmlChar *strA = NULL, *strB = NULL;
2983
2984 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2985 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2986 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2987 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2988 NULL, NULL);
2989 FREE_AND_NULL(strA);
2990 FREE_AND_NULL(strB);
2991 }
2992
2993 /**
2994 * xmlSchemaPCustomErr:
2995 * @ctxt: the schema parser context
2996 * @error: the error code
2997 * @itemDes: the designation of the schema item
2998 * @item: the schema item
2999 * @itemElem: the node of the schema item
3000 * @message: the error message
3001 * @str1: an optional param for the error message
3002 * @str2: an optional param for the error message
3003 * @str3: an optional param for the error message
3004 *
3005 * Reports an error during parsing.
3006 */
3007 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)3008 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
3009 xmlParserErrors error,
3010 xmlSchemaBasicItemPtr item,
3011 xmlNodePtr itemElem,
3012 const char *message,
3013 const xmlChar *str1,
3014 const xmlChar *str2,
3015 const xmlChar *str3)
3016 {
3017 xmlChar *des = NULL, *msg = NULL;
3018
3019 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
3020 msg = xmlStrdup(BAD_CAST "%s: ");
3021 msg = xmlStrcat(msg, (const xmlChar *) message);
3022 msg = xmlStrcat(msg, BAD_CAST ".\n");
3023 if ((itemElem == NULL) && (item != NULL))
3024 itemElem = WXS_ITEM_NODE(item);
3025 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
3026 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
3027 FREE_AND_NULL(des);
3028 FREE_AND_NULL(msg);
3029 }
3030
3031 /**
3032 * xmlSchemaPCustomErr:
3033 * @ctxt: the schema parser context
3034 * @error: the error code
3035 * @itemDes: the designation of the schema item
3036 * @item: the schema item
3037 * @itemElem: the node of the schema item
3038 * @message: the error message
3039 * @str1: the optional param for the error message
3040 *
3041 * Reports an error during parsing.
3042 */
3043 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1)3044 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
3045 xmlParserErrors error,
3046 xmlSchemaBasicItemPtr item,
3047 xmlNodePtr itemElem,
3048 const char *message,
3049 const xmlChar *str1)
3050 {
3051 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
3052 str1, NULL, NULL);
3053 }
3054
3055 /**
3056 * xmlSchemaPAttrUseErr:
3057 * @ctxt: the schema parser context
3058 * @error: the error code
3059 * @itemDes: the designation of the schema type
3060 * @item: the schema type
3061 * @itemElem: the node of the schema type
3062 * @attr: the invalid schema attribute
3063 * @message: the error message
3064 * @str1: the optional param for the error message
3065 *
3066 * Reports an attribute use error during parsing.
3067 */
3068 static void LIBXML_ATTR_FORMAT(6,0)
xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaBasicItemPtr ownerItem,const xmlSchemaAttributeUsePtr attruse,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)3069 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3070 xmlParserErrors error,
3071 xmlNodePtr node,
3072 xmlSchemaBasicItemPtr ownerItem,
3073 const xmlSchemaAttributeUsePtr attruse,
3074 const char *message,
3075 const xmlChar *str1, const xmlChar *str2,
3076 const xmlChar *str3,const xmlChar *str4)
3077 {
3078 xmlChar *str = NULL, *msg = NULL;
3079
3080 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3081 msg = xmlStrcat(msg, BAD_CAST ", ");
3082 msg = xmlStrcat(msg,
3083 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3084 WXS_BASIC_CAST attruse, NULL));
3085 FREE_AND_NULL(str);
3086 msg = xmlStrcat(msg, BAD_CAST ": ");
3087 msg = xmlStrcat(msg, (const xmlChar *) message);
3088 msg = xmlStrcat(msg, BAD_CAST ".\n");
3089 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3090 (const char *) msg, str1, str2, str3, str4);
3091 xmlFree(msg);
3092 }
3093
3094 /**
3095 * xmlSchemaPIllegalFacetAtomicErr:
3096 * @ctxt: the schema parser context
3097 * @error: the error code
3098 * @type: the schema type
3099 * @baseType: the base type of type
3100 * @facet: the illegal facet
3101 *
3102 * Reports an illegal facet for atomic simple types.
3103 */
3104 static void
xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,xmlSchemaFacetPtr facet)3105 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3106 xmlParserErrors error,
3107 xmlSchemaTypePtr type,
3108 xmlSchemaTypePtr baseType,
3109 xmlSchemaFacetPtr facet)
3110 {
3111 xmlChar *des = NULL, *strT = NULL;
3112
3113 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3114 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3115 "%s: The facet '%s' is not allowed on types derived from the "
3116 "type %s.\n",
3117 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3118 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3119 NULL, NULL);
3120 FREE_AND_NULL(des);
3121 FREE_AND_NULL(strT);
3122 }
3123
3124 /**
3125 * xmlSchemaPIllegalFacetListUnionErr:
3126 * @ctxt: the schema parser context
3127 * @error: the error code
3128 * @itemDes: the designation of the schema item involved
3129 * @item: the schema item involved
3130 * @facet: the illegal facet
3131 *
3132 * Reports an illegal facet for <list> and <union>.
3133 */
3134 static void
xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet)3135 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3136 xmlParserErrors error,
3137 xmlSchemaTypePtr type,
3138 xmlSchemaFacetPtr facet)
3139 {
3140 xmlChar *des = NULL;
3141
3142 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3143 type->node);
3144 xmlSchemaPErr(ctxt, type->node, error,
3145 "%s: The facet '%s' is not allowed.\n",
3146 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3147 FREE_AND_NULL(des);
3148 }
3149
3150 /**
3151 * xmlSchemaPMutualExclAttrErr:
3152 * @ctxt: the schema validation context
3153 * @error: the error code
3154 * @elemDes: the designation of the parent element node
3155 * @attr: the bad attribute node
3156 * @type: the corresponding type of the attribute node
3157 *
3158 * Reports an illegal attribute.
3159 */
3160 static void
xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * name1,const char * name2)3161 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3162 xmlParserErrors error,
3163 xmlSchemaBasicItemPtr ownerItem,
3164 xmlAttrPtr attr,
3165 const char *name1,
3166 const char *name2)
3167 {
3168 xmlChar *des = NULL;
3169
3170 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3171 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3172 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3173 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3174 FREE_AND_NULL(des);
3175 }
3176
3177 /**
3178 * xmlSchemaPSimpleTypeErr:
3179 * @ctxt: the schema validation context
3180 * @error: the error code
3181 * @type: the type specifier
3182 * @ownerItem: the schema object if existent
3183 * @node: the validated node
3184 * @value: the validated value
3185 *
3186 * Reports a simple type validation error.
3187 * TODO: Should this report the value of an element as well?
3188 */
3189 static void LIBXML_ATTR_FORMAT(8,0)
xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,xmlNodePtr node,xmlSchemaTypePtr type,const char * expected,const xmlChar * value,const char * message,const xmlChar * str1,const xmlChar * str2)3190 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3191 xmlParserErrors error,
3192 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3193 xmlNodePtr node,
3194 xmlSchemaTypePtr type,
3195 const char *expected,
3196 const xmlChar *value,
3197 const char *message,
3198 const xmlChar *str1,
3199 const xmlChar *str2)
3200 {
3201 xmlChar *msg = NULL;
3202
3203 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3204 if (message == NULL) {
3205 /*
3206 * Use default messages.
3207 */
3208 if (type != NULL) {
3209 if (node->type == XML_ATTRIBUTE_NODE)
3210 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3211 else
3212 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3213 "valid value of ");
3214 if (! xmlSchemaIsGlobalItem(type))
3215 msg = xmlStrcat(msg, BAD_CAST "the local ");
3216 else
3217 msg = xmlStrcat(msg, BAD_CAST "the ");
3218
3219 if (WXS_IS_ATOMIC(type))
3220 msg = xmlStrcat(msg, BAD_CAST "atomic type");
3221 else if (WXS_IS_LIST(type))
3222 msg = xmlStrcat(msg, BAD_CAST "list type");
3223 else if (WXS_IS_UNION(type))
3224 msg = xmlStrcat(msg, BAD_CAST "union type");
3225
3226 if (xmlSchemaIsGlobalItem(type)) {
3227 xmlChar *str = NULL;
3228 msg = xmlStrcat(msg, BAD_CAST " '");
3229 if (type->builtInType != 0) {
3230 msg = xmlStrcat(msg, BAD_CAST "xs:");
3231 str = xmlStrdup(type->name);
3232 } else {
3233 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3234 if (!str)
3235 str = xmlStrdup(qName);
3236 }
3237 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3238 msg = xmlStrcat(msg, BAD_CAST "'.");
3239 FREE_AND_NULL(str);
3240 }
3241 } else {
3242 if (node->type == XML_ATTRIBUTE_NODE)
3243 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3244 else
3245 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3246 "valid.");
3247 }
3248 if (expected) {
3249 xmlChar *expectedEscaped = xmlCharStrdup(expected);
3250 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3251 msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3252 FREE_AND_NULL(expectedEscaped);
3253 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3254 } else
3255 msg = xmlStrcat(msg, BAD_CAST "\n");
3256 if (node->type == XML_ATTRIBUTE_NODE)
3257 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3258 else
3259 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3260 } else {
3261 msg = xmlStrcat(msg, BAD_CAST message);
3262 msg = xmlStrcat(msg, BAD_CAST ".\n");
3263 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3264 (const char*) msg, str1, str2, NULL, NULL, NULL);
3265 }
3266 /* Cleanup. */
3267 FREE_AND_NULL(msg)
3268 }
3269
3270 /**
3271 * xmlSchemaPContentErr:
3272 * @ctxt: the schema parser context
3273 * @error: the error code
3274 * @ownerItem: the owner item of the holder of the content
3275 * @ownerElem: the node of the holder of the content
3276 * @child: the invalid child node
3277 * @message: the optional error message
3278 * @content: the optional string describing the correct content
3279 *
3280 * Reports an error concerning the content of a schema element.
3281 */
3282 static void
xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,xmlNodePtr child,const char * message,const char * content)3283 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3284 xmlParserErrors error,
3285 xmlSchemaBasicItemPtr ownerItem,
3286 xmlNodePtr ownerElem,
3287 xmlNodePtr child,
3288 const char *message,
3289 const char *content)
3290 {
3291 xmlChar *des = NULL;
3292
3293 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3294 if (message != NULL)
3295 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3296 "%s: %s.\n",
3297 BAD_CAST des, BAD_CAST message);
3298 else {
3299 if (content != NULL) {
3300 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3301 "%s: The content is not valid. Expected is %s.\n",
3302 BAD_CAST des, BAD_CAST content);
3303 } else {
3304 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3305 "%s: The content is not valid.\n",
3306 BAD_CAST des, NULL);
3307 }
3308 }
3309 FREE_AND_NULL(des)
3310 }
3311
3312 /************************************************************************
3313 * *
3314 * Streamable error functions *
3315 * *
3316 ************************************************************************/
3317
3318
3319
3320
3321 /************************************************************************
3322 * *
3323 * Validation helper functions *
3324 * *
3325 ************************************************************************/
3326
3327
3328 /************************************************************************
3329 * *
3330 * Allocation functions *
3331 * *
3332 ************************************************************************/
3333
3334 /**
3335 * xmlSchemaNewSchemaForParserCtxt:
3336 * @ctxt: a schema validation context
3337 *
3338 * Allocate a new Schema structure.
3339 *
3340 * Returns the newly allocated structure or NULL in case or error
3341 */
3342 static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)3343 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3344 {
3345 xmlSchemaPtr ret;
3346
3347 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3348 if (ret == NULL) {
3349 xmlSchemaPErrMemory(ctxt);
3350 return (NULL);
3351 }
3352 memset(ret, 0, sizeof(xmlSchema));
3353 ret->dict = ctxt->dict;
3354 xmlDictReference(ret->dict);
3355
3356 return (ret);
3357 }
3358
3359 /**
3360 * xmlSchemaNewFacet:
3361 *
3362 * Allocate a new Facet structure.
3363 *
3364 * Returns the newly allocated structure or NULL in case or error
3365 */
3366 xmlSchemaFacetPtr
xmlSchemaNewFacet(void)3367 xmlSchemaNewFacet(void)
3368 {
3369 xmlSchemaFacetPtr ret;
3370
3371 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3372 if (ret == NULL) {
3373 return (NULL);
3374 }
3375 memset(ret, 0, sizeof(xmlSchemaFacet));
3376
3377 return (ret);
3378 }
3379
3380 /**
3381 * xmlSchemaNewAnnot:
3382 * @ctxt: a schema validation context
3383 * @node: a node
3384 *
3385 * Allocate a new annotation structure.
3386 *
3387 * Returns the newly allocated structure or NULL in case or error
3388 */
3389 static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)3390 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3391 {
3392 xmlSchemaAnnotPtr ret;
3393
3394 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3395 if (ret == NULL) {
3396 xmlSchemaPErrMemory(ctxt);
3397 return (NULL);
3398 }
3399 memset(ret, 0, sizeof(xmlSchemaAnnot));
3400 ret->content = node;
3401 return (ret);
3402 }
3403
3404 static xmlSchemaItemListPtr
xmlSchemaItemListCreate(void)3405 xmlSchemaItemListCreate(void)
3406 {
3407 xmlSchemaItemListPtr ret;
3408
3409 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3410 if (ret == NULL) {
3411 xmlSchemaPErrMemory(NULL);
3412 return (NULL);
3413 }
3414 memset(ret, 0, sizeof(xmlSchemaItemList));
3415 return (ret);
3416 }
3417
3418 static void
xmlSchemaItemListClear(xmlSchemaItemListPtr list)3419 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3420 {
3421 if (list->items != NULL) {
3422 xmlFree(list->items);
3423 list->items = NULL;
3424 }
3425 list->nbItems = 0;
3426 list->sizeItems = 0;
3427 }
3428
3429 static int
xmlSchemaItemListAdd(xmlSchemaItemListPtr list,void * item)3430 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3431 {
3432 if (list->sizeItems <= list->nbItems) {
3433 void **tmp;
3434 size_t newSize = list->sizeItems == 0 ? 20 : list->sizeItems * 2;
3435
3436 tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *));
3437 if (tmp == NULL) {
3438 xmlSchemaPErrMemory(NULL);
3439 return(-1);
3440 }
3441 list->items = tmp;
3442 list->sizeItems = newSize;
3443 }
3444 list->items[list->nbItems++] = item;
3445 return(0);
3446 }
3447
3448 static int
xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,int initialSize,void * item)3449 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3450 int initialSize,
3451 void *item)
3452 {
3453 if (list->items == NULL) {
3454 if (initialSize <= 0)
3455 initialSize = 1;
3456 list->items = (void **) xmlMalloc(
3457 initialSize * sizeof(void *));
3458 if (list->items == NULL) {
3459 xmlSchemaPErrMemory(NULL);
3460 return(-1);
3461 }
3462 list->sizeItems = initialSize;
3463 } else if (list->sizeItems <= list->nbItems) {
3464 void **tmp;
3465
3466 list->sizeItems *= 2;
3467 tmp = (void **) xmlRealloc(list->items,
3468 list->sizeItems * sizeof(void *));
3469 if (tmp == NULL) {
3470 xmlSchemaPErrMemory(NULL);
3471 list->sizeItems /= 2;
3472 return(-1);
3473 }
3474 list->items = tmp;
3475 }
3476 list->items[list->nbItems++] = item;
3477 return(0);
3478 }
3479
3480 static int
xmlSchemaItemListInsert(xmlSchemaItemListPtr list,void * item,int idx)3481 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3482 {
3483 if (list->sizeItems <= list->nbItems) {
3484 void **tmp;
3485 size_t newSize = list->sizeItems == 0 ? 20 : list->sizeItems * 2;
3486
3487 tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *));
3488 if (tmp == NULL) {
3489 xmlSchemaPErrMemory(NULL);
3490 return(-1);
3491 }
3492 list->items = tmp;
3493 list->sizeItems = newSize;
3494 }
3495 /*
3496 * Just append if the index is greater/equal than the item count.
3497 */
3498 if (idx >= list->nbItems) {
3499 list->items[list->nbItems++] = item;
3500 } else {
3501 int i;
3502 for (i = list->nbItems; i > idx; i--)
3503 list->items[i] = list->items[i-1];
3504 list->items[idx] = item;
3505 list->nbItems++;
3506 }
3507 return(0);
3508 }
3509
3510 #if 0 /* enable if ever needed */
3511 static int
3512 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3513 int initialSize,
3514 void *item,
3515 int idx)
3516 {
3517 if (list->items == NULL) {
3518 if (initialSize <= 0)
3519 initialSize = 1;
3520 list->items = (void **) xmlMalloc(
3521 initialSize * sizeof(void *));
3522 if (list->items == NULL) {
3523 xmlSchemaPErrMemory(NULL);
3524 return(-1);
3525 }
3526 list->sizeItems = initialSize;
3527 } else if (list->sizeItems <= list->nbItems) {
3528 list->sizeItems *= 2;
3529 list->items = (void **) xmlRealloc(list->items,
3530 list->sizeItems * sizeof(void *));
3531 if (list->items == NULL) {
3532 xmlSchemaPErrMemory(NULL);
3533 list->sizeItems = 0;
3534 return(-1);
3535 }
3536 }
3537 /*
3538 * Just append if the index is greater/equal than the item count.
3539 */
3540 if (idx >= list->nbItems) {
3541 list->items[list->nbItems++] = item;
3542 } else {
3543 int i;
3544 for (i = list->nbItems; i > idx; i--)
3545 list->items[i] = list->items[i-1];
3546 list->items[idx] = item;
3547 list->nbItems++;
3548 }
3549 return(0);
3550 }
3551 #endif
3552
3553 static int
xmlSchemaItemListRemove(xmlSchemaItemListPtr list,int idx)3554 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3555 {
3556 int i;
3557 if ((list->items == NULL) || (idx >= list->nbItems))
3558 return(-1);
3559
3560 if (list->nbItems == 1) {
3561 /* TODO: Really free the list? */
3562 xmlFree(list->items);
3563 list->items = NULL;
3564 list->nbItems = 0;
3565 list->sizeItems = 0;
3566 } else if (list->nbItems -1 == idx) {
3567 list->nbItems--;
3568 } else {
3569 for (i = idx; i < list->nbItems -1; i++)
3570 list->items[i] = list->items[i+1];
3571 list->nbItems--;
3572 }
3573 return(0);
3574 }
3575
3576 /**
3577 * xmlSchemaItemListFree:
3578 * @annot: a schema type structure
3579 *
3580 * Deallocate a annotation structure
3581 */
3582 static void
xmlSchemaItemListFree(xmlSchemaItemListPtr list)3583 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3584 {
3585 if (list == NULL)
3586 return;
3587 if (list->items != NULL)
3588 xmlFree(list->items);
3589 xmlFree(list);
3590 }
3591
3592 static void
xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)3593 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3594 {
3595 if (bucket == NULL)
3596 return;
3597 if (bucket->globals != NULL) {
3598 xmlSchemaComponentListFree(bucket->globals);
3599 xmlSchemaItemListFree(bucket->globals);
3600 }
3601 if (bucket->locals != NULL) {
3602 xmlSchemaComponentListFree(bucket->locals);
3603 xmlSchemaItemListFree(bucket->locals);
3604 }
3605 if (bucket->relations != NULL) {
3606 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3607 do {
3608 prev = cur;
3609 cur = cur->next;
3610 xmlFree(prev);
3611 } while (cur != NULL);
3612 }
3613 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3614 xmlFreeDoc(bucket->doc);
3615 }
3616 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3617 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3618 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3619 }
3620 xmlFree(bucket);
3621 }
3622
3623 static void
xmlSchemaBucketFreeEntry(void * bucket,const xmlChar * name ATTRIBUTE_UNUSED)3624 xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3625 {
3626 xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3627 }
3628
3629 static xmlSchemaBucketPtr
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * targetNamespace)3630 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3631 int type, const xmlChar *targetNamespace)
3632 {
3633 xmlSchemaBucketPtr ret;
3634 int size;
3635 xmlSchemaPtr mainSchema;
3636
3637 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3638 PERROR_INT("xmlSchemaBucketCreate",
3639 "no main schema on constructor");
3640 return(NULL);
3641 }
3642 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3643 /* Create the schema bucket. */
3644 if (WXS_IS_BUCKET_INCREDEF(type))
3645 size = sizeof(xmlSchemaInclude);
3646 else
3647 size = sizeof(xmlSchemaImport);
3648 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3649 if (ret == NULL) {
3650 xmlSchemaPErrMemory(NULL);
3651 return(NULL);
3652 }
3653 memset(ret, 0, size);
3654 ret->targetNamespace = targetNamespace;
3655 ret->type = type;
3656 ret->globals = xmlSchemaItemListCreate();
3657 if (ret->globals == NULL) {
3658 xmlSchemaBucketFree(ret);
3659 return(NULL);
3660 }
3661 ret->locals = xmlSchemaItemListCreate();
3662 if (ret->locals == NULL) {
3663 xmlSchemaBucketFree(ret);
3664 return(NULL);
3665 }
3666 /*
3667 * The following will assure that only the first bucket is marked as
3668 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3669 * For each following import buckets an xmlSchema will be created.
3670 * An xmlSchema will be created for every distinct targetNamespace.
3671 * We assign the targetNamespace to the schemata here.
3672 */
3673 if (! WXS_HAS_BUCKETS(pctxt)) {
3674 if (WXS_IS_BUCKET_INCREDEF(type)) {
3675 PERROR_INT("xmlSchemaBucketCreate",
3676 "first bucket but it's an include or redefine");
3677 xmlSchemaBucketFree(ret);
3678 return(NULL);
3679 }
3680 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3681 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3682 /* Point to the *main* schema. */
3683 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3684 WXS_IMPBUCKET(ret)->schema = mainSchema;
3685 /*
3686 * Ensure that the main schema gets a targetNamespace.
3687 */
3688 mainSchema->targetNamespace = targetNamespace;
3689 } else {
3690 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3691 PERROR_INT("xmlSchemaBucketCreate",
3692 "main bucket but it's not the first one");
3693 xmlSchemaBucketFree(ret);
3694 return(NULL);
3695 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3696 /*
3697 * Create a schema for imports and assign the
3698 * targetNamespace.
3699 */
3700 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3701 if (WXS_IMPBUCKET(ret)->schema == NULL) {
3702 xmlSchemaBucketFree(ret);
3703 return(NULL);
3704 }
3705 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3706 }
3707 }
3708 if (WXS_IS_BUCKET_IMPMAIN(type)) {
3709 int res;
3710 /*
3711 * Imports go into the "schemasImports" slot of the main *schema*.
3712 * Note that we create an import entry for the main schema as well; i.e.,
3713 * even if there's only one schema, we'll get an import.
3714 */
3715 if (mainSchema->schemasImports == NULL) {
3716 mainSchema->schemasImports = xmlHashCreateDict(5,
3717 WXS_CONSTRUCTOR(pctxt)->dict);
3718 if (mainSchema->schemasImports == NULL) {
3719 xmlSchemaBucketFree(ret);
3720 return(NULL);
3721 }
3722 }
3723 if (targetNamespace == NULL)
3724 res = xmlHashAddEntry(mainSchema->schemasImports,
3725 XML_SCHEMAS_NO_NAMESPACE, ret);
3726 else
3727 res = xmlHashAddEntry(mainSchema->schemasImports,
3728 targetNamespace, ret);
3729 if (res != 0) {
3730 PERROR_INT("xmlSchemaBucketCreate",
3731 "failed to add the schema bucket to the hash");
3732 xmlSchemaBucketFree(ret);
3733 return(NULL);
3734 }
3735 } else {
3736 /* Set the @ownerImport of an include bucket. */
3737 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3738 WXS_INCBUCKET(ret)->ownerImport =
3739 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3740 else
3741 WXS_INCBUCKET(ret)->ownerImport =
3742 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3743
3744 /* Includes got into the "includes" slot of the *main* schema. */
3745 if (mainSchema->includes == NULL) {
3746 mainSchema->includes = xmlSchemaItemListCreate();
3747 if (mainSchema->includes == NULL) {
3748 xmlSchemaBucketFree(ret);
3749 return(NULL);
3750 }
3751 }
3752 if (xmlSchemaItemListAdd(mainSchema->includes, ret) < 0) {
3753 xmlSchemaBucketFree(ret);
3754 return(NULL);
3755 }
3756 }
3757 /*
3758 * Add to list of all buckets; this is used for lookup
3759 * during schema construction time only.
3760 */
3761 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3762 return(NULL);
3763 return(ret);
3764 }
3765
3766 static int
xmlSchemaAddItemSize(xmlSchemaItemListPtr * list,int initialSize,void * item)3767 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3768 {
3769 if (*list == NULL) {
3770 *list = xmlSchemaItemListCreate();
3771 if (*list == NULL)
3772 return(-1);
3773 }
3774 return(xmlSchemaItemListAddSize(*list, initialSize, item));
3775 }
3776
3777 /**
3778 * xmlSchemaFreeAnnot:
3779 * @annot: a schema type structure
3780 *
3781 * Deallocate a annotation structure
3782 */
3783 static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)3784 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3785 {
3786 if (annot == NULL)
3787 return;
3788 if (annot->next == NULL) {
3789 xmlFree(annot);
3790 } else {
3791 xmlSchemaAnnotPtr prev;
3792
3793 do {
3794 prev = annot;
3795 annot = annot->next;
3796 xmlFree(prev);
3797 } while (annot != NULL);
3798 }
3799 }
3800
3801 /**
3802 * xmlSchemaFreeNotation:
3803 * @schema: a schema notation structure
3804 *
3805 * Deallocate a Schema Notation structure.
3806 */
3807 static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)3808 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3809 {
3810 if (nota == NULL)
3811 return;
3812 if (nota->annot != NULL)
3813 xmlSchemaFreeAnnot(nota->annot);
3814 xmlFree(nota);
3815 }
3816
3817 /**
3818 * xmlSchemaFreeAttribute:
3819 * @attr: an attribute declaration
3820 *
3821 * Deallocates an attribute declaration structure.
3822 */
3823 static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)3824 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3825 {
3826 if (attr == NULL)
3827 return;
3828 if (attr->annot != NULL)
3829 xmlSchemaFreeAnnot(attr->annot);
3830 if (attr->defVal != NULL)
3831 xmlSchemaFreeValue(attr->defVal);
3832 xmlFree(attr);
3833 }
3834
3835 /**
3836 * xmlSchemaFreeAttributeUse:
3837 * @use: an attribute use
3838 *
3839 * Deallocates an attribute use structure.
3840 */
3841 static void
xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)3842 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3843 {
3844 if (use == NULL)
3845 return;
3846 if (use->annot != NULL)
3847 xmlSchemaFreeAnnot(use->annot);
3848 if (use->defVal != NULL)
3849 xmlSchemaFreeValue(use->defVal);
3850 xmlFree(use);
3851 }
3852
3853 /**
3854 * xmlSchemaFreeAttributeUseProhib:
3855 * @prohib: an attribute use prohibition
3856 *
3857 * Deallocates an attribute use structure.
3858 */
3859 static void
xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)3860 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3861 {
3862 if (prohib == NULL)
3863 return;
3864 xmlFree(prohib);
3865 }
3866
3867 /**
3868 * xmlSchemaFreeWildcardNsSet:
3869 * set: a schema wildcard namespace
3870 *
3871 * Deallocates a list of wildcard constraint structures.
3872 */
3873 static void
xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)3874 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3875 {
3876 xmlSchemaWildcardNsPtr next;
3877
3878 while (set != NULL) {
3879 next = set->next;
3880 xmlFree(set);
3881 set = next;
3882 }
3883 }
3884
3885 /**
3886 * xmlSchemaFreeWildcard:
3887 * @wildcard: a wildcard structure
3888 *
3889 * Deallocates a wildcard structure.
3890 */
3891 void
xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)3892 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3893 {
3894 if (wildcard == NULL)
3895 return;
3896 if (wildcard->annot != NULL)
3897 xmlSchemaFreeAnnot(wildcard->annot);
3898 if (wildcard->nsSet != NULL)
3899 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3900 if (wildcard->negNsSet != NULL)
3901 xmlFree(wildcard->negNsSet);
3902 xmlFree(wildcard);
3903 }
3904
3905 /**
3906 * xmlSchemaFreeAttributeGroup:
3907 * @schema: a schema attribute group structure
3908 *
3909 * Deallocate a Schema Attribute Group structure.
3910 */
3911 static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)3912 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3913 {
3914 if (attrGr == NULL)
3915 return;
3916 if (attrGr->annot != NULL)
3917 xmlSchemaFreeAnnot(attrGr->annot);
3918 if (attrGr->attrUses != NULL)
3919 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3920 xmlFree(attrGr);
3921 }
3922
3923 /**
3924 * xmlSchemaFreeQNameRef:
3925 * @item: a QName reference structure
3926 *
3927 * Deallocatea a QName reference structure.
3928 */
3929 static void
xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)3930 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3931 {
3932 xmlFree(item);
3933 }
3934
3935 /**
3936 * xmlSchemaFreeTypeLinkList:
3937 * @alink: a type link
3938 *
3939 * Deallocate a list of types.
3940 */
3941 static void
xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)3942 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3943 {
3944 xmlSchemaTypeLinkPtr next;
3945
3946 while (link != NULL) {
3947 next = link->next;
3948 xmlFree(link);
3949 link = next;
3950 }
3951 }
3952
3953 static void
xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)3954 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3955 {
3956 xmlSchemaIDCStateObjPtr next;
3957 while (sto != NULL) {
3958 next = sto->next;
3959 if (sto->history != NULL)
3960 xmlFree(sto->history);
3961 if (sto->xpathCtxt != NULL)
3962 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3963 xmlFree(sto);
3964 sto = next;
3965 }
3966 }
3967
3968 /**
3969 * xmlSchemaFreeIDC:
3970 * @idc: a identity-constraint definition
3971 *
3972 * Deallocates an identity-constraint definition.
3973 */
3974 static void
xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)3975 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3976 {
3977 xmlSchemaIDCSelectPtr cur, prev;
3978
3979 if (idcDef == NULL)
3980 return;
3981 if (idcDef->annot != NULL)
3982 xmlSchemaFreeAnnot(idcDef->annot);
3983 /* Selector */
3984 if (idcDef->selector != NULL) {
3985 if (idcDef->selector->xpathComp != NULL)
3986 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3987 xmlFree(idcDef->selector);
3988 }
3989 /* Fields */
3990 if (idcDef->fields != NULL) {
3991 cur = idcDef->fields;
3992 do {
3993 prev = cur;
3994 cur = cur->next;
3995 if (prev->xpathComp != NULL)
3996 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3997 xmlFree(prev);
3998 } while (cur != NULL);
3999 }
4000 xmlFree(idcDef);
4001 }
4002
4003 /**
4004 * xmlSchemaFreeElement:
4005 * @schema: a schema element structure
4006 *
4007 * Deallocate a Schema Element structure.
4008 */
4009 static void
xmlSchemaFreeElement(xmlSchemaElementPtr elem)4010 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
4011 {
4012 if (elem == NULL)
4013 return;
4014 if (elem->annot != NULL)
4015 xmlSchemaFreeAnnot(elem->annot);
4016 if (elem->contModel != NULL)
4017 xmlRegFreeRegexp(elem->contModel);
4018 if (elem->defVal != NULL)
4019 xmlSchemaFreeValue(elem->defVal);
4020 xmlFree(elem);
4021 }
4022
4023 /**
4024 * xmlSchemaFreeFacet:
4025 * @facet: a schema facet structure
4026 *
4027 * Deallocate a Schema Facet structure.
4028 */
4029 void
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)4030 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
4031 {
4032 if (facet == NULL)
4033 return;
4034 if (facet->val != NULL)
4035 xmlSchemaFreeValue(facet->val);
4036 if (facet->regexp != NULL)
4037 xmlRegFreeRegexp(facet->regexp);
4038 if (facet->annot != NULL)
4039 xmlSchemaFreeAnnot(facet->annot);
4040 xmlFree(facet);
4041 }
4042
4043 /**
4044 * xmlSchemaFreeType:
4045 * @type: a schema type structure
4046 *
4047 * Deallocate a Schema Type structure.
4048 */
4049 void
xmlSchemaFreeType(xmlSchemaTypePtr type)4050 xmlSchemaFreeType(xmlSchemaTypePtr type)
4051 {
4052 if (type == NULL)
4053 return;
4054 if (type->annot != NULL)
4055 xmlSchemaFreeAnnot(type->annot);
4056 if (type->facets != NULL) {
4057 xmlSchemaFacetPtr facet, next;
4058
4059 facet = type->facets;
4060 while (facet != NULL) {
4061 next = facet->next;
4062 xmlSchemaFreeFacet(facet);
4063 facet = next;
4064 }
4065 }
4066 if (type->attrUses != NULL)
4067 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4068 if (type->memberTypes != NULL)
4069 xmlSchemaFreeTypeLinkList(type->memberTypes);
4070 if (type->facetSet != NULL) {
4071 xmlSchemaFacetLinkPtr next, link;
4072
4073 link = type->facetSet;
4074 do {
4075 next = link->next;
4076 xmlFree(link);
4077 link = next;
4078 } while (link != NULL);
4079 }
4080 if (type->contModel != NULL)
4081 xmlRegFreeRegexp(type->contModel);
4082 xmlFree(type);
4083 }
4084
4085 /**
4086 * xmlSchemaFreeModelGroupDef:
4087 * @item: a schema model group definition
4088 *
4089 * Deallocates a schema model group definition.
4090 */
4091 static void
xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)4092 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4093 {
4094 if (item->annot != NULL)
4095 xmlSchemaFreeAnnot(item->annot);
4096 xmlFree(item);
4097 }
4098
4099 /**
4100 * xmlSchemaFreeModelGroup:
4101 * @item: a schema model group
4102 *
4103 * Deallocates a schema model group structure.
4104 */
4105 static void
xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)4106 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4107 {
4108 if (item->annot != NULL)
4109 xmlSchemaFreeAnnot(item->annot);
4110 xmlFree(item);
4111 }
4112
4113 static void
xmlSchemaComponentListFree(xmlSchemaItemListPtr list)4114 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4115 {
4116 if ((list == NULL) || (list->nbItems == 0))
4117 return;
4118 {
4119 xmlSchemaTreeItemPtr item;
4120 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4121 int i;
4122
4123 for (i = 0; i < list->nbItems; i++) {
4124 item = items[i];
4125 if (item == NULL)
4126 continue;
4127 switch (item->type) {
4128 case XML_SCHEMA_TYPE_SIMPLE:
4129 case XML_SCHEMA_TYPE_COMPLEX:
4130 xmlSchemaFreeType((xmlSchemaTypePtr) item);
4131 break;
4132 case XML_SCHEMA_TYPE_ATTRIBUTE:
4133 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4134 break;
4135 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4136 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4137 break;
4138 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4139 xmlSchemaFreeAttributeUseProhib(
4140 (xmlSchemaAttributeUseProhibPtr) item);
4141 break;
4142 case XML_SCHEMA_TYPE_ELEMENT:
4143 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4144 break;
4145 case XML_SCHEMA_TYPE_PARTICLE:
4146 if (item->annot != NULL)
4147 xmlSchemaFreeAnnot(item->annot);
4148 xmlFree(item);
4149 break;
4150 case XML_SCHEMA_TYPE_SEQUENCE:
4151 case XML_SCHEMA_TYPE_CHOICE:
4152 case XML_SCHEMA_TYPE_ALL:
4153 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4154 break;
4155 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4156 xmlSchemaFreeAttributeGroup(
4157 (xmlSchemaAttributeGroupPtr) item);
4158 break;
4159 case XML_SCHEMA_TYPE_GROUP:
4160 xmlSchemaFreeModelGroupDef(
4161 (xmlSchemaModelGroupDefPtr) item);
4162 break;
4163 case XML_SCHEMA_TYPE_ANY:
4164 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4165 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4166 break;
4167 case XML_SCHEMA_TYPE_IDC_KEY:
4168 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4169 case XML_SCHEMA_TYPE_IDC_KEYREF:
4170 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4171 break;
4172 case XML_SCHEMA_TYPE_NOTATION:
4173 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4174 break;
4175 case XML_SCHEMA_EXTRA_QNAMEREF:
4176 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4177 break;
4178 default:
4179 /* TODO: This should never be hit. */
4180 break;
4181 }
4182 }
4183 list->nbItems = 0;
4184 }
4185 }
4186
4187 /**
4188 * xmlSchemaFree:
4189 * @schema: a schema structure
4190 *
4191 * Deallocate a Schema structure.
4192 */
4193 void
xmlSchemaFree(xmlSchemaPtr schema)4194 xmlSchemaFree(xmlSchemaPtr schema)
4195 {
4196 if (schema == NULL)
4197 return;
4198 /*
4199 * Note that those slots are not responsible for freeing
4200 * schema components anymore; this will now be done by
4201 * the schema buckets.
4202 */
4203 if (schema->notaDecl != NULL)
4204 xmlHashFree(schema->notaDecl, NULL);
4205 if (schema->attrDecl != NULL)
4206 xmlHashFree(schema->attrDecl, NULL);
4207 if (schema->attrgrpDecl != NULL)
4208 xmlHashFree(schema->attrgrpDecl, NULL);
4209 if (schema->elemDecl != NULL)
4210 xmlHashFree(schema->elemDecl, NULL);
4211 if (schema->typeDecl != NULL)
4212 xmlHashFree(schema->typeDecl, NULL);
4213 if (schema->groupDecl != NULL)
4214 xmlHashFree(schema->groupDecl, NULL);
4215 if (schema->idcDef != NULL)
4216 xmlHashFree(schema->idcDef, NULL);
4217
4218 if (schema->schemasImports != NULL)
4219 xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4220 if (schema->includes != NULL) {
4221 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4222 int i;
4223 for (i = 0; i < list->nbItems; i++) {
4224 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4225 }
4226 xmlSchemaItemListFree(list);
4227 }
4228 if (schema->annot != NULL)
4229 xmlSchemaFreeAnnot(schema->annot);
4230 /* Never free the doc here, since this will be done by the buckets. */
4231
4232 xmlDictFree(schema->dict);
4233 xmlFree(schema);
4234 }
4235
4236 /************************************************************************
4237 * *
4238 * Debug functions *
4239 * *
4240 ************************************************************************/
4241
4242 #ifdef LIBXML_OUTPUT_ENABLED
4243
4244 static void
4245 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4246
4247 /**
4248 * xmlSchemaElementDump:
4249 * @elem: an element
4250 * @output: the file output
4251 *
4252 * Dump the element
4253 */
4254 static void
xmlSchemaElementDump(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED,const xmlChar * context ATTRIBUTE_UNUSED)4255 xmlSchemaElementDump(void *payload, void *data,
4256 const xmlChar * name ATTRIBUTE_UNUSED,
4257 const xmlChar * namespace ATTRIBUTE_UNUSED,
4258 const xmlChar * context ATTRIBUTE_UNUSED)
4259 {
4260 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4261 FILE *output = (FILE *) data;
4262 if (elem == NULL)
4263 return;
4264
4265
4266 fprintf(output, "Element");
4267 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4268 fprintf(output, " (global)");
4269 fprintf(output, ": '%s' ", elem->name);
4270 if (namespace != NULL)
4271 fprintf(output, "ns '%s'", namespace);
4272 fprintf(output, "\n");
4273 #if 0
4274 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4275 fprintf(output, " min %d ", elem->minOccurs);
4276 if (elem->maxOccurs >= UNBOUNDED)
4277 fprintf(output, "max: unbounded\n");
4278 else if (elem->maxOccurs != 1)
4279 fprintf(output, "max: %d\n", elem->maxOccurs);
4280 else
4281 fprintf(output, "\n");
4282 }
4283 #endif
4284 /*
4285 * Misc other properties.
4286 */
4287 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4288 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4289 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4290 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4291 fprintf(output, " props: ");
4292 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4293 fprintf(output, "[fixed] ");
4294 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4295 fprintf(output, "[default] ");
4296 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4297 fprintf(output, "[abstract] ");
4298 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4299 fprintf(output, "[nillable] ");
4300 fprintf(output, "\n");
4301 }
4302 /*
4303 * Default/fixed value.
4304 */
4305 if (elem->value != NULL)
4306 fprintf(output, " value: '%s'\n", elem->value);
4307 /*
4308 * Type.
4309 */
4310 if (elem->namedType != NULL) {
4311 fprintf(output, " type: '%s' ", elem->namedType);
4312 if (elem->namedTypeNs != NULL)
4313 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4314 else
4315 fprintf(output, "\n");
4316 } else if (elem->subtypes != NULL) {
4317 /*
4318 * Dump local types.
4319 */
4320 xmlSchemaTypeDump(elem->subtypes, output);
4321 }
4322 /*
4323 * Substitution group.
4324 */
4325 if (elem->substGroup != NULL) {
4326 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
4327 if (elem->substGroupNs != NULL)
4328 fprintf(output, "ns '%s'\n", elem->substGroupNs);
4329 else
4330 fprintf(output, "\n");
4331 }
4332 }
4333
4334 /**
4335 * xmlSchemaAnnotDump:
4336 * @output: the file output
4337 * @annot: a annotation
4338 *
4339 * Dump the annotation
4340 */
4341 static void
xmlSchemaAnnotDump(FILE * output,xmlSchemaAnnotPtr annot)4342 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4343 {
4344 xmlChar *content;
4345
4346 if (annot == NULL)
4347 return;
4348
4349 content = xmlNodeGetContent(annot->content);
4350 if (content != NULL) {
4351 fprintf(output, " Annot: %s\n", content);
4352 xmlFree(content);
4353 } else
4354 fprintf(output, " Annot: empty\n");
4355 }
4356
4357 /**
4358 * xmlSchemaContentModelDump:
4359 * @particle: the schema particle
4360 * @output: the file output
4361 * @depth: the depth used for indentation
4362 *
4363 * Dump a SchemaType structure
4364 */
4365 static void
xmlSchemaContentModelDump(xmlSchemaParticlePtr particle,FILE * output,int depth)4366 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4367 {
4368 xmlChar *str = NULL;
4369 xmlSchemaTreeItemPtr term;
4370 char shift[100];
4371 int i;
4372
4373 if (particle == NULL)
4374 return;
4375 for (i = 0;((i < depth) && (i < 25));i++)
4376 shift[2 * i] = shift[2 * i + 1] = ' ';
4377 shift[2 * i] = shift[2 * i + 1] = 0;
4378 fprintf(output, "%s", shift);
4379 if (particle->children == NULL) {
4380 fprintf(output, "MISSING particle term\n");
4381 return;
4382 }
4383 term = particle->children;
4384 if (term == NULL) {
4385 fprintf(output, "(NULL)");
4386 } else {
4387 switch (term->type) {
4388 case XML_SCHEMA_TYPE_ELEMENT:
4389 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4390 ((xmlSchemaElementPtr)term)->targetNamespace,
4391 ((xmlSchemaElementPtr)term)->name));
4392 FREE_AND_NULL(str);
4393 break;
4394 case XML_SCHEMA_TYPE_SEQUENCE:
4395 fprintf(output, "SEQUENCE");
4396 break;
4397 case XML_SCHEMA_TYPE_CHOICE:
4398 fprintf(output, "CHOICE");
4399 break;
4400 case XML_SCHEMA_TYPE_ALL:
4401 fprintf(output, "ALL");
4402 break;
4403 case XML_SCHEMA_TYPE_ANY:
4404 fprintf(output, "ANY");
4405 break;
4406 default:
4407 fprintf(output, "UNKNOWN\n");
4408 return;
4409 }
4410 }
4411 if (particle->minOccurs != 1)
4412 fprintf(output, " min: %d", particle->minOccurs);
4413 if (particle->maxOccurs >= UNBOUNDED)
4414 fprintf(output, " max: unbounded");
4415 else if (particle->maxOccurs != 1)
4416 fprintf(output, " max: %d", particle->maxOccurs);
4417 fprintf(output, "\n");
4418 if (term &&
4419 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4420 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4421 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4422 (term->children != NULL)) {
4423 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4424 output, depth +1);
4425 }
4426 if (particle->next != NULL)
4427 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4428 output, depth);
4429 }
4430
4431 /**
4432 * xmlSchemaAttrUsesDump:
4433 * @uses: attribute uses list
4434 * @output: the file output
4435 *
4436 * Dumps a list of attribute use components.
4437 */
4438 static void
xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses,FILE * output)4439 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4440 {
4441 xmlSchemaAttributeUsePtr use;
4442 xmlSchemaAttributeUseProhibPtr prohib;
4443 xmlSchemaQNameRefPtr ref;
4444 const xmlChar *name, *tns;
4445 xmlChar *str = NULL;
4446 int i;
4447
4448 if ((uses == NULL) || (uses->nbItems == 0))
4449 return;
4450
4451 fprintf(output, " attributes:\n");
4452 for (i = 0; i < uses->nbItems; i++) {
4453 use = uses->items[i];
4454 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4455 fprintf(output, " [prohibition] ");
4456 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4457 name = prohib->name;
4458 tns = prohib->targetNamespace;
4459 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4460 fprintf(output, " [reference] ");
4461 ref = (xmlSchemaQNameRefPtr) use;
4462 name = ref->name;
4463 tns = ref->targetNamespace;
4464 } else {
4465 fprintf(output, " [use] ");
4466 name = WXS_ATTRUSE_DECL_NAME(use);
4467 tns = WXS_ATTRUSE_DECL_TNS(use);
4468 }
4469 fprintf(output, "'%s'\n",
4470 (const char *) xmlSchemaFormatQName(&str, tns, name));
4471 FREE_AND_NULL(str);
4472 }
4473 }
4474
4475 /**
4476 * xmlSchemaTypeDump:
4477 * @output: the file output
4478 * @type: a type structure
4479 *
4480 * Dump a SchemaType structure
4481 */
4482 static void
xmlSchemaTypeDump(xmlSchemaTypePtr type,FILE * output)4483 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4484 {
4485 if (type == NULL) {
4486 fprintf(output, "Type: NULL\n");
4487 return;
4488 }
4489 fprintf(output, "Type: ");
4490 if (type->name != NULL)
4491 fprintf(output, "'%s' ", type->name);
4492 else
4493 fprintf(output, "(no name) ");
4494 if (type->targetNamespace != NULL)
4495 fprintf(output, "ns '%s' ", type->targetNamespace);
4496 switch (type->type) {
4497 case XML_SCHEMA_TYPE_BASIC:
4498 fprintf(output, "[basic] ");
4499 break;
4500 case XML_SCHEMA_TYPE_SIMPLE:
4501 fprintf(output, "[simple] ");
4502 break;
4503 case XML_SCHEMA_TYPE_COMPLEX:
4504 fprintf(output, "[complex] ");
4505 break;
4506 case XML_SCHEMA_TYPE_SEQUENCE:
4507 fprintf(output, "[sequence] ");
4508 break;
4509 case XML_SCHEMA_TYPE_CHOICE:
4510 fprintf(output, "[choice] ");
4511 break;
4512 case XML_SCHEMA_TYPE_ALL:
4513 fprintf(output, "[all] ");
4514 break;
4515 case XML_SCHEMA_TYPE_UR:
4516 fprintf(output, "[ur] ");
4517 break;
4518 case XML_SCHEMA_TYPE_RESTRICTION:
4519 fprintf(output, "[restriction] ");
4520 break;
4521 case XML_SCHEMA_TYPE_EXTENSION:
4522 fprintf(output, "[extension] ");
4523 break;
4524 default:
4525 fprintf(output, "[unknown type %d] ", type->type);
4526 break;
4527 }
4528 fprintf(output, "content: ");
4529 switch (type->contentType) {
4530 case XML_SCHEMA_CONTENT_UNKNOWN:
4531 fprintf(output, "[unknown] ");
4532 break;
4533 case XML_SCHEMA_CONTENT_EMPTY:
4534 fprintf(output, "[empty] ");
4535 break;
4536 case XML_SCHEMA_CONTENT_ELEMENTS:
4537 fprintf(output, "[element] ");
4538 break;
4539 case XML_SCHEMA_CONTENT_MIXED:
4540 fprintf(output, "[mixed] ");
4541 break;
4542 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4543 /* not used. */
4544 break;
4545 case XML_SCHEMA_CONTENT_BASIC:
4546 fprintf(output, "[basic] ");
4547 break;
4548 case XML_SCHEMA_CONTENT_SIMPLE:
4549 fprintf(output, "[simple] ");
4550 break;
4551 case XML_SCHEMA_CONTENT_ANY:
4552 fprintf(output, "[any] ");
4553 break;
4554 }
4555 fprintf(output, "\n");
4556 if (type->base != NULL) {
4557 fprintf(output, " base type: '%s'", type->base);
4558 if (type->baseNs != NULL)
4559 fprintf(output, " ns '%s'\n", type->baseNs);
4560 else
4561 fprintf(output, "\n");
4562 }
4563 if (type->attrUses != NULL)
4564 xmlSchemaAttrUsesDump(type->attrUses, output);
4565 if (type->annot != NULL)
4566 xmlSchemaAnnotDump(output, type->annot);
4567 #ifdef DUMP_CONTENT_MODEL
4568 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4569 (type->subtypes != NULL)) {
4570 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4571 output, 1);
4572 }
4573 #endif
4574 }
4575
4576 static void
xmlSchemaTypeDumpEntry(void * type,void * output,const xmlChar * name ATTRIBUTE_UNUSED)4577 xmlSchemaTypeDumpEntry(void *type, void *output,
4578 const xmlChar *name ATTRIBUTE_UNUSED)
4579 {
4580 xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4581 }
4582
4583 /**
4584 * xmlSchemaDump:
4585 * @output: the file output
4586 * @schema: a schema structure
4587 *
4588 * Dump a Schema structure.
4589 */
4590 void
xmlSchemaDump(FILE * output,xmlSchemaPtr schema)4591 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4592 {
4593 if (output == NULL)
4594 return;
4595 if (schema == NULL) {
4596 fprintf(output, "Schemas: NULL\n");
4597 return;
4598 }
4599 fprintf(output, "Schemas: ");
4600 if (schema->name != NULL)
4601 fprintf(output, "%s, ", schema->name);
4602 else
4603 fprintf(output, "no name, ");
4604 if (schema->targetNamespace != NULL)
4605 fprintf(output, "%s", (const char *) schema->targetNamespace);
4606 else
4607 fprintf(output, "no target namespace");
4608 fprintf(output, "\n");
4609 if (schema->annot != NULL)
4610 xmlSchemaAnnotDump(output, schema->annot);
4611 xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4612 xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4613 }
4614
4615 #endif /* LIBXML_OUTPUT_ENABLED */
4616
4617 /************************************************************************
4618 * *
4619 * Utilities *
4620 * *
4621 ************************************************************************/
4622
4623 /**
4624 * xmlSchemaGetPropNode:
4625 * @node: the element node
4626 * @name: the name of the attribute
4627 *
4628 * Seeks an attribute with a name of @name in
4629 * no namespace.
4630 *
4631 * Returns the attribute or NULL if not present.
4632 */
4633 static xmlAttrPtr
xmlSchemaGetPropNode(xmlNodePtr node,const char * name)4634 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4635 {
4636 xmlAttrPtr prop;
4637
4638 if ((node == NULL) || (name == NULL))
4639 return(NULL);
4640 prop = node->properties;
4641 while (prop != NULL) {
4642 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4643 return(prop);
4644 prop = prop->next;
4645 }
4646 return (NULL);
4647 }
4648
4649 /**
4650 * xmlSchemaGetPropNodeNs:
4651 * @node: the element node
4652 * @uri: the uri
4653 * @name: the name of the attribute
4654 *
4655 * Seeks an attribute with a local name of @name and
4656 * a namespace URI of @uri.
4657 *
4658 * Returns the attribute or NULL if not present.
4659 */
4660 static xmlAttrPtr
xmlSchemaGetPropNodeNs(xmlNodePtr node,const char * uri,const char * name)4661 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4662 {
4663 xmlAttrPtr prop;
4664
4665 if ((node == NULL) || (name == NULL))
4666 return(NULL);
4667 prop = node->properties;
4668 while (prop != NULL) {
4669 if ((prop->ns != NULL) &&
4670 xmlStrEqual(prop->name, BAD_CAST name) &&
4671 xmlStrEqual(prop->ns->href, BAD_CAST uri))
4672 return(prop);
4673 prop = prop->next;
4674 }
4675 return (NULL);
4676 }
4677
4678 static const xmlChar *
xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)4679 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4680 {
4681 xmlChar *val;
4682 const xmlChar *ret;
4683
4684 val = xmlNodeGetContent(node);
4685 if (val == NULL)
4686 val = xmlStrdup((xmlChar *)"");
4687 ret = xmlDictLookup(ctxt->dict, val, -1);
4688 xmlFree(val);
4689 if (ret == NULL)
4690 xmlSchemaPErrMemory(ctxt);
4691 return(ret);
4692 }
4693
4694 static const xmlChar *
xmlSchemaGetNodeContentNoDict(xmlNodePtr node)4695 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4696 {
4697 return((const xmlChar*) xmlNodeGetContent(node));
4698 }
4699
4700 /**
4701 * xmlSchemaGetProp:
4702 * @ctxt: the parser context
4703 * @node: the node
4704 * @name: the property name
4705 *
4706 * Read a attribute value and internalize the string
4707 *
4708 * Returns the string or NULL if not present.
4709 */
4710 static const xmlChar *
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name)4711 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4712 const char *name)
4713 {
4714 xmlChar *val;
4715 const xmlChar *ret;
4716
4717 val = xmlGetNoNsProp(node, BAD_CAST name);
4718 if (val == NULL)
4719 return(NULL);
4720 ret = xmlDictLookup(ctxt->dict, val, -1);
4721 xmlFree(val);
4722 return(ret);
4723 }
4724
4725 /************************************************************************
4726 * *
4727 * Parsing functions *
4728 * *
4729 ************************************************************************/
4730
4731 #define WXS_FIND_GLOBAL_ITEM(slot) \
4732 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4733 ret = xmlHashLookup(schema->slot, name); \
4734 if (ret != NULL) goto exit; \
4735 } \
4736 if (xmlHashSize(schema->schemasImports) > 1) { \
4737 xmlSchemaImportPtr import; \
4738 if (nsName == NULL) \
4739 import = xmlHashLookup(schema->schemasImports, \
4740 XML_SCHEMAS_NO_NAMESPACE); \
4741 else \
4742 import = xmlHashLookup(schema->schemasImports, nsName); \
4743 if (import == NULL) \
4744 goto exit; \
4745 ret = xmlHashLookup(import->schema->slot, name); \
4746 }
4747
4748 /**
4749 * xmlSchemaGetElem:
4750 * @schema: the schema context
4751 * @name: the element name
4752 * @ns: the element namespace
4753 *
4754 * Lookup a global element declaration in the schema.
4755 *
4756 * Returns the element declaration or NULL if not found.
4757 */
4758 static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4759 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4760 const xmlChar * nsName)
4761 {
4762 xmlSchemaElementPtr ret = NULL;
4763
4764 if ((name == NULL) || (schema == NULL))
4765 return(NULL);
4766 if (schema != NULL) {
4767 WXS_FIND_GLOBAL_ITEM(elemDecl)
4768 }
4769 exit:
4770 return (ret);
4771 }
4772
4773 /**
4774 * xmlSchemaGetType:
4775 * @schema: the main schema
4776 * @name: the type's name
4777 * nsName: the type's namespace
4778 *
4779 * Lookup a type in the schemas or the predefined types
4780 *
4781 * Returns the group definition or NULL if not found.
4782 */
4783 static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4784 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4785 const xmlChar * nsName)
4786 {
4787 xmlSchemaTypePtr ret = NULL;
4788
4789 if (name == NULL)
4790 return (NULL);
4791 /* First try the built-in types. */
4792 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4793 ret = xmlSchemaGetPredefinedType(name, nsName);
4794 if (ret != NULL)
4795 goto exit;
4796 /*
4797 * Note that we try the parsed schemas as well here
4798 * since one might have parsed the S4S, which contain more
4799 * than the built-in types.
4800 * TODO: Can we optimize this?
4801 */
4802 }
4803 if (schema != NULL) {
4804 WXS_FIND_GLOBAL_ITEM(typeDecl)
4805 }
4806 exit:
4807
4808 return (ret);
4809 }
4810
4811 /**
4812 * xmlSchemaGetAttributeDecl:
4813 * @schema: the context of the schema
4814 * @name: the name of the attribute
4815 * @ns: the target namespace of the attribute
4816 *
4817 * Lookup a an attribute in the schema or imported schemas
4818 *
4819 * Returns the attribute declaration or NULL if not found.
4820 */
4821 static xmlSchemaAttributePtr
xmlSchemaGetAttributeDecl(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4822 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4823 const xmlChar * nsName)
4824 {
4825 xmlSchemaAttributePtr ret = NULL;
4826
4827 if ((name == NULL) || (schema == NULL))
4828 return (NULL);
4829 if (schema != NULL) {
4830 WXS_FIND_GLOBAL_ITEM(attrDecl)
4831 }
4832 exit:
4833 return (ret);
4834 }
4835
4836 /**
4837 * xmlSchemaGetAttributeGroup:
4838 * @schema: the context of the schema
4839 * @name: the name of the attribute group
4840 * @ns: the target namespace of the attribute group
4841 *
4842 * Lookup a an attribute group in the schema or imported schemas
4843 *
4844 * Returns the attribute group definition or NULL if not found.
4845 */
4846 static xmlSchemaAttributeGroupPtr
xmlSchemaGetAttributeGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4847 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4848 const xmlChar * nsName)
4849 {
4850 xmlSchemaAttributeGroupPtr ret = NULL;
4851
4852 if ((name == NULL) || (schema == NULL))
4853 return (NULL);
4854 if (schema != NULL) {
4855 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4856 }
4857 exit:
4858 /* TODO:
4859 if ((ret != NULL) && (ret->redef != NULL)) {
4860 * Return the last redefinition. *
4861 ret = ret->redef;
4862 }
4863 */
4864 return (ret);
4865 }
4866
4867 /**
4868 * xmlSchemaGetGroup:
4869 * @schema: the context of the schema
4870 * @name: the name of the group
4871 * @ns: the target namespace of the group
4872 *
4873 * Lookup a group in the schema or imported schemas
4874 *
4875 * Returns the group definition or NULL if not found.
4876 */
4877 static xmlSchemaModelGroupDefPtr
xmlSchemaGetGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4878 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4879 const xmlChar * nsName)
4880 {
4881 xmlSchemaModelGroupDefPtr ret = NULL;
4882
4883 if ((name == NULL) || (schema == NULL))
4884 return (NULL);
4885 if (schema != NULL) {
4886 WXS_FIND_GLOBAL_ITEM(groupDecl)
4887 }
4888 exit:
4889
4890 return (ret);
4891 }
4892
4893 static xmlSchemaNotationPtr
xmlSchemaGetNotation(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4894 xmlSchemaGetNotation(xmlSchemaPtr schema,
4895 const xmlChar *name,
4896 const xmlChar *nsName)
4897 {
4898 xmlSchemaNotationPtr ret = NULL;
4899
4900 if ((name == NULL) || (schema == NULL))
4901 return (NULL);
4902 if (schema != NULL) {
4903 WXS_FIND_GLOBAL_ITEM(notaDecl)
4904 }
4905 exit:
4906 return (ret);
4907 }
4908
4909 static xmlSchemaIDCPtr
xmlSchemaGetIDC(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4910 xmlSchemaGetIDC(xmlSchemaPtr schema,
4911 const xmlChar *name,
4912 const xmlChar *nsName)
4913 {
4914 xmlSchemaIDCPtr ret = NULL;
4915
4916 if ((name == NULL) || (schema == NULL))
4917 return (NULL);
4918 if (schema != NULL) {
4919 WXS_FIND_GLOBAL_ITEM(idcDef)
4920 }
4921 exit:
4922 return (ret);
4923 }
4924
4925 /**
4926 * xmlSchemaGetNamedComponent:
4927 * @schema: the schema
4928 * @name: the name of the group
4929 * @ns: the target namespace of the group
4930 *
4931 * Lookup a group in the schema or imported schemas
4932 *
4933 * Returns the group definition or NULL if not found.
4934 */
4935 static xmlSchemaBasicItemPtr
xmlSchemaGetNamedComponent(xmlSchemaPtr schema,xmlSchemaTypeType itemType,const xmlChar * name,const xmlChar * targetNs)4936 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4937 xmlSchemaTypeType itemType,
4938 const xmlChar *name,
4939 const xmlChar *targetNs)
4940 {
4941 switch (itemType) {
4942 case XML_SCHEMA_TYPE_GROUP:
4943 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4944 name, targetNs));
4945 case XML_SCHEMA_TYPE_ELEMENT:
4946 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4947 name, targetNs));
4948 default:
4949 /* TODO */
4950 return (NULL);
4951 }
4952 }
4953
4954 /************************************************************************
4955 * *
4956 * Parsing functions *
4957 * *
4958 ************************************************************************/
4959
4960 #define IS_BLANK_NODE(n) \
4961 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4962
4963 /**
4964 * xmlSchemaIsBlank:
4965 * @str: a string
4966 * @len: the length of the string or -1
4967 *
4968 * Check if a string is ignorable
4969 *
4970 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4971 */
4972 static int
xmlSchemaIsBlank(xmlChar * str,int len)4973 xmlSchemaIsBlank(xmlChar * str, int len)
4974 {
4975 if (str == NULL)
4976 return (1);
4977 if (len < 0) {
4978 while (*str != 0) {
4979 if (!(IS_BLANK_CH(*str)))
4980 return (0);
4981 str++;
4982 }
4983 } else while ((*str != 0) && (len != 0)) {
4984 if (!(IS_BLANK_CH(*str)))
4985 return (0);
4986 str++;
4987 len--;
4988 }
4989
4990 return (1);
4991 }
4992
4993 #define WXS_COMP_NAME(c, t) ((t) (c))->name
4994 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4995 /*
4996 * xmlSchemaFindRedefCompInGraph:
4997 * ATTENTION TODO: This uses pointer comp. for strings.
4998 */
4999 static xmlSchemaBasicItemPtr
xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName)5000 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5001 xmlSchemaTypeType type,
5002 const xmlChar *name,
5003 const xmlChar *nsName)
5004 {
5005 xmlSchemaBasicItemPtr ret;
5006 int i;
5007
5008 if ((bucket == NULL) || (name == NULL))
5009 return(NULL);
5010 if ((bucket->globals == NULL) ||
5011 (bucket->globals->nbItems == 0))
5012 goto subschemas;
5013 /*
5014 * Search in global components.
5015 */
5016 for (i = 0; i < bucket->globals->nbItems; i++) {
5017 ret = bucket->globals->items[i];
5018 if (ret->type == type) {
5019 switch (type) {
5020 case XML_SCHEMA_TYPE_COMPLEX:
5021 case XML_SCHEMA_TYPE_SIMPLE:
5022 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5023 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5024 nsName))
5025 {
5026 return(ret);
5027 }
5028 break;
5029 case XML_SCHEMA_TYPE_GROUP:
5030 if ((WXS_COMP_NAME(ret,
5031 xmlSchemaModelGroupDefPtr) == name) &&
5032 (WXS_COMP_TNS(ret,
5033 xmlSchemaModelGroupDefPtr) == nsName))
5034 {
5035 return(ret);
5036 }
5037 break;
5038 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5039 if ((WXS_COMP_NAME(ret,
5040 xmlSchemaAttributeGroupPtr) == name) &&
5041 (WXS_COMP_TNS(ret,
5042 xmlSchemaAttributeGroupPtr) == nsName))
5043 {
5044 return(ret);
5045 }
5046 break;
5047 default:
5048 /* Should not be hit. */
5049 return(NULL);
5050 }
5051 }
5052 }
5053 subschemas:
5054 /*
5055 * Process imported/included schemas.
5056 */
5057 if (bucket->relations != NULL) {
5058 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5059
5060 /*
5061 * TODO: Marking the bucket will not avoid multiple searches
5062 * in the same schema, but avoids at least circularity.
5063 */
5064 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5065 do {
5066 if ((rel->bucket != NULL) &&
5067 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5068 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5069 type, name, nsName);
5070 if (ret != NULL)
5071 return(ret);
5072 }
5073 rel = rel->next;
5074 } while (rel != NULL);
5075 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5076 }
5077 return(NULL);
5078 }
5079
5080 /**
5081 * xmlSchemaAddNotation:
5082 * @ctxt: a schema parser context
5083 * @schema: the schema being built
5084 * @name: the item name
5085 *
5086 * Add an XML schema annotation declaration
5087 * *WARNING* this interface is highly subject to change
5088 *
5089 * Returns the new structure or NULL in case of error
5090 */
5091 static xmlSchemaNotationPtr
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node ATTRIBUTE_UNUSED)5092 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5093 const xmlChar *name, const xmlChar *nsName,
5094 xmlNodePtr node ATTRIBUTE_UNUSED)
5095 {
5096 xmlSchemaNotationPtr ret = NULL;
5097
5098 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5099 return (NULL);
5100
5101 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5102 if (ret == NULL) {
5103 xmlSchemaPErrMemory(ctxt);
5104 return (NULL);
5105 }
5106 memset(ret, 0, sizeof(xmlSchemaNotation));
5107 ret->type = XML_SCHEMA_TYPE_NOTATION;
5108 ret->name = name;
5109 ret->targetNamespace = nsName;
5110 /* TODO: do we need the node to be set?
5111 * ret->node = node;*/
5112 WXS_ADD_GLOBAL(ctxt, ret);
5113 return (ret);
5114 }
5115
5116 /**
5117 * xmlSchemaAddAttribute:
5118 * @ctxt: a schema parser context
5119 * @schema: the schema being built
5120 * @name: the item name
5121 * @namespace: the namespace
5122 *
5123 * Add an XML schema Attribute declaration
5124 * *WARNING* this interface is highly subject to change
5125 *
5126 * Returns the new structure or NULL in case of error
5127 */
5128 static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5129 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5130 const xmlChar * name, const xmlChar * nsName,
5131 xmlNodePtr node, int topLevel)
5132 {
5133 xmlSchemaAttributePtr ret = NULL;
5134
5135 if ((ctxt == NULL) || (schema == NULL))
5136 return (NULL);
5137
5138 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5139 if (ret == NULL) {
5140 xmlSchemaPErrMemory(ctxt);
5141 return (NULL);
5142 }
5143 memset(ret, 0, sizeof(xmlSchemaAttribute));
5144 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5145 ret->node = node;
5146 ret->name = name;
5147 ret->targetNamespace = nsName;
5148
5149 if (topLevel)
5150 WXS_ADD_GLOBAL(ctxt, ret);
5151 else
5152 WXS_ADD_LOCAL(ctxt, ret);
5153 WXS_ADD_PENDING(ctxt, ret);
5154 return (ret);
5155 }
5156
5157 /**
5158 * xmlSchemaAddAttributeUse:
5159 * @ctxt: a schema parser context
5160 * @schema: the schema being built
5161 * @name: the item name
5162 * @namespace: the namespace
5163 *
5164 * Add an XML schema Attribute declaration
5165 * *WARNING* this interface is highly subject to change
5166 *
5167 * Returns the new structure or NULL in case of error
5168 */
5169 static xmlSchemaAttributeUsePtr
xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node)5170 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5171 xmlNodePtr node)
5172 {
5173 xmlSchemaAttributeUsePtr ret = NULL;
5174
5175 if (pctxt == NULL)
5176 return (NULL);
5177
5178 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5179 if (ret == NULL) {
5180 xmlSchemaPErrMemory(pctxt);
5181 return (NULL);
5182 }
5183 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5184 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5185 ret->node = node;
5186
5187 WXS_ADD_LOCAL(pctxt, ret);
5188 return (ret);
5189 }
5190
5191 /*
5192 * xmlSchemaAddRedef:
5193 *
5194 * Adds a redefinition information. This is used at a later stage to:
5195 * resolve references to the redefined components and to check constraints.
5196 */
5197 static xmlSchemaRedefPtr
xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr targetBucket,void * item,const xmlChar * refName,const xmlChar * refTargetNs)5198 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5199 xmlSchemaBucketPtr targetBucket,
5200 void *item,
5201 const xmlChar *refName,
5202 const xmlChar *refTargetNs)
5203 {
5204 xmlSchemaRedefPtr ret;
5205
5206 ret = (xmlSchemaRedefPtr)
5207 xmlMalloc(sizeof(xmlSchemaRedef));
5208 if (ret == NULL) {
5209 xmlSchemaPErrMemory(pctxt);
5210 return (NULL);
5211 }
5212 memset(ret, 0, sizeof(xmlSchemaRedef));
5213 ret->item = item;
5214 ret->targetBucket = targetBucket;
5215 ret->refName = refName;
5216 ret->refTargetNs = refTargetNs;
5217 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5218 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5219 else
5220 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5221 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5222
5223 return (ret);
5224 }
5225
5226 /**
5227 * xmlSchemaAddAttributeGroupDefinition:
5228 * @ctxt: a schema parser context
5229 * @schema: the schema being built
5230 * @name: the item name
5231 * @nsName: the target namespace
5232 * @node: the corresponding node
5233 *
5234 * Add an XML schema Attribute Group definition.
5235 *
5236 * Returns the new structure or NULL in case of error
5237 */
5238 static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5239 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5240 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5241 const xmlChar *name,
5242 const xmlChar *nsName,
5243 xmlNodePtr node)
5244 {
5245 xmlSchemaAttributeGroupPtr ret = NULL;
5246
5247 if ((pctxt == NULL) || (name == NULL))
5248 return (NULL);
5249
5250 ret = (xmlSchemaAttributeGroupPtr)
5251 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5252 if (ret == NULL) {
5253 xmlSchemaPErrMemory(pctxt);
5254 return (NULL);
5255 }
5256 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5257 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5258 ret->name = name;
5259 ret->targetNamespace = nsName;
5260 ret->node = node;
5261
5262 /* TODO: Remove the flag. */
5263 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5264 if (pctxt->isRedefine) {
5265 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5266 ret, name, nsName);
5267 if (pctxt->redef == NULL) {
5268 xmlFree(ret);
5269 return(NULL);
5270 }
5271 pctxt->redefCounter = 0;
5272 }
5273 WXS_ADD_GLOBAL(pctxt, ret);
5274 WXS_ADD_PENDING(pctxt, ret);
5275 return (ret);
5276 }
5277
5278 /**
5279 * xmlSchemaAddElement:
5280 * @ctxt: a schema parser context
5281 * @schema: the schema being built
5282 * @name: the type name
5283 * @namespace: the type namespace
5284 *
5285 * Add an XML schema Element declaration
5286 * *WARNING* this interface is highly subject to change
5287 *
5288 * Returns the new structure or NULL in case of error
5289 */
5290 static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5291 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5292 const xmlChar * name, const xmlChar * nsName,
5293 xmlNodePtr node, int topLevel)
5294 {
5295 xmlSchemaElementPtr ret = NULL;
5296
5297 if ((ctxt == NULL) || (name == NULL))
5298 return (NULL);
5299
5300 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5301 if (ret == NULL) {
5302 xmlSchemaPErrMemory(ctxt);
5303 return (NULL);
5304 }
5305 memset(ret, 0, sizeof(xmlSchemaElement));
5306 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5307 ret->name = name;
5308 ret->targetNamespace = nsName;
5309 ret->node = node;
5310
5311 if (topLevel)
5312 WXS_ADD_GLOBAL(ctxt, ret);
5313 else
5314 WXS_ADD_LOCAL(ctxt, ret);
5315 WXS_ADD_PENDING(ctxt, ret);
5316 return (ret);
5317 }
5318
5319 /**
5320 * xmlSchemaAddType:
5321 * @ctxt: a schema parser context
5322 * @schema: the schema being built
5323 * @name: the item name
5324 * @namespace: the namespace
5325 *
5326 * Add an XML schema item
5327 * *WARNING* this interface is highly subject to change
5328 *
5329 * Returns the new structure or NULL in case of error
5330 */
5331 static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5332 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5333 xmlSchemaTypeType type,
5334 const xmlChar * name, const xmlChar * nsName,
5335 xmlNodePtr node, int topLevel)
5336 {
5337 xmlSchemaTypePtr ret = NULL;
5338
5339 if ((ctxt == NULL) || (schema == NULL))
5340 return (NULL);
5341
5342 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5343 if (ret == NULL) {
5344 xmlSchemaPErrMemory(ctxt);
5345 return (NULL);
5346 }
5347 memset(ret, 0, sizeof(xmlSchemaType));
5348 ret->type = type;
5349 ret->name = name;
5350 ret->targetNamespace = nsName;
5351 ret->node = node;
5352 if (topLevel) {
5353 if (ctxt->isRedefine) {
5354 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5355 ret, name, nsName);
5356 if (ctxt->redef == NULL) {
5357 xmlFree(ret);
5358 return(NULL);
5359 }
5360 ctxt->redefCounter = 0;
5361 }
5362 WXS_ADD_GLOBAL(ctxt, ret);
5363 } else
5364 WXS_ADD_LOCAL(ctxt, ret);
5365 WXS_ADD_PENDING(ctxt, ret);
5366 return (ret);
5367 }
5368
5369 static xmlSchemaQNameRefPtr
xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypeType refType,const xmlChar * refName,const xmlChar * refNs)5370 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5371 xmlSchemaTypeType refType,
5372 const xmlChar *refName,
5373 const xmlChar *refNs)
5374 {
5375 xmlSchemaQNameRefPtr ret;
5376
5377 ret = (xmlSchemaQNameRefPtr)
5378 xmlMalloc(sizeof(xmlSchemaQNameRef));
5379 if (ret == NULL) {
5380 xmlSchemaPErrMemory(pctxt);
5381 return (NULL);
5382 }
5383 ret->node = NULL;
5384 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5385 ret->name = refName;
5386 ret->targetNamespace = refNs;
5387 ret->item = NULL;
5388 ret->itemType = refType;
5389 /*
5390 * Store the reference item in the schema.
5391 */
5392 WXS_ADD_LOCAL(pctxt, ret);
5393 return (ret);
5394 }
5395
5396 static xmlSchemaAttributeUseProhibPtr
xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)5397 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5398 {
5399 xmlSchemaAttributeUseProhibPtr ret;
5400
5401 ret = (xmlSchemaAttributeUseProhibPtr)
5402 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5403 if (ret == NULL) {
5404 xmlSchemaPErrMemory(pctxt);
5405 return (NULL);
5406 }
5407 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5408 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5409 WXS_ADD_LOCAL(pctxt, ret);
5410 return (ret);
5411 }
5412
5413
5414 /**
5415 * xmlSchemaAddModelGroup:
5416 * @ctxt: a schema parser context
5417 * @schema: the schema being built
5418 * @type: the "compositor" type of the model group
5419 * @node: the node in the schema doc
5420 *
5421 * Adds a schema model group
5422 * *WARNING* this interface is highly subject to change
5423 *
5424 * Returns the new structure or NULL in case of error
5425 */
5426 static xmlSchemaModelGroupPtr
xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5427 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5428 xmlSchemaPtr schema,
5429 xmlSchemaTypeType type,
5430 xmlNodePtr node)
5431 {
5432 xmlSchemaModelGroupPtr ret = NULL;
5433
5434 if ((ctxt == NULL) || (schema == NULL))
5435 return (NULL);
5436
5437 ret = (xmlSchemaModelGroupPtr)
5438 xmlMalloc(sizeof(xmlSchemaModelGroup));
5439 if (ret == NULL) {
5440 xmlSchemaPErrMemory(ctxt);
5441 return (NULL);
5442 }
5443 memset(ret, 0, sizeof(xmlSchemaModelGroup));
5444 ret->type = type;
5445 ret->node = node;
5446 WXS_ADD_LOCAL(ctxt, ret);
5447 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5448 (type == XML_SCHEMA_TYPE_CHOICE))
5449 WXS_ADD_PENDING(ctxt, ret);
5450 return (ret);
5451 }
5452
5453
5454 /**
5455 * xmlSchemaAddParticle:
5456 * @ctxt: a schema parser context
5457 * @schema: the schema being built
5458 * @node: the corresponding node in the schema doc
5459 * @min: the minOccurs
5460 * @max: the maxOccurs
5461 *
5462 * Adds an XML schema particle component.
5463 * *WARNING* this interface is highly subject to change
5464 *
5465 * Returns the new structure or NULL in case of error
5466 */
5467 static xmlSchemaParticlePtr
xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max)5468 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5469 xmlNodePtr node, int min, int max)
5470 {
5471 xmlSchemaParticlePtr ret = NULL;
5472 if (ctxt == NULL)
5473 return (NULL);
5474
5475 ret = (xmlSchemaParticlePtr)
5476 xmlMalloc(sizeof(xmlSchemaParticle));
5477 if (ret == NULL) {
5478 xmlSchemaPErrMemory(ctxt);
5479 return (NULL);
5480 }
5481 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5482 ret->annot = NULL;
5483 ret->node = node;
5484 ret->minOccurs = min;
5485 ret->maxOccurs = max;
5486 ret->next = NULL;
5487 ret->children = NULL;
5488
5489 WXS_ADD_LOCAL(ctxt, ret);
5490 /*
5491 * Note that addition to pending components will be done locally
5492 * to the specific parsing function, since the most particles
5493 * need not to be fixed up (i.e. the reference to be resolved).
5494 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5495 */
5496 return (ret);
5497 }
5498
5499 /**
5500 * xmlSchemaAddModelGroupDefinition:
5501 * @ctxt: a schema validation context
5502 * @schema: the schema being built
5503 * @name: the group name
5504 *
5505 * Add an XML schema Group definition
5506 *
5507 * Returns the new structure or NULL in case of error
5508 */
5509 static xmlSchemaModelGroupDefPtr
xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5510 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5511 xmlSchemaPtr schema,
5512 const xmlChar *name,
5513 const xmlChar *nsName,
5514 xmlNodePtr node)
5515 {
5516 xmlSchemaModelGroupDefPtr ret = NULL;
5517
5518 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5519 return (NULL);
5520
5521 ret = (xmlSchemaModelGroupDefPtr)
5522 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5523 if (ret == NULL) {
5524 xmlSchemaPErrMemory(ctxt);
5525 return (NULL);
5526 }
5527 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5528 ret->name = name;
5529 ret->type = XML_SCHEMA_TYPE_GROUP;
5530 ret->node = node;
5531 ret->targetNamespace = nsName;
5532
5533 if (ctxt->isRedefine) {
5534 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5535 ret, name, nsName);
5536 if (ctxt->redef == NULL) {
5537 xmlFree(ret);
5538 return(NULL);
5539 }
5540 ctxt->redefCounter = 0;
5541 }
5542 WXS_ADD_GLOBAL(ctxt, ret);
5543 WXS_ADD_PENDING(ctxt, ret);
5544 return (ret);
5545 }
5546
5547 /**
5548 * xmlSchemaNewWildcardNs:
5549 * @ctxt: a schema validation context
5550 *
5551 * Creates a new wildcard namespace constraint.
5552 *
5553 * Returns the new structure or NULL in case of error
5554 */
5555 static xmlSchemaWildcardNsPtr
xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)5556 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5557 {
5558 xmlSchemaWildcardNsPtr ret;
5559
5560 ret = (xmlSchemaWildcardNsPtr)
5561 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5562 if (ret == NULL) {
5563 xmlSchemaPErrMemory(ctxt);
5564 return (NULL);
5565 }
5566 ret->value = NULL;
5567 ret->next = NULL;
5568 return (ret);
5569 }
5570
5571 static xmlSchemaIDCPtr
xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,int category,xmlNodePtr node)5572 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5573 const xmlChar *name, const xmlChar *nsName,
5574 int category, xmlNodePtr node)
5575 {
5576 xmlSchemaIDCPtr ret = NULL;
5577
5578 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5579 return (NULL);
5580
5581 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5582 if (ret == NULL) {
5583 xmlSchemaPErrMemory(ctxt);
5584 return (NULL);
5585 }
5586 memset(ret, 0, sizeof(xmlSchemaIDC));
5587 /* The target namespace of the parent element declaration. */
5588 ret->targetNamespace = nsName;
5589 ret->name = name;
5590 ret->type = category;
5591 ret->node = node;
5592
5593 WXS_ADD_GLOBAL(ctxt, ret);
5594 /*
5595 * Only keyrefs need to be fixup up.
5596 */
5597 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5598 WXS_ADD_PENDING(ctxt, ret);
5599 return (ret);
5600 }
5601
5602 /**
5603 * xmlSchemaAddWildcard:
5604 * @ctxt: a schema validation context
5605 * @schema: a schema
5606 *
5607 * Adds a wildcard.
5608 * It corresponds to a xsd:anyAttribute and xsd:any.
5609 *
5610 * Returns the new structure or NULL in case of error
5611 */
5612 static xmlSchemaWildcardPtr
xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5613 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5614 xmlSchemaTypeType type, xmlNodePtr node)
5615 {
5616 xmlSchemaWildcardPtr ret = NULL;
5617
5618 if ((ctxt == NULL) || (schema == NULL))
5619 return (NULL);
5620
5621 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5622 if (ret == NULL) {
5623 xmlSchemaPErrMemory(ctxt);
5624 return (NULL);
5625 }
5626 memset(ret, 0, sizeof(xmlSchemaWildcard));
5627 ret->type = type;
5628 ret->node = node;
5629 WXS_ADD_LOCAL(ctxt, ret);
5630 return (ret);
5631 }
5632
5633 static void
xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)5634 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5635 {
5636 if (group == NULL)
5637 return;
5638 if (group->members != NULL)
5639 xmlSchemaItemListFree(group->members);
5640 xmlFree(group);
5641 }
5642
5643 static void
xmlSchemaSubstGroupFreeEntry(void * group,const xmlChar * name ATTRIBUTE_UNUSED)5644 xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5645 {
5646 xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5647 }
5648
5649 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5650 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5651 xmlSchemaElementPtr head)
5652 {
5653 xmlSchemaSubstGroupPtr ret;
5654
5655 /* Init subst group hash. */
5656 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5657 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5658 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5659 return(NULL);
5660 }
5661 /* Create a new substitution group. */
5662 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5663 if (ret == NULL) {
5664 xmlSchemaPErrMemory(NULL);
5665 return(NULL);
5666 }
5667 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5668 ret->head = head;
5669 /* Create list of members. */
5670 ret->members = xmlSchemaItemListCreate();
5671 if (ret->members == NULL) {
5672 xmlSchemaSubstGroupFree(ret);
5673 return(NULL);
5674 }
5675 /* Add subst group to hash. */
5676 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5677 head->name, head->targetNamespace, ret) != 0) {
5678 PERROR_INT("xmlSchemaSubstGroupAdd",
5679 "failed to add a new substitution container");
5680 xmlSchemaSubstGroupFree(ret);
5681 return(NULL);
5682 }
5683 return(ret);
5684 }
5685
5686 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5687 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5688 xmlSchemaElementPtr head)
5689 {
5690 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5691 return(NULL);
5692 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5693 head->name, head->targetNamespace));
5694
5695 }
5696
5697 /**
5698 * xmlSchemaAddElementSubstitutionMember:
5699 * @pctxt: a schema parser context
5700 * @head: the head of the substitution group
5701 * @member: the new member of the substitution group
5702 *
5703 * Allocate a new annotation structure.
5704 *
5705 * Returns the newly allocated structure or NULL in case or error
5706 */
5707 static int
xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head,xmlSchemaElementPtr member)5708 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5709 xmlSchemaElementPtr head,
5710 xmlSchemaElementPtr member)
5711 {
5712 xmlSchemaSubstGroupPtr substGroup = NULL;
5713
5714 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5715 return (-1);
5716
5717 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5718 if (substGroup == NULL)
5719 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5720 if (substGroup == NULL)
5721 return(-1);
5722 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5723 return(-1);
5724 return(0);
5725 }
5726
5727 /************************************************************************
5728 * *
5729 * Utilities for parsing *
5730 * *
5731 ************************************************************************/
5732
5733 /**
5734 * xmlSchemaPValAttrNodeQNameValue:
5735 * @ctxt: a schema parser context
5736 * @schema: the schema context
5737 * @ownerItem: the parent as a schema object
5738 * @value: the QName value
5739 * @uri: the resulting namespace URI if found
5740 * @local: the resulting local part if found, the attribute value otherwise
5741 *
5742 * Extracts the local name and the URI of a QName value and validates it.
5743 * This one is intended to be used on attribute values that
5744 * should resolve to schema components.
5745 *
5746 * Returns 0, in case the QName is valid, a positive error code
5747 * if not valid and -1 if an internal error occurs.
5748 */
5749 static int
xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,const xmlChar ** uri,const xmlChar ** local)5750 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5751 xmlSchemaPtr schema,
5752 xmlSchemaBasicItemPtr ownerItem,
5753 xmlAttrPtr attr,
5754 const xmlChar *value,
5755 const xmlChar **uri,
5756 const xmlChar **local)
5757 {
5758 const xmlChar *pref;
5759 xmlNsPtr ns;
5760 int len, ret;
5761
5762 *uri = NULL;
5763 *local = NULL;
5764 ret = xmlValidateQName(value, 1);
5765 if (ret > 0) {
5766 xmlSchemaPSimpleTypeErr(ctxt,
5767 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5768 ownerItem, (xmlNodePtr) attr,
5769 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5770 NULL, value, NULL, NULL, NULL);
5771 *local = value;
5772 return (ctxt->err);
5773 } else if (ret < 0)
5774 return (-1);
5775
5776 if (!strchr((char *) value, ':')) {
5777 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5778 if (ns && ns->href && ns->href[0])
5779 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5780 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5781 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5782 * parser context. */
5783 /*
5784 * This one takes care of included schemas with no
5785 * target namespace.
5786 */
5787 *uri = ctxt->targetNamespace;
5788 }
5789 *local = xmlDictLookup(ctxt->dict, value, -1);
5790 return (0);
5791 }
5792 /*
5793 * At this point xmlSplitQName3 has to return a local name.
5794 */
5795 *local = xmlSplitQName3(value, &len);
5796 *local = xmlDictLookup(ctxt->dict, *local, -1);
5797 pref = xmlDictLookup(ctxt->dict, value, len);
5798 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5799 if (ns == NULL) {
5800 xmlSchemaPSimpleTypeErr(ctxt,
5801 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5802 ownerItem, (xmlNodePtr) attr,
5803 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5804 "The value '%s' of simple type 'xs:QName' has no "
5805 "corresponding namespace declaration in scope", value, NULL);
5806 return (ctxt->err);
5807 } else {
5808 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5809 }
5810 return (0);
5811 }
5812
5813 /**
5814 * xmlSchemaPValAttrNodeQName:
5815 * @ctxt: a schema parser context
5816 * @schema: the schema context
5817 * @ownerItem: the owner as a schema object
5818 * @attr: the attribute node
5819 * @uri: the resulting namespace URI if found
5820 * @local: the resulting local part if found, the attribute value otherwise
5821 *
5822 * Extracts and validates the QName of an attribute value.
5823 * This one is intended to be used on attribute values that
5824 * should resolve to schema components.
5825 *
5826 * Returns 0, in case the QName is valid, a positive error code
5827 * if not valid and -1 if an internal error occurs.
5828 */
5829 static int
xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar ** uri,const xmlChar ** local)5830 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5831 xmlSchemaPtr schema,
5832 xmlSchemaBasicItemPtr ownerItem,
5833 xmlAttrPtr attr,
5834 const xmlChar **uri,
5835 const xmlChar **local)
5836 {
5837 const xmlChar *value;
5838
5839 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5840 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5841 ownerItem, attr, value, uri, local));
5842 }
5843
5844 /**
5845 * xmlSchemaPValAttrQName:
5846 * @ctxt: a schema parser context
5847 * @schema: the schema context
5848 * @ownerItem: the owner as a schema object
5849 * @ownerElem: the parent node of the attribute
5850 * @name: the name of the attribute
5851 * @uri: the resulting namespace URI if found
5852 * @local: the resulting local part if found, the attribute value otherwise
5853 *
5854 * Extracts and validates the QName of an attribute value.
5855 *
5856 * Returns 0, in case the QName is valid, a positive error code
5857 * if not valid and -1 if an internal error occurs.
5858 */
5859 static int
xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar ** uri,const xmlChar ** local)5860 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5861 xmlSchemaPtr schema,
5862 xmlSchemaBasicItemPtr ownerItem,
5863 xmlNodePtr ownerElem,
5864 const char *name,
5865 const xmlChar **uri,
5866 const xmlChar **local)
5867 {
5868 xmlAttrPtr attr;
5869
5870 attr = xmlSchemaGetPropNode(ownerElem, name);
5871 if (attr == NULL) {
5872 *local = NULL;
5873 *uri = NULL;
5874 return (0);
5875 }
5876 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5877 ownerItem, attr, uri, local));
5878 }
5879
5880 /**
5881 * xmlSchemaPValAttrID:
5882 * @ctxt: a schema parser context
5883 *
5884 * Extracts and validates the ID of an attribute value.
5885 *
5886 * Returns 0, in case the ID is valid, a positive error code
5887 * if not valid and -1 if an internal error occurs.
5888 */
5889 static int
xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt,xmlAttrPtr attr)5890 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5891 {
5892 int ret;
5893 const xmlChar *value;
5894
5895 if (attr == NULL)
5896 return(0);
5897 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5898 ret = xmlValidateNCName(value, 1);
5899 if (ret == 0) {
5900 /*
5901 * NOTE: the IDness might have already be declared in the DTD
5902 */
5903 if (attr->atype != XML_ATTRIBUTE_ID) {
5904 xmlChar *strip;
5905 int res;
5906
5907 /*
5908 * TODO: Use xmlSchemaStrip here; it's not exported at this
5909 * moment.
5910 */
5911 strip = xmlSchemaCollapseString(value);
5912 if (strip != NULL) {
5913 xmlFree((xmlChar *) value);
5914 value = strip;
5915 }
5916 res = xmlAddIDSafe(attr, value);
5917 if (res < 0) {
5918 xmlSchemaPErrMemory(ctxt);
5919 } else if (res == 0) {
5920 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5921 xmlSchemaPSimpleTypeErr(ctxt,
5922 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5923 NULL, (xmlNodePtr) attr,
5924 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5925 NULL, NULL, "Duplicate value '%s' of simple "
5926 "type 'xs:ID'", value, NULL);
5927 }
5928 }
5929 } else if (ret > 0) {
5930 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5931 xmlSchemaPSimpleTypeErr(ctxt,
5932 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5933 NULL, (xmlNodePtr) attr,
5934 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5935 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5936 "not a valid 'xs:NCName'",
5937 value, NULL);
5938 }
5939 if (value != NULL)
5940 xmlFree((xmlChar *)value);
5941
5942 return (ret);
5943 }
5944
5945 static int
xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr ownerElem,const xmlChar * name)5946 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5947 xmlNodePtr ownerElem,
5948 const xmlChar *name)
5949 {
5950 xmlAttrPtr attr;
5951
5952 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5953 if (attr == NULL)
5954 return(0);
5955 return(xmlSchemaPValAttrNodeID(ctxt, attr));
5956
5957 }
5958
5959 /**
5960 * xmlGetMaxOccurs:
5961 * @ctxt: a schema validation context
5962 * @node: a subtree containing XML Schema information
5963 *
5964 * Get the maxOccurs property
5965 *
5966 * Returns the default if not found, or the value
5967 */
5968 static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)5969 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5970 int min, int max, int def, const char *expected)
5971 {
5972 const xmlChar *val, *cur;
5973 int ret = 0;
5974 xmlAttrPtr attr;
5975
5976 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5977 if (attr == NULL)
5978 return (def);
5979 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5980 if (val == NULL)
5981 return (def);
5982
5983 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
5984 if (max != UNBOUNDED) {
5985 xmlSchemaPSimpleTypeErr(ctxt,
5986 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5987 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5988 NULL, (xmlNodePtr) attr, NULL, expected,
5989 val, NULL, NULL, NULL);
5990 return (def);
5991 } else
5992 return (UNBOUNDED); /* encoding it with -1 might be another option */
5993 }
5994
5995 cur = val;
5996 while (IS_BLANK_CH(*cur))
5997 cur++;
5998 if (*cur == 0) {
5999 xmlSchemaPSimpleTypeErr(ctxt,
6000 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6001 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6002 NULL, (xmlNodePtr) attr, NULL, expected,
6003 val, NULL, NULL, NULL);
6004 return (def);
6005 }
6006 while ((*cur >= '0') && (*cur <= '9')) {
6007 if (ret > INT_MAX / 10) {
6008 ret = INT_MAX;
6009 } else {
6010 int digit = *cur - '0';
6011 ret *= 10;
6012 if (ret > INT_MAX - digit)
6013 ret = INT_MAX;
6014 else
6015 ret += digit;
6016 }
6017 cur++;
6018 }
6019 while (IS_BLANK_CH(*cur))
6020 cur++;
6021 /*
6022 * TODO: Restrict the maximal value to Integer.
6023 */
6024 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6025 xmlSchemaPSimpleTypeErr(ctxt,
6026 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6027 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6028 NULL, (xmlNodePtr) attr, NULL, expected,
6029 val, NULL, NULL, NULL);
6030 return (def);
6031 }
6032 return (ret);
6033 }
6034
6035 /**
6036 * xmlGetMinOccurs:
6037 * @ctxt: a schema validation context
6038 * @node: a subtree containing XML Schema information
6039 *
6040 * Get the minOccurs property
6041 *
6042 * Returns the default if not found, or the value
6043 */
6044 static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6045 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6046 int min, int max, int def, const char *expected)
6047 {
6048 const xmlChar *val, *cur;
6049 int ret = 0;
6050 xmlAttrPtr attr;
6051
6052 attr = xmlSchemaGetPropNode(node, "minOccurs");
6053 if (attr == NULL)
6054 return (def);
6055 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6056 if (val == NULL)
6057 return (def);
6058 cur = val;
6059 while (IS_BLANK_CH(*cur))
6060 cur++;
6061 if (*cur == 0) {
6062 xmlSchemaPSimpleTypeErr(ctxt,
6063 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6064 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6065 NULL, (xmlNodePtr) attr, NULL, expected,
6066 val, NULL, NULL, NULL);
6067 return (def);
6068 }
6069 while ((*cur >= '0') && (*cur <= '9')) {
6070 if (ret > INT_MAX / 10) {
6071 ret = INT_MAX;
6072 } else {
6073 int digit = *cur - '0';
6074 ret *= 10;
6075 if (ret > INT_MAX - digit)
6076 ret = INT_MAX;
6077 else
6078 ret += digit;
6079 }
6080 cur++;
6081 }
6082 while (IS_BLANK_CH(*cur))
6083 cur++;
6084 /*
6085 * TODO: Restrict the maximal value to Integer.
6086 */
6087 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6088 xmlSchemaPSimpleTypeErr(ctxt,
6089 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6090 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6091 NULL, (xmlNodePtr) attr, NULL, expected,
6092 val, NULL, NULL, NULL);
6093 return (def);
6094 }
6095 return (ret);
6096 }
6097
6098 /**
6099 * xmlSchemaPGetBoolNodeValue:
6100 * @ctxt: a schema validation context
6101 * @ownerItem: the owner as a schema item
6102 * @node: the node holding the value
6103 *
6104 * Converts a boolean string value into 1 or 0.
6105 *
6106 * Returns 0 or 1.
6107 */
6108 static int
xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr node)6109 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6110 xmlSchemaBasicItemPtr ownerItem,
6111 xmlNodePtr node)
6112 {
6113 xmlChar *value = NULL;
6114 int res = 0;
6115
6116 value = xmlNodeGetContent(node);
6117 /*
6118 * 3.2.2.1 Lexical representation
6119 * An instance of a datatype that is defined as `boolean`
6120 * can have the following legal literals {true, false, 1, 0}.
6121 */
6122 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6123 res = 1;
6124 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6125 res = 0;
6126 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6127 res = 1;
6128 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6129 res = 0;
6130 else {
6131 xmlSchemaPSimpleTypeErr(ctxt,
6132 XML_SCHEMAP_INVALID_BOOLEAN,
6133 ownerItem, node,
6134 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6135 NULL, BAD_CAST value,
6136 NULL, NULL, NULL);
6137 }
6138 if (value != NULL)
6139 xmlFree(value);
6140 return (res);
6141 }
6142
6143 /**
6144 * xmlGetBooleanProp:
6145 * @ctxt: a schema validation context
6146 * @node: a subtree containing XML Schema information
6147 * @name: the attribute name
6148 * @def: the default value
6149 *
6150 * Evaluate if a boolean property is set
6151 *
6152 * Returns the default if not found, 0 if found to be false,
6153 * 1 if found to be true
6154 */
6155 static int
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,int def)6156 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6157 xmlNodePtr node,
6158 const char *name, int def)
6159 {
6160 const xmlChar *val;
6161
6162 val = xmlSchemaGetProp(ctxt, node, name);
6163 if (val == NULL)
6164 return (def);
6165 /*
6166 * 3.2.2.1 Lexical representation
6167 * An instance of a datatype that is defined as `boolean`
6168 * can have the following legal literals {true, false, 1, 0}.
6169 */
6170 if (xmlStrEqual(val, BAD_CAST "true"))
6171 def = 1;
6172 else if (xmlStrEqual(val, BAD_CAST "false"))
6173 def = 0;
6174 else if (xmlStrEqual(val, BAD_CAST "1"))
6175 def = 1;
6176 else if (xmlStrEqual(val, BAD_CAST "0"))
6177 def = 0;
6178 else {
6179 xmlSchemaPSimpleTypeErr(ctxt,
6180 XML_SCHEMAP_INVALID_BOOLEAN,
6181 NULL,
6182 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6183 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6184 NULL, val, NULL, NULL, NULL);
6185 }
6186 return (def);
6187 }
6188
6189 /************************************************************************
6190 * *
6191 * Schema extraction from an Infoset *
6192 * *
6193 ************************************************************************/
6194 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6195 ctxt, xmlSchemaPtr schema,
6196 xmlNodePtr node,
6197 int topLevel);
6198 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6199 ctxt,
6200 xmlSchemaPtr schema,
6201 xmlNodePtr node,
6202 int topLevel);
6203 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6204 ctxt,
6205 xmlSchemaPtr schema,
6206 xmlNodePtr node,
6207 xmlSchemaTypeType parentType);
6208 static xmlSchemaBasicItemPtr
6209 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6210 xmlSchemaPtr schema,
6211 xmlNodePtr node,
6212 xmlSchemaItemListPtr uses,
6213 int parentType);
6214 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6215 xmlSchemaPtr schema,
6216 xmlNodePtr node);
6217 static xmlSchemaWildcardPtr
6218 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6219 xmlSchemaPtr schema, xmlNodePtr node);
6220
6221 /**
6222 * xmlSchemaPValAttrNodeValue:
6223 *
6224 * @pctxt: a schema parser context
6225 * @ownerItem: the schema object owner if existent
6226 * @attr: the schema attribute node being validated
6227 * @value: the value
6228 * @type: the built-in type to be validated against
6229 *
6230 * Validates a value against the given built-in type.
6231 * This one is intended to be used internally for validation
6232 * of schema attribute values during parsing of the schema.
6233 *
6234 * Returns 0 if the value is valid, a positive error code
6235 * number otherwise and -1 in case of an internal or API error.
6236 */
6237 static int
xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,xmlSchemaTypePtr type)6238 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6239 xmlSchemaBasicItemPtr ownerItem,
6240 xmlAttrPtr attr,
6241 const xmlChar *value,
6242 xmlSchemaTypePtr type)
6243 {
6244
6245 int ret = 0;
6246
6247 /*
6248 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6249 * one is really meant to be used internally, so better not.
6250 */
6251 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6252 return (-1);
6253 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6254 PERROR_INT("xmlSchemaPValAttrNodeValue",
6255 "the given type is not a built-in type");
6256 return (-1);
6257 }
6258 switch (type->builtInType) {
6259 case XML_SCHEMAS_NCNAME:
6260 case XML_SCHEMAS_QNAME:
6261 case XML_SCHEMAS_ANYURI:
6262 case XML_SCHEMAS_TOKEN:
6263 case XML_SCHEMAS_LANGUAGE:
6264 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6265 (xmlNodePtr) attr);
6266 break;
6267 default: {
6268 PERROR_INT("xmlSchemaPValAttrNodeValue",
6269 "validation using the given type is not supported while "
6270 "parsing a schema");
6271 return (-1);
6272 }
6273 }
6274 /*
6275 * TODO: Should we use the S4S error codes instead?
6276 */
6277 if (ret < 0) {
6278 PERROR_INT("xmlSchemaPValAttrNodeValue",
6279 "failed to validate a schema attribute value");
6280 return (-1);
6281 } else if (ret > 0) {
6282 if (WXS_IS_LIST(type))
6283 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6284 else
6285 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6286 xmlSchemaPSimpleTypeErr(pctxt,
6287 ret, ownerItem, (xmlNodePtr) attr,
6288 type, NULL, value, NULL, NULL, NULL);
6289 }
6290 return (ret);
6291 }
6292
6293 /**
6294 * xmlSchemaPValAttrNode:
6295 *
6296 * @ctxt: a schema parser context
6297 * @ownerItem: the schema object owner if existent
6298 * @attr: the schema attribute node being validated
6299 * @type: the built-in type to be validated against
6300 * @value: the resulting value if any
6301 *
6302 * Extracts and validates a value against the given built-in type.
6303 * This one is intended to be used internally for validation
6304 * of schema attribute values during parsing of the schema.
6305 *
6306 * Returns 0 if the value is valid, a positive error code
6307 * number otherwise and -1 in case of an internal or API error.
6308 */
6309 static int
xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,xmlSchemaTypePtr type,const xmlChar ** value)6310 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6311 xmlSchemaBasicItemPtr ownerItem,
6312 xmlAttrPtr attr,
6313 xmlSchemaTypePtr type,
6314 const xmlChar **value)
6315 {
6316 const xmlChar *val;
6317
6318 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6319 return (-1);
6320
6321 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6322 if (value != NULL)
6323 *value = val;
6324
6325 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6326 val, type));
6327 }
6328
6329 /**
6330 * xmlSchemaPValAttr:
6331 *
6332 * @ctxt: a schema parser context
6333 * @node: the element node of the attribute
6334 * @ownerItem: the schema object owner if existent
6335 * @ownerElem: the owner element node
6336 * @name: the name of the schema attribute node
6337 * @type: the built-in type to be validated against
6338 * @value: the resulting value if any
6339 *
6340 * Extracts and validates a value against the given built-in type.
6341 * This one is intended to be used internally for validation
6342 * of schema attribute values during parsing of the schema.
6343 *
6344 * Returns 0 if the value is valid, a positive error code
6345 * number otherwise and -1 in case of an internal or API error.
6346 */
6347 static int
xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,xmlSchemaTypePtr type,const xmlChar ** value)6348 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6349 xmlSchemaBasicItemPtr ownerItem,
6350 xmlNodePtr ownerElem,
6351 const char *name,
6352 xmlSchemaTypePtr type,
6353 const xmlChar **value)
6354 {
6355 xmlAttrPtr attr;
6356
6357 if ((ctxt == NULL) || (type == NULL)) {
6358 if (value != NULL)
6359 *value = NULL;
6360 return (-1);
6361 }
6362 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6363 if (value != NULL)
6364 *value = NULL;
6365 xmlSchemaPErr(ctxt, ownerElem,
6366 XML_SCHEMAP_INTERNAL,
6367 "Internal error: xmlSchemaPValAttr, the given "
6368 "type '%s' is not a built-in type.\n",
6369 type->name, NULL);
6370 return (-1);
6371 }
6372 attr = xmlSchemaGetPropNode(ownerElem, name);
6373 if (attr == NULL) {
6374 if (value != NULL)
6375 *value = NULL;
6376 return (0);
6377 }
6378 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6379 type, value));
6380 }
6381
6382 static int
xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlNodePtr node,xmlAttrPtr attr,const xmlChar * namespaceName)6383 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6384 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6385 xmlNodePtr node,
6386 xmlAttrPtr attr,
6387 const xmlChar *namespaceName)
6388 {
6389 /* TODO: Pointer comparison instead? */
6390 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6391 return (0);
6392 if (xmlStrEqual(xmlSchemaNs, namespaceName))
6393 return (0);
6394 /*
6395 * Check if the referenced namespace was <import>ed.
6396 */
6397 if (WXS_BUCKET(pctxt)->relations != NULL) {
6398 xmlSchemaSchemaRelationPtr rel;
6399
6400 rel = WXS_BUCKET(pctxt)->relations;
6401 do {
6402 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6403 xmlStrEqual(namespaceName, rel->importNamespace))
6404 return (0);
6405 rel = rel->next;
6406 } while (rel != NULL);
6407 }
6408 /*
6409 * No matching <import>ed namespace found.
6410 */
6411 {
6412 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6413
6414 if (namespaceName == NULL)
6415 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6416 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6417 "References from this schema to components in no "
6418 "namespace are not allowed, since not indicated by an "
6419 "import statement", NULL, NULL);
6420 else
6421 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6422 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6423 "References from this schema to components in the "
6424 "namespace '%s' are not allowed, since not indicated by an "
6425 "import statement", namespaceName, NULL);
6426 }
6427 return (XML_SCHEMAP_SRC_RESOLVE);
6428 }
6429
6430 /**
6431 * xmlSchemaParseLocalAttributes:
6432 * @ctxt: a schema validation context
6433 * @schema: the schema being built
6434 * @node: a subtree containing XML Schema information
6435 * @type: the hosting type where the attributes will be anchored
6436 *
6437 * Parses attribute uses and attribute declarations and
6438 * attribute group references.
6439 */
6440 static int
xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr * child,xmlSchemaItemListPtr * list,int parentType,int * hasRefs)6441 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6442 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6443 int parentType, int *hasRefs)
6444 {
6445 void *item;
6446
6447 while ((IS_SCHEMA((*child), "attribute")) ||
6448 (IS_SCHEMA((*child), "attributeGroup"))) {
6449 if (IS_SCHEMA((*child), "attribute")) {
6450 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6451 *list, parentType);
6452 } else {
6453 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6454 if ((item != NULL) && (hasRefs != NULL))
6455 *hasRefs = 1;
6456 }
6457 if (item != NULL) {
6458 if (*list == NULL) {
6459 /* TODO: Customize grow factor. */
6460 *list = xmlSchemaItemListCreate();
6461 if (*list == NULL)
6462 return(-1);
6463 }
6464 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6465 return(-1);
6466 }
6467 *child = (*child)->next;
6468 }
6469 return (0);
6470 }
6471
6472 /**
6473 * xmlSchemaParseAnnotation:
6474 * @ctxt: a schema validation context
6475 * @schema: the schema being built
6476 * @node: a subtree containing XML Schema information
6477 *
6478 * parse a XML schema Attribute declaration
6479 * *WARNING* this interface is highly subject to change
6480 *
6481 * Returns -1 in case of error, 0 if the declaration is improper and
6482 * 1 in case of success.
6483 */
6484 static xmlSchemaAnnotPtr
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int needed)6485 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6486 {
6487 xmlSchemaAnnotPtr ret;
6488 xmlNodePtr child = NULL;
6489 xmlAttrPtr attr;
6490 int barked = 0;
6491
6492 /*
6493 * INFO: S4S completed.
6494 */
6495 /*
6496 * id = ID
6497 * {any attributes with non-schema namespace . . .}>
6498 * Content: (appinfo | documentation)*
6499 */
6500 if ((ctxt == NULL) || (node == NULL))
6501 return (NULL);
6502 if (needed)
6503 ret = xmlSchemaNewAnnot(ctxt, node);
6504 else
6505 ret = NULL;
6506 attr = node->properties;
6507 while (attr != NULL) {
6508 if (((attr->ns == NULL) &&
6509 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6510 ((attr->ns != NULL) &&
6511 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6512
6513 xmlSchemaPIllegalAttrErr(ctxt,
6514 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6515 }
6516 attr = attr->next;
6517 }
6518 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6519 /*
6520 * And now for the children...
6521 */
6522 child = node->children;
6523 while (child != NULL) {
6524 if (IS_SCHEMA(child, "appinfo")) {
6525 /* TODO: make available the content of "appinfo". */
6526 /*
6527 * source = anyURI
6528 * {any attributes with non-schema namespace . . .}>
6529 * Content: ({any})*
6530 */
6531 attr = child->properties;
6532 while (attr != NULL) {
6533 if (((attr->ns == NULL) &&
6534 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6535 ((attr->ns != NULL) &&
6536 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6537
6538 xmlSchemaPIllegalAttrErr(ctxt,
6539 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6540 }
6541 attr = attr->next;
6542 }
6543 xmlSchemaPValAttr(ctxt, NULL, child, "source",
6544 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6545 child = child->next;
6546 } else if (IS_SCHEMA(child, "documentation")) {
6547 /* TODO: make available the content of "documentation". */
6548 /*
6549 * source = anyURI
6550 * {any attributes with non-schema namespace . . .}>
6551 * Content: ({any})*
6552 */
6553 attr = child->properties;
6554 while (attr != NULL) {
6555 if (attr->ns == NULL) {
6556 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6557 xmlSchemaPIllegalAttrErr(ctxt,
6558 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6559 }
6560 } else {
6561 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6562 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6563 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6564
6565 xmlSchemaPIllegalAttrErr(ctxt,
6566 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6567 }
6568 }
6569 attr = attr->next;
6570 }
6571 /*
6572 * Attribute "xml:lang".
6573 */
6574 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6575 if (attr != NULL)
6576 xmlSchemaPValAttrNode(ctxt, NULL, attr,
6577 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6578 child = child->next;
6579 } else {
6580 if (!barked)
6581 xmlSchemaPContentErr(ctxt,
6582 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6583 NULL, node, child, NULL, "(appinfo | documentation)*");
6584 barked = 1;
6585 child = child->next;
6586 }
6587 }
6588
6589 return (ret);
6590 }
6591
6592 /**
6593 * xmlSchemaParseFacet:
6594 * @ctxt: a schema validation context
6595 * @schema: the schema being built
6596 * @node: a subtree containing XML Schema information
6597 *
6598 * parse a XML schema Facet declaration
6599 * *WARNING* this interface is highly subject to change
6600 *
6601 * Returns the new type structure or NULL in case of error
6602 */
6603 static xmlSchemaFacetPtr
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6604 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6605 xmlNodePtr node)
6606 {
6607 xmlSchemaFacetPtr facet;
6608 xmlNodePtr child = NULL;
6609 const xmlChar *value;
6610
6611 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6612 return (NULL);
6613
6614 facet = xmlSchemaNewFacet();
6615 if (facet == NULL) {
6616 xmlSchemaPErrMemory(ctxt);
6617 return (NULL);
6618 }
6619 facet->node = node;
6620 value = xmlSchemaGetProp(ctxt, node, "value");
6621 if (value == NULL) {
6622 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6623 "Facet %s has no value\n", node->name, NULL);
6624 xmlSchemaFreeFacet(facet);
6625 return (NULL);
6626 }
6627 if (IS_SCHEMA(node, "minInclusive")) {
6628 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6629 } else if (IS_SCHEMA(node, "minExclusive")) {
6630 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6631 } else if (IS_SCHEMA(node, "maxInclusive")) {
6632 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6633 } else if (IS_SCHEMA(node, "maxExclusive")) {
6634 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6635 } else if (IS_SCHEMA(node, "totalDigits")) {
6636 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6637 } else if (IS_SCHEMA(node, "fractionDigits")) {
6638 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6639 } else if (IS_SCHEMA(node, "pattern")) {
6640 facet->type = XML_SCHEMA_FACET_PATTERN;
6641 } else if (IS_SCHEMA(node, "enumeration")) {
6642 facet->type = XML_SCHEMA_FACET_ENUMERATION;
6643 } else if (IS_SCHEMA(node, "whiteSpace")) {
6644 facet->type = XML_SCHEMA_FACET_WHITESPACE;
6645 } else if (IS_SCHEMA(node, "length")) {
6646 facet->type = XML_SCHEMA_FACET_LENGTH;
6647 } else if (IS_SCHEMA(node, "maxLength")) {
6648 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6649 } else if (IS_SCHEMA(node, "minLength")) {
6650 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6651 } else {
6652 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6653 "Unknown facet type %s\n", node->name, NULL);
6654 xmlSchemaFreeFacet(facet);
6655 return (NULL);
6656 }
6657 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6658 facet->value = value;
6659 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6660 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6661 const xmlChar *fixed;
6662
6663 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6664 if (fixed != NULL) {
6665 if (xmlStrEqual(fixed, BAD_CAST "true"))
6666 facet->fixed = 1;
6667 }
6668 }
6669 child = node->children;
6670
6671 if (IS_SCHEMA(child, "annotation")) {
6672 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6673 child = child->next;
6674 }
6675 if (child != NULL) {
6676 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6677 "Facet %s has unexpected child content\n",
6678 node->name, NULL);
6679 }
6680 return (facet);
6681 }
6682
6683 /**
6684 * xmlSchemaParseWildcardNs:
6685 * @ctxt: a schema parser context
6686 * @wildc: the wildcard, already created
6687 * @node: a subtree containing XML Schema information
6688 *
6689 * Parses the attribute "processContents" and "namespace"
6690 * of a xsd:anyAttribute and xsd:any.
6691 * *WARNING* this interface is highly subject to change
6692 *
6693 * Returns 0 if everything goes fine, a positive error code
6694 * if something is not valid and -1 if an internal error occurs.
6695 */
6696 static int
xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlSchemaWildcardPtr wildc,xmlNodePtr node)6697 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6698 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6699 xmlSchemaWildcardPtr wildc,
6700 xmlNodePtr node)
6701 {
6702 const xmlChar *pc, *ns, *dictnsItem;
6703 int ret = 0;
6704 xmlChar *nsItem;
6705 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6706 xmlAttrPtr attr;
6707
6708 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6709 if ((pc == NULL)
6710 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6711 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6712 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6713 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6714 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6715 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6716 } else {
6717 xmlSchemaPSimpleTypeErr(ctxt,
6718 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6719 NULL, node,
6720 NULL, "(strict | skip | lax)", pc,
6721 NULL, NULL, NULL);
6722 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6723 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6724 }
6725 /*
6726 * Build the namespace constraints.
6727 */
6728 attr = xmlSchemaGetPropNode(node, "namespace");
6729 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6730 if (ns == NULL)
6731 return (-1);
6732 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6733 wildc->any = 1;
6734 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6735 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6736 if (wildc->negNsSet == NULL) {
6737 return (-1);
6738 }
6739 wildc->negNsSet->value = ctxt->targetNamespace;
6740 } else {
6741 const xmlChar *end, *cur;
6742
6743 cur = ns;
6744 do {
6745 while (IS_BLANK_CH(*cur))
6746 cur++;
6747 end = cur;
6748 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6749 end++;
6750 if (end == cur)
6751 break;
6752 nsItem = xmlStrndup(cur, end - cur);
6753 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6754 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6755 xmlSchemaPSimpleTypeErr(ctxt,
6756 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6757 NULL, (xmlNodePtr) attr,
6758 NULL,
6759 "((##any | ##other) | List of (xs:anyURI | "
6760 "(##targetNamespace | ##local)))",
6761 nsItem, NULL, NULL, NULL);
6762 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6763 } else {
6764 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6765 dictnsItem = ctxt->targetNamespace;
6766 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6767 dictnsItem = NULL;
6768 } else {
6769 /*
6770 * Validate the item (anyURI).
6771 */
6772 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6773 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6774 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6775 }
6776 /*
6777 * Avoid duplicate namespaces.
6778 */
6779 tmp = wildc->nsSet;
6780 while (tmp != NULL) {
6781 if (dictnsItem == tmp->value)
6782 break;
6783 tmp = tmp->next;
6784 }
6785 if (tmp == NULL) {
6786 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6787 if (tmp == NULL) {
6788 xmlFree(nsItem);
6789 return (-1);
6790 }
6791 tmp->value = dictnsItem;
6792 tmp->next = NULL;
6793 if (wildc->nsSet == NULL)
6794 wildc->nsSet = tmp;
6795 else if (lastNs != NULL)
6796 lastNs->next = tmp;
6797 lastNs = tmp;
6798 }
6799
6800 }
6801 xmlFree(nsItem);
6802 cur = end;
6803 } while (*cur != 0);
6804 }
6805 return (ret);
6806 }
6807
6808 static int
xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,xmlNodePtr node,int minOccurs,int maxOccurs)6809 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6810 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6811 xmlNodePtr node,
6812 int minOccurs,
6813 int maxOccurs) {
6814
6815 if ((maxOccurs == 0) && ( minOccurs == 0))
6816 return (0);
6817 if (maxOccurs != UNBOUNDED) {
6818 /*
6819 * TODO: Maybe we should better not create the particle,
6820 * if min/max is invalid, since it could confuse the build of the
6821 * content model.
6822 */
6823 /*
6824 * 3.9.6 Schema Component Constraint: Particle Correct
6825 *
6826 */
6827 if (maxOccurs < 1) {
6828 /*
6829 * 2.2 {max occurs} must be greater than or equal to 1.
6830 */
6831 xmlSchemaPCustomAttrErr(ctxt,
6832 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6833 NULL, NULL,
6834 xmlSchemaGetPropNode(node, "maxOccurs"),
6835 "The value must be greater than or equal to 1");
6836 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6837 } else if (minOccurs > maxOccurs) {
6838 /*
6839 * 2.1 {min occurs} must not be greater than {max occurs}.
6840 */
6841 xmlSchemaPCustomAttrErr(ctxt,
6842 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6843 NULL, NULL,
6844 xmlSchemaGetPropNode(node, "minOccurs"),
6845 "The value must not be greater than the value of 'maxOccurs'");
6846 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6847 }
6848 }
6849 return (0);
6850 }
6851
6852 /**
6853 * xmlSchemaParseAny:
6854 * @ctxt: a schema validation context
6855 * @schema: the schema being built
6856 * @node: a subtree containing XML Schema information
6857 *
6858 * Parsea a XML schema <any> element. A particle and wildcard
6859 * will be created (except if minOccurs==maxOccurs==0, in this case
6860 * nothing will be created).
6861 * *WARNING* this interface is highly subject to change
6862 *
6863 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6864 */
6865 static xmlSchemaParticlePtr
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6866 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6867 xmlNodePtr node)
6868 {
6869 xmlSchemaParticlePtr particle;
6870 xmlNodePtr child = NULL;
6871 xmlSchemaWildcardPtr wild;
6872 int min, max;
6873 xmlAttrPtr attr;
6874 xmlSchemaAnnotPtr annot = NULL;
6875
6876 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6877 return (NULL);
6878 /*
6879 * Check for illegal attributes.
6880 */
6881 attr = node->properties;
6882 while (attr != NULL) {
6883 if (attr->ns == NULL) {
6884 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6885 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6886 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6887 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6888 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6889 xmlSchemaPIllegalAttrErr(ctxt,
6890 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6891 }
6892 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6893 xmlSchemaPIllegalAttrErr(ctxt,
6894 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6895 }
6896 attr = attr->next;
6897 }
6898 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6899 /*
6900 * minOccurs/maxOccurs.
6901 */
6902 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6903 "(xs:nonNegativeInteger | unbounded)");
6904 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6905 "xs:nonNegativeInteger");
6906 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6907 /*
6908 * Create & parse the wildcard.
6909 */
6910 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6911 if (wild == NULL)
6912 return (NULL);
6913 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6914 /*
6915 * And now for the children...
6916 */
6917 child = node->children;
6918 if (IS_SCHEMA(child, "annotation")) {
6919 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6920 child = child->next;
6921 }
6922 if (child != NULL) {
6923 xmlSchemaPContentErr(ctxt,
6924 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6925 NULL, node, child,
6926 NULL, "(annotation?)");
6927 }
6928 /*
6929 * No component if minOccurs==maxOccurs==0.
6930 */
6931 if ((min == 0) && (max == 0)) {
6932 /* Don't free the wildcard, since it's already on the list. */
6933 return (NULL);
6934 }
6935 /*
6936 * Create the particle.
6937 */
6938 particle = xmlSchemaAddParticle(ctxt, node, min, max);
6939 if (particle == NULL)
6940 return (NULL);
6941 particle->annot = annot;
6942 particle->children = (xmlSchemaTreeItemPtr) wild;
6943
6944 return (particle);
6945 }
6946
6947 /**
6948 * xmlSchemaParseNotation:
6949 * @ctxt: a schema validation context
6950 * @schema: the schema being built
6951 * @node: a subtree containing XML Schema information
6952 *
6953 * parse a XML schema Notation declaration
6954 *
6955 * Returns the new structure or NULL in case of error
6956 */
6957 static xmlSchemaNotationPtr
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6958 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6959 xmlNodePtr node)
6960 {
6961 const xmlChar *name;
6962 xmlSchemaNotationPtr ret;
6963 xmlNodePtr child = NULL;
6964
6965 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6966 return (NULL);
6967 name = xmlSchemaGetProp(ctxt, node, "name");
6968 if (name == NULL) {
6969 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6970 "Notation has no name\n", NULL, NULL);
6971 return (NULL);
6972 }
6973 ret = xmlSchemaAddNotation(ctxt, schema, name,
6974 ctxt->targetNamespace, node);
6975 if (ret == NULL)
6976 return (NULL);
6977 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6978
6979 child = node->children;
6980 if (IS_SCHEMA(child, "annotation")) {
6981 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6982 child = child->next;
6983 }
6984 if (child != NULL) {
6985 xmlSchemaPContentErr(ctxt,
6986 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6987 NULL, node, child,
6988 NULL, "(annotation?)");
6989 }
6990
6991 return (ret);
6992 }
6993
6994 /**
6995 * xmlSchemaParseAnyAttribute:
6996 * @ctxt: a schema validation context
6997 * @schema: the schema being built
6998 * @node: a subtree containing XML Schema information
6999 *
7000 * parse a XML schema AnyAttribute declaration
7001 * *WARNING* this interface is highly subject to change
7002 *
7003 * Returns a wildcard or NULL.
7004 */
7005 static xmlSchemaWildcardPtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7006 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7007 xmlSchemaPtr schema, xmlNodePtr node)
7008 {
7009 xmlSchemaWildcardPtr ret;
7010 xmlNodePtr child = NULL;
7011 xmlAttrPtr attr;
7012
7013 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7014 return (NULL);
7015
7016 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7017 node);
7018 if (ret == NULL) {
7019 return (NULL);
7020 }
7021 /*
7022 * Check for illegal attributes.
7023 */
7024 attr = node->properties;
7025 while (attr != NULL) {
7026 if (attr->ns == NULL) {
7027 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7028 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7029 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7030 xmlSchemaPIllegalAttrErr(ctxt,
7031 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7032 }
7033 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7034 xmlSchemaPIllegalAttrErr(ctxt,
7035 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7036 }
7037 attr = attr->next;
7038 }
7039 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7040 /*
7041 * Parse the namespace list.
7042 */
7043 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7044 return (NULL);
7045 /*
7046 * And now for the children...
7047 */
7048 child = node->children;
7049 if (IS_SCHEMA(child, "annotation")) {
7050 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7051 child = child->next;
7052 }
7053 if (child != NULL) {
7054 xmlSchemaPContentErr(ctxt,
7055 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7056 NULL, node, child,
7057 NULL, "(annotation?)");
7058 }
7059
7060 return (ret);
7061 }
7062
7063
7064 /**
7065 * xmlSchemaParseAttribute:
7066 * @ctxt: a schema validation context
7067 * @schema: the schema being built
7068 * @node: a subtree containing XML Schema information
7069 *
7070 * parse a XML schema Attribute declaration
7071 * *WARNING* this interface is highly subject to change
7072 *
7073 * Returns the attribute declaration.
7074 */
7075 static xmlSchemaBasicItemPtr
xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaItemListPtr uses,int parentType)7076 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7077 xmlSchemaPtr schema,
7078 xmlNodePtr node,
7079 xmlSchemaItemListPtr uses,
7080 int parentType)
7081 {
7082 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7083 xmlSchemaAttributeUsePtr use = NULL;
7084 xmlNodePtr child = NULL;
7085 xmlAttrPtr attr;
7086 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7087 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7088 int nberrors, hasForm = 0, defValueType = 0;
7089
7090 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7091 #define WXS_ATTR_DEF_VAL_FIXED 2
7092
7093 /*
7094 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7095 */
7096
7097 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7098 return (NULL);
7099 attr = xmlSchemaGetPropNode(node, "ref");
7100 if (attr != NULL) {
7101 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7102 NULL, attr, &tmpNs, &tmpName) != 0) {
7103 return (NULL);
7104 }
7105 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7106 return(NULL);
7107 isRef = 1;
7108 }
7109 nberrors = pctxt->nberrors;
7110 /*
7111 * Check for illegal attributes.
7112 */
7113 attr = node->properties;
7114 while (attr != NULL) {
7115 if (attr->ns == NULL) {
7116 if (isRef) {
7117 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7118 xmlSchemaPValAttrNodeID(pctxt, attr);
7119 goto attr_next;
7120 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7121 goto attr_next;
7122 }
7123 } else {
7124 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7125 goto attr_next;
7126 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7127 xmlSchemaPValAttrNodeID(pctxt, attr);
7128 goto attr_next;
7129 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7130 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7131 attr, &tmpNs, &tmpName);
7132 goto attr_next;
7133 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7134 /*
7135 * Evaluate the target namespace
7136 */
7137 hasForm = 1;
7138 attrValue = xmlSchemaGetNodeContent(pctxt,
7139 (xmlNodePtr) attr);
7140 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7141 ns = pctxt->targetNamespace;
7142 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7143 {
7144 xmlSchemaPSimpleTypeErr(pctxt,
7145 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7146 NULL, (xmlNodePtr) attr,
7147 NULL, "(qualified | unqualified)",
7148 attrValue, NULL, NULL, NULL);
7149 }
7150 goto attr_next;
7151 }
7152 }
7153 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7154
7155 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7156 /* TODO: Maybe we need to normalize the value beforehand. */
7157 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7158 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7159 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7160 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7161 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7162 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7163 else {
7164 xmlSchemaPSimpleTypeErr(pctxt,
7165 XML_SCHEMAP_INVALID_ATTR_USE,
7166 NULL, (xmlNodePtr) attr,
7167 NULL, "(optional | prohibited | required)",
7168 attrValue, NULL, NULL, NULL);
7169 }
7170 goto attr_next;
7171 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7172 /*
7173 * 3.2.3 : 1
7174 * default and fixed must not both be present.
7175 */
7176 if (defValue) {
7177 xmlSchemaPMutualExclAttrErr(pctxt,
7178 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7179 NULL, attr, "default", "fixed");
7180 } else {
7181 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7182 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7183 }
7184 goto attr_next;
7185 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7186 /*
7187 * 3.2.3 : 1
7188 * default and fixed must not both be present.
7189 */
7190 if (defValue) {
7191 xmlSchemaPMutualExclAttrErr(pctxt,
7192 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7193 NULL, attr, "default", "fixed");
7194 } else {
7195 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7196 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7197 }
7198 goto attr_next;
7199 }
7200 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7201 goto attr_next;
7202
7203 xmlSchemaPIllegalAttrErr(pctxt,
7204 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7205
7206 attr_next:
7207 attr = attr->next;
7208 }
7209 /*
7210 * 3.2.3 : 2
7211 * If default and use are both present, use must have
7212 * the actual value optional.
7213 */
7214 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7215 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7216 xmlSchemaPSimpleTypeErr(pctxt,
7217 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7218 NULL, node, NULL,
7219 "(optional | prohibited | required)", NULL,
7220 "The value of the attribute 'use' must be 'optional' "
7221 "if the attribute 'default' is present",
7222 NULL, NULL);
7223 }
7224 /*
7225 * We want correct attributes.
7226 */
7227 if (nberrors != pctxt->nberrors)
7228 return(NULL);
7229 if (! isRef) {
7230 xmlSchemaAttributePtr attrDecl;
7231
7232 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7233 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7234 ns = pctxt->targetNamespace;
7235 /*
7236 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7237 * TODO: Move this to the component layer.
7238 */
7239 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7240 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7241 XML_SCHEMAP_NO_XSI,
7242 node, NULL,
7243 "The target namespace must not match '%s'",
7244 xmlSchemaInstanceNs, NULL);
7245 }
7246 attr = xmlSchemaGetPropNode(node, "name");
7247 if (attr == NULL) {
7248 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7249 NULL, node, "name", NULL);
7250 return (NULL);
7251 }
7252 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7253 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7254 return (NULL);
7255 }
7256 /*
7257 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7258 * TODO: Move this to the component layer.
7259 */
7260 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7261 xmlSchemaPSimpleTypeErr(pctxt,
7262 XML_SCHEMAP_NO_XMLNS,
7263 NULL, (xmlNodePtr) attr,
7264 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7265 "The value of the attribute must not match 'xmlns'",
7266 NULL, NULL);
7267 return (NULL);
7268 }
7269 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7270 goto check_children;
7271 /*
7272 * Create the attribute use component.
7273 */
7274 use = xmlSchemaAddAttributeUse(pctxt, node);
7275 if (use == NULL)
7276 return(NULL);
7277 use->occurs = occurs;
7278 /*
7279 * Create the attribute declaration.
7280 */
7281 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7282 if (attrDecl == NULL)
7283 return (NULL);
7284 if (tmpName != NULL) {
7285 attrDecl->typeName = tmpName;
7286 attrDecl->typeNs = tmpNs;
7287 }
7288 use->attrDecl = attrDecl;
7289 /*
7290 * Value constraint.
7291 */
7292 if (defValue != NULL) {
7293 attrDecl->defValue = defValue;
7294 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7295 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7296 }
7297 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7298 xmlSchemaQNameRefPtr ref;
7299
7300 /*
7301 * Create the attribute use component.
7302 */
7303 use = xmlSchemaAddAttributeUse(pctxt, node);
7304 if (use == NULL)
7305 return(NULL);
7306 /*
7307 * We need to resolve the reference at later stage.
7308 */
7309 WXS_ADD_PENDING(pctxt, use);
7310 use->occurs = occurs;
7311 /*
7312 * Create a QName reference to the attribute declaration.
7313 */
7314 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7315 tmpName, tmpNs);
7316 if (ref == NULL)
7317 return(NULL);
7318 /*
7319 * Assign the reference. This will be substituted for the
7320 * referenced attribute declaration when the QName is resolved.
7321 */
7322 use->attrDecl = WXS_ATTR_CAST ref;
7323 /*
7324 * Value constraint.
7325 */
7326 if (defValue != NULL)
7327 use->defValue = defValue;
7328 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7329 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7330 }
7331
7332 check_children:
7333 /*
7334 * And now for the children...
7335 */
7336 child = node->children;
7337 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7338 xmlSchemaAttributeUseProhibPtr prohib;
7339
7340 if (IS_SCHEMA(child, "annotation")) {
7341 xmlSchemaParseAnnotation(pctxt, child, 0);
7342 child = child->next;
7343 }
7344 if (child != NULL) {
7345 xmlSchemaPContentErr(pctxt,
7346 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7347 NULL, node, child, NULL,
7348 "(annotation?)");
7349 }
7350 /*
7351 * Check for pointlessness of attribute prohibitions.
7352 */
7353 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7354 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7355 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7356 node, NULL,
7357 "Skipping attribute use prohibition, since it is "
7358 "pointless inside an <attributeGroup>",
7359 NULL, NULL, NULL);
7360 return(NULL);
7361 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7362 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7363 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7364 node, NULL,
7365 "Skipping attribute use prohibition, since it is "
7366 "pointless when extending a type",
7367 NULL, NULL, NULL);
7368 return(NULL);
7369 }
7370 if (! isRef) {
7371 tmpName = name;
7372 tmpNs = ns;
7373 }
7374 /*
7375 * Check for duplicate attribute prohibitions.
7376 */
7377 if (uses) {
7378 int i;
7379
7380 for (i = 0; i < uses->nbItems; i++) {
7381 use = uses->items[i];
7382 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7383 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7384 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7385 {
7386 xmlChar *str = NULL;
7387
7388 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7389 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7390 node, NULL,
7391 "Skipping duplicate attribute use prohibition '%s'",
7392 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7393 NULL, NULL);
7394 FREE_AND_NULL(str)
7395 return(NULL);
7396 }
7397 }
7398 }
7399 /*
7400 * Create the attribute prohibition helper component.
7401 */
7402 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7403 if (prohib == NULL)
7404 return(NULL);
7405 prohib->node = node;
7406 prohib->name = tmpName;
7407 prohib->targetNamespace = tmpNs;
7408 if (isRef) {
7409 /*
7410 * We need at least to resolve to the attribute declaration.
7411 */
7412 WXS_ADD_PENDING(pctxt, prohib);
7413 }
7414 return(WXS_BASIC_CAST prohib);
7415 } else {
7416 if (IS_SCHEMA(child, "annotation")) {
7417 /*
7418 * TODO: Should this go into the attr decl?
7419 */
7420 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7421 child = child->next;
7422 }
7423 if (isRef) {
7424 if (child != NULL) {
7425 if (IS_SCHEMA(child, "simpleType"))
7426 /*
7427 * 3.2.3 : 3.2
7428 * If ref is present, then all of <simpleType>,
7429 * form and type must be absent.
7430 */
7431 xmlSchemaPContentErr(pctxt,
7432 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7433 NULL, node, child, NULL,
7434 "(annotation?)");
7435 else
7436 xmlSchemaPContentErr(pctxt,
7437 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7438 NULL, node, child, NULL,
7439 "(annotation?)");
7440 }
7441 } else {
7442 if (IS_SCHEMA(child, "simpleType")) {
7443 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7444 /*
7445 * 3.2.3 : 4
7446 * type and <simpleType> must not both be present.
7447 */
7448 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7449 NULL, node, child,
7450 "The attribute 'type' and the <simpleType> child "
7451 "are mutually exclusive", NULL);
7452 } else
7453 WXS_ATTRUSE_TYPEDEF(use) =
7454 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7455 child = child->next;
7456 }
7457 if (child != NULL)
7458 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7459 NULL, node, child, NULL,
7460 "(annotation?, simpleType?)");
7461 }
7462 }
7463 return (WXS_BASIC_CAST use);
7464 }
7465
7466
7467 static xmlSchemaAttributePtr
xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7468 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7469 xmlSchemaPtr schema,
7470 xmlNodePtr node)
7471 {
7472 const xmlChar *attrValue;
7473 xmlSchemaAttributePtr ret;
7474 xmlNodePtr child = NULL;
7475 xmlAttrPtr attr;
7476
7477 /*
7478 * Note that the w3c spec assumes the schema to be validated with schema
7479 * for schemas beforehand.
7480 *
7481 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7482 */
7483 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7484 return (NULL);
7485 /*
7486 * 3.2.3 : 3.1
7487 * One of ref or name must be present, but not both
7488 */
7489 attr = xmlSchemaGetPropNode(node, "name");
7490 if (attr == NULL) {
7491 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7492 NULL, node, "name", NULL);
7493 return (NULL);
7494 }
7495 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7496 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7497 return (NULL);
7498 }
7499 /*
7500 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7501 * TODO: Move this to the component layer.
7502 */
7503 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7504 xmlSchemaPSimpleTypeErr(pctxt,
7505 XML_SCHEMAP_NO_XMLNS,
7506 NULL, (xmlNodePtr) attr,
7507 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7508 "The value of the attribute must not match 'xmlns'",
7509 NULL, NULL);
7510 return (NULL);
7511 }
7512 /*
7513 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7514 * TODO: Move this to the component layer.
7515 * Or better leave it here and add it to the component layer
7516 * if we have a schema construction API.
7517 */
7518 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7519 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7520 XML_SCHEMAP_NO_XSI, node, NULL,
7521 "The target namespace must not match '%s'",
7522 xmlSchemaInstanceNs, NULL);
7523 }
7524
7525 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7526 pctxt->targetNamespace, node, 1);
7527 if (ret == NULL)
7528 return (NULL);
7529 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7530
7531 /*
7532 * Check for illegal attributes.
7533 */
7534 attr = node->properties;
7535 while (attr != NULL) {
7536 if (attr->ns == NULL) {
7537 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7538 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7539 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7540 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7541 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7542 {
7543 xmlSchemaPIllegalAttrErr(pctxt,
7544 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7545 }
7546 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7547 xmlSchemaPIllegalAttrErr(pctxt,
7548 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7549 }
7550 attr = attr->next;
7551 }
7552 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7553 node, "type", &ret->typeNs, &ret->typeName);
7554
7555 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7556 /*
7557 * Attribute "fixed".
7558 */
7559 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7560 if (ret->defValue != NULL)
7561 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7562 /*
7563 * Attribute "default".
7564 */
7565 attr = xmlSchemaGetPropNode(node, "default");
7566 if (attr != NULL) {
7567 /*
7568 * 3.2.3 : 1
7569 * default and fixed must not both be present.
7570 */
7571 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7572 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7573 WXS_BASIC_CAST ret, attr, "default", "fixed");
7574 } else
7575 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7576 }
7577 /*
7578 * And now for the children...
7579 */
7580 child = node->children;
7581 if (IS_SCHEMA(child, "annotation")) {
7582 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7583 child = child->next;
7584 }
7585 if (IS_SCHEMA(child, "simpleType")) {
7586 if (ret->typeName != NULL) {
7587 /*
7588 * 3.2.3 : 4
7589 * type and <simpleType> must not both be present.
7590 */
7591 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7592 NULL, node, child,
7593 "The attribute 'type' and the <simpleType> child "
7594 "are mutually exclusive", NULL);
7595 } else
7596 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7597 child = child->next;
7598 }
7599 if (child != NULL)
7600 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7601 NULL, node, child, NULL,
7602 "(annotation?, simpleType?)");
7603
7604 return (ret);
7605 }
7606
7607 /**
7608 * xmlSchemaParseAttributeGroupRef:
7609 * @ctxt: a schema validation context
7610 * @schema: the schema being built
7611 * @node: a subtree containing XML Schema information
7612 *
7613 * Parse an attribute group definition reference.
7614 * Note that a reference to an attribute group does not
7615 * correspond to any component at all.
7616 * *WARNING* this interface is highly subject to change
7617 *
7618 * Returns the attribute group or NULL in case of error.
7619 */
7620 static xmlSchemaQNameRefPtr
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7621 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7622 xmlSchemaPtr schema,
7623 xmlNodePtr node)
7624 {
7625 xmlSchemaQNameRefPtr ret;
7626 xmlNodePtr child = NULL;
7627 xmlAttrPtr attr;
7628 const xmlChar *refNs = NULL, *ref = NULL;
7629
7630 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7631 return (NULL);
7632
7633 attr = xmlSchemaGetPropNode(node, "ref");
7634 if (attr == NULL) {
7635 xmlSchemaPMissingAttrErr(pctxt,
7636 XML_SCHEMAP_S4S_ATTR_MISSING,
7637 NULL, node, "ref", NULL);
7638 return (NULL);
7639 }
7640 xmlSchemaPValAttrNodeQName(pctxt, schema,
7641 NULL, attr, &refNs, &ref);
7642 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7643 return(NULL);
7644
7645 /*
7646 * Check for illegal attributes.
7647 */
7648 attr = node->properties;
7649 while (attr != NULL) {
7650 if (attr->ns == NULL) {
7651 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7652 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7653 {
7654 xmlSchemaPIllegalAttrErr(pctxt,
7655 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7656 }
7657 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7658 xmlSchemaPIllegalAttrErr(pctxt,
7659 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7660 }
7661 attr = attr->next;
7662 }
7663 /* Attribute ID */
7664 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7665
7666 /*
7667 * And now for the children...
7668 */
7669 child = node->children;
7670 if (IS_SCHEMA(child, "annotation")) {
7671 /*
7672 * TODO: We do not have a place to store the annotation, do we?
7673 */
7674 xmlSchemaParseAnnotation(pctxt, child, 0);
7675 child = child->next;
7676 }
7677 if (child != NULL) {
7678 xmlSchemaPContentErr(pctxt,
7679 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7680 NULL, node, child, NULL,
7681 "(annotation?)");
7682 }
7683
7684 /*
7685 * Handle attribute group redefinitions.
7686 */
7687 if (pctxt->isRedefine && pctxt->redef &&
7688 (pctxt->redef->item->type ==
7689 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7690 (ref == pctxt->redef->refName) &&
7691 (refNs == pctxt->redef->refTargetNs))
7692 {
7693 /*
7694 * SPEC src-redefine:
7695 * (7.1) "If it has an <attributeGroup> among its contents
7696 * the `actual value` of whose ref [attribute] is the same
7697 * as the `actual value` of its own name attribute plus
7698 * target namespace, then it must have exactly one such group."
7699 */
7700 if (pctxt->redefCounter != 0) {
7701 xmlChar *str = NULL;
7702
7703 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7704 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7705 "The redefining attribute group definition "
7706 "'%s' must not contain more than one "
7707 "reference to the redefined definition",
7708 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7709 FREE_AND_NULL(str);
7710 return(NULL);
7711 }
7712 pctxt->redefCounter++;
7713 /*
7714 * URGENT TODO: How to ensure that the reference will not be
7715 * handled by the normal component resolution mechanism?
7716 */
7717 ret = xmlSchemaNewQNameRef(pctxt,
7718 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7719 if (ret == NULL)
7720 return(NULL);
7721 ret->node = node;
7722 pctxt->redef->reference = WXS_BASIC_CAST ret;
7723 } else {
7724 /*
7725 * Create a QName-reference helper component. We will substitute this
7726 * component for the attribute uses of the referenced attribute group
7727 * definition.
7728 */
7729 ret = xmlSchemaNewQNameRef(pctxt,
7730 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7731 if (ret == NULL)
7732 return(NULL);
7733 ret->node = node;
7734 /* Add to pending items, to be able to resolve the reference. */
7735 WXS_ADD_PENDING(pctxt, ret);
7736 }
7737 return (ret);
7738 }
7739
7740 /**
7741 * xmlSchemaParseAttributeGroupDefinition:
7742 * @pctxt: a schema validation context
7743 * @schema: the schema being built
7744 * @node: a subtree containing XML Schema information
7745 *
7746 * parse a XML schema Attribute Group declaration
7747 * *WARNING* this interface is highly subject to change
7748 *
7749 * Returns the attribute group definition or NULL in case of error.
7750 */
7751 static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7752 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7753 xmlSchemaPtr schema,
7754 xmlNodePtr node)
7755 {
7756 const xmlChar *name;
7757 xmlSchemaAttributeGroupPtr ret;
7758 xmlNodePtr child = NULL;
7759 xmlAttrPtr attr;
7760 int hasRefs = 0;
7761
7762 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7763 return (NULL);
7764
7765 attr = xmlSchemaGetPropNode(node, "name");
7766 if (attr == NULL) {
7767 xmlSchemaPMissingAttrErr(pctxt,
7768 XML_SCHEMAP_S4S_ATTR_MISSING,
7769 NULL, node, "name", NULL);
7770 return (NULL);
7771 }
7772 /*
7773 * The name is crucial, exit if invalid.
7774 */
7775 if (xmlSchemaPValAttrNode(pctxt,
7776 NULL, attr,
7777 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7778 return (NULL);
7779 }
7780 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7781 name, pctxt->targetNamespace, node);
7782 if (ret == NULL)
7783 return (NULL);
7784 /*
7785 * Check for illegal attributes.
7786 */
7787 attr = node->properties;
7788 while (attr != NULL) {
7789 if (attr->ns == NULL) {
7790 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7791 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7792 {
7793 xmlSchemaPIllegalAttrErr(pctxt,
7794 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7795 }
7796 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7797 xmlSchemaPIllegalAttrErr(pctxt,
7798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7799 }
7800 attr = attr->next;
7801 }
7802 /* Attribute ID */
7803 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7804 /*
7805 * And now for the children...
7806 */
7807 child = node->children;
7808 if (IS_SCHEMA(child, "annotation")) {
7809 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7810 child = child->next;
7811 }
7812 /*
7813 * Parse contained attribute decls/refs.
7814 */
7815 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7816 (xmlSchemaItemListPtr *) &(ret->attrUses),
7817 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7818 return(NULL);
7819 if (hasRefs)
7820 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7821 /*
7822 * Parse the attribute wildcard.
7823 */
7824 if (IS_SCHEMA(child, "anyAttribute")) {
7825 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7826 schema, child);
7827 child = child->next;
7828 }
7829 if (child != NULL) {
7830 xmlSchemaPContentErr(pctxt,
7831 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7832 NULL, node, child, NULL,
7833 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7834 }
7835 return (ret);
7836 }
7837
7838 /**
7839 * xmlSchemaPValAttrFormDefault:
7840 * @value: the value
7841 * @flags: the flags to be modified
7842 * @flagQualified: the specific flag for "qualified"
7843 *
7844 * Returns 0 if the value is valid, 1 otherwise.
7845 */
7846 static int
xmlSchemaPValAttrFormDefault(const xmlChar * value,int * flags,int flagQualified)7847 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7848 int *flags,
7849 int flagQualified)
7850 {
7851 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7852 if ((*flags & flagQualified) == 0)
7853 *flags |= flagQualified;
7854 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7855 return (1);
7856
7857 return (0);
7858 }
7859
7860 /**
7861 * xmlSchemaPValAttrBlockFinal:
7862 * @value: the value
7863 * @flags: the flags to be modified
7864 * @flagAll: the specific flag for "#all"
7865 * @flagExtension: the specific flag for "extension"
7866 * @flagRestriction: the specific flag for "restriction"
7867 * @flagSubstitution: the specific flag for "substitution"
7868 * @flagList: the specific flag for "list"
7869 * @flagUnion: the specific flag for "union"
7870 *
7871 * Validates the value of the attribute "final" and "block". The value
7872 * is converted into the specified flag values and returned in @flags.
7873 *
7874 * Returns 0 if the value is valid, 1 otherwise.
7875 */
7876
7877 static int
xmlSchemaPValAttrBlockFinal(const xmlChar * value,int * flags,int flagAll,int flagExtension,int flagRestriction,int flagSubstitution,int flagList,int flagUnion)7878 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7879 int *flags,
7880 int flagAll,
7881 int flagExtension,
7882 int flagRestriction,
7883 int flagSubstitution,
7884 int flagList,
7885 int flagUnion)
7886 {
7887 int ret = 0;
7888
7889 /*
7890 * TODO: This does not check for duplicate entries.
7891 */
7892 if ((flags == NULL) || (value == NULL))
7893 return (-1);
7894 if (value[0] == 0)
7895 return (0);
7896 if (xmlStrEqual(value, BAD_CAST "#all")) {
7897 if (flagAll != -1)
7898 *flags |= flagAll;
7899 else {
7900 if (flagExtension != -1)
7901 *flags |= flagExtension;
7902 if (flagRestriction != -1)
7903 *flags |= flagRestriction;
7904 if (flagSubstitution != -1)
7905 *flags |= flagSubstitution;
7906 if (flagList != -1)
7907 *flags |= flagList;
7908 if (flagUnion != -1)
7909 *flags |= flagUnion;
7910 }
7911 } else {
7912 const xmlChar *end, *cur = value;
7913 xmlChar *item;
7914
7915 do {
7916 while (IS_BLANK_CH(*cur))
7917 cur++;
7918 end = cur;
7919 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7920 end++;
7921 if (end == cur)
7922 break;
7923 item = xmlStrndup(cur, end - cur);
7924 if (xmlStrEqual(item, BAD_CAST "extension")) {
7925 if (flagExtension != -1) {
7926 if ((*flags & flagExtension) == 0)
7927 *flags |= flagExtension;
7928 } else
7929 ret = 1;
7930 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7931 if (flagRestriction != -1) {
7932 if ((*flags & flagRestriction) == 0)
7933 *flags |= flagRestriction;
7934 } else
7935 ret = 1;
7936 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7937 if (flagSubstitution != -1) {
7938 if ((*flags & flagSubstitution) == 0)
7939 *flags |= flagSubstitution;
7940 } else
7941 ret = 1;
7942 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7943 if (flagList != -1) {
7944 if ((*flags & flagList) == 0)
7945 *flags |= flagList;
7946 } else
7947 ret = 1;
7948 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7949 if (flagUnion != -1) {
7950 if ((*flags & flagUnion) == 0)
7951 *flags |= flagUnion;
7952 } else
7953 ret = 1;
7954 } else
7955 ret = 1;
7956 if (item != NULL)
7957 xmlFree(item);
7958 cur = end;
7959 } while ((ret == 0) && (*cur != 0));
7960 }
7961
7962 return (ret);
7963 }
7964
7965 static int
xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlSchemaIDCSelectPtr selector,xmlAttrPtr attr,int isField)7966 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7967 xmlSchemaIDCPtr idc,
7968 xmlSchemaIDCSelectPtr selector,
7969 xmlAttrPtr attr,
7970 int isField)
7971 {
7972 xmlNodePtr node;
7973
7974 /*
7975 * c-selector-xpath:
7976 * Schema Component Constraint: Selector Value OK
7977 *
7978 * TODO: 1 The {selector} must be a valid XPath expression, as defined
7979 * in [XPath].
7980 */
7981 if (selector == NULL) {
7982 xmlSchemaPErr(ctxt, idc->node,
7983 XML_SCHEMAP_INTERNAL,
7984 "Internal error: xmlSchemaCheckCSelectorXPath, "
7985 "the selector is not specified.\n", NULL, NULL);
7986 return (-1);
7987 }
7988 if (attr == NULL)
7989 node = idc->node;
7990 else
7991 node = (xmlNodePtr) attr;
7992 if (selector->xpath == NULL) {
7993 xmlSchemaPCustomErr(ctxt,
7994 /* TODO: Adjust error code. */
7995 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7996 NULL, node,
7997 "The XPath expression of the selector is not valid", NULL);
7998 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7999 } else {
8000 const xmlChar **nsArray = NULL;
8001 xmlNsPtr *nsList = NULL;
8002 /*
8003 * Compile the XPath expression.
8004 */
8005 /*
8006 * TODO: We need the array of in-scope namespaces for compilation.
8007 * TODO: Call xmlPatterncompile with different options for selector/
8008 * field.
8009 */
8010 if (attr == NULL)
8011 nsList = NULL;
8012 else
8013 nsList = xmlGetNsList(attr->doc, attr->parent);
8014 /*
8015 * Build an array of prefixes and namespaces.
8016 */
8017 if (nsList != NULL) {
8018 int i, count = 0;
8019
8020 for (i = 0; nsList[i] != NULL; i++)
8021 count++;
8022
8023 nsArray = (const xmlChar **) xmlMalloc(
8024 (count * 2 + 1) * sizeof(const xmlChar *));
8025 if (nsArray == NULL) {
8026 xmlSchemaPErrMemory(ctxt);
8027 xmlFree(nsList);
8028 return (-1);
8029 }
8030 for (i = 0; i < count; i++) {
8031 nsArray[2 * i] = nsList[i]->href;
8032 nsArray[2 * i + 1] = nsList[i]->prefix;
8033 }
8034 nsArray[count * 2] = NULL;
8035 xmlFree(nsList);
8036 }
8037 /*
8038 * TODO: Differentiate between "selector" and "field".
8039 */
8040 if (isField)
8041 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8042 NULL, XML_PATTERN_XSFIELD, nsArray);
8043 else
8044 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8045 NULL, XML_PATTERN_XSSEL, nsArray);
8046 if (nsArray != NULL)
8047 xmlFree((xmlChar **) nsArray);
8048
8049 if (selector->xpathComp == NULL) {
8050 xmlSchemaPCustomErr(ctxt,
8051 /* TODO: Adjust error code? */
8052 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8053 NULL, node,
8054 "The XPath expression '%s' could not be "
8055 "compiled", selector->xpath);
8056 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8057 }
8058 }
8059 return (0);
8060 }
8061
8062 #define ADD_ANNOTATION(annot) \
8063 xmlSchemaAnnotPtr cur = item->annot; \
8064 if (item->annot == NULL) { \
8065 item->annot = annot; \
8066 return (annot); \
8067 } \
8068 cur = item->annot; \
8069 while (cur->next != NULL) { \
8070 cur = cur->next; \
8071 } \
8072 cur->next = annot;
8073
8074 /**
8075 * xmlSchemaAssignAnnotation:
8076 * @item: the schema component
8077 * @annot: the annotation
8078 *
8079 * Adds the annotation to the given schema component.
8080 *
8081 * Returns the given annotation.
8082 */
8083 static xmlSchemaAnnotPtr
xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,xmlSchemaAnnotPtr annot)8084 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8085 xmlSchemaAnnotPtr annot)
8086 {
8087 if ((annItem == NULL) || (annot == NULL))
8088 return (NULL);
8089 switch (annItem->type) {
8090 case XML_SCHEMA_TYPE_ELEMENT: {
8091 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8092 ADD_ANNOTATION(annot)
8093 }
8094 break;
8095 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8096 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8097 ADD_ANNOTATION(annot)
8098 }
8099 break;
8100 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8101 case XML_SCHEMA_TYPE_ANY: {
8102 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8103 ADD_ANNOTATION(annot)
8104 }
8105 break;
8106 case XML_SCHEMA_TYPE_PARTICLE:
8107 case XML_SCHEMA_TYPE_IDC_KEY:
8108 case XML_SCHEMA_TYPE_IDC_KEYREF:
8109 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8110 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8111 ADD_ANNOTATION(annot)
8112 }
8113 break;
8114 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8115 xmlSchemaAttributeGroupPtr item =
8116 (xmlSchemaAttributeGroupPtr) annItem;
8117 ADD_ANNOTATION(annot)
8118 }
8119 break;
8120 case XML_SCHEMA_TYPE_NOTATION: {
8121 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8122 ADD_ANNOTATION(annot)
8123 }
8124 break;
8125 case XML_SCHEMA_FACET_MININCLUSIVE:
8126 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8127 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8128 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8129 case XML_SCHEMA_FACET_TOTALDIGITS:
8130 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8131 case XML_SCHEMA_FACET_PATTERN:
8132 case XML_SCHEMA_FACET_ENUMERATION:
8133 case XML_SCHEMA_FACET_WHITESPACE:
8134 case XML_SCHEMA_FACET_LENGTH:
8135 case XML_SCHEMA_FACET_MAXLENGTH:
8136 case XML_SCHEMA_FACET_MINLENGTH: {
8137 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8138 ADD_ANNOTATION(annot)
8139 }
8140 break;
8141 case XML_SCHEMA_TYPE_SIMPLE:
8142 case XML_SCHEMA_TYPE_COMPLEX: {
8143 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8144 ADD_ANNOTATION(annot)
8145 }
8146 break;
8147 case XML_SCHEMA_TYPE_GROUP: {
8148 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8149 ADD_ANNOTATION(annot)
8150 }
8151 break;
8152 case XML_SCHEMA_TYPE_SEQUENCE:
8153 case XML_SCHEMA_TYPE_CHOICE:
8154 case XML_SCHEMA_TYPE_ALL: {
8155 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8156 ADD_ANNOTATION(annot)
8157 }
8158 break;
8159 default:
8160 xmlSchemaPCustomErr(NULL,
8161 XML_SCHEMAP_INTERNAL,
8162 NULL, NULL,
8163 "Internal error: xmlSchemaAddAnnotation, "
8164 "The item is not a annotated schema component", NULL);
8165 break;
8166 }
8167 return (annot);
8168 }
8169
8170 /**
8171 * xmlSchemaParseIDCSelectorAndField:
8172 * @ctxt: a schema validation context
8173 * @schema: the schema being built
8174 * @node: a subtree containing XML Schema information
8175 *
8176 * Parses a XML Schema identity-constraint definition's
8177 * <selector> and <field> elements.
8178 *
8179 * Returns the parsed identity-constraint definition.
8180 */
8181 static xmlSchemaIDCSelectPtr
xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlNodePtr node,int isField)8182 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8183 xmlSchemaIDCPtr idc,
8184 xmlNodePtr node,
8185 int isField)
8186 {
8187 xmlSchemaIDCSelectPtr item;
8188 xmlNodePtr child = NULL;
8189 xmlAttrPtr attr;
8190
8191 /*
8192 * Check for illegal attributes.
8193 */
8194 attr = node->properties;
8195 while (attr != NULL) {
8196 if (attr->ns == NULL) {
8197 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8198 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8199 xmlSchemaPIllegalAttrErr(ctxt,
8200 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8201 }
8202 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8203 xmlSchemaPIllegalAttrErr(ctxt,
8204 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8205 }
8206 attr = attr->next;
8207 }
8208 /*
8209 * Create the item.
8210 */
8211 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8212 if (item == NULL) {
8213 xmlSchemaPErrMemory(ctxt);
8214 return (NULL);
8215 }
8216 memset(item, 0, sizeof(xmlSchemaIDCSelect));
8217 /*
8218 * Attribute "xpath" (mandatory).
8219 */
8220 attr = xmlSchemaGetPropNode(node, "xpath");
8221 if (attr == NULL) {
8222 xmlSchemaPMissingAttrErr(ctxt,
8223 XML_SCHEMAP_S4S_ATTR_MISSING,
8224 NULL, node,
8225 "name", NULL);
8226 } else {
8227 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8228 /*
8229 * URGENT TODO: "field"s have an other syntax than "selector"s.
8230 */
8231
8232 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8233 isField) == -1) {
8234 xmlSchemaPErr(ctxt,
8235 (xmlNodePtr) attr,
8236 XML_SCHEMAP_INTERNAL,
8237 "Internal error: xmlSchemaParseIDCSelectorAndField, "
8238 "validating the XPath expression of a IDC selector.\n",
8239 NULL, NULL);
8240 }
8241
8242 }
8243 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8244 /*
8245 * And now for the children...
8246 */
8247 child = node->children;
8248 if (IS_SCHEMA(child, "annotation")) {
8249 /*
8250 * Add the annotation to the parent IDC.
8251 */
8252 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8253 xmlSchemaParseAnnotation(ctxt, child, 1));
8254 child = child->next;
8255 }
8256 if (child != NULL) {
8257 xmlSchemaPContentErr(ctxt,
8258 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8259 NULL, node, child,
8260 NULL, "(annotation?)");
8261 }
8262
8263 return (item);
8264 }
8265
8266 /**
8267 * xmlSchemaParseIDC:
8268 * @ctxt: a schema validation context
8269 * @schema: the schema being built
8270 * @node: a subtree containing XML Schema information
8271 *
8272 * Parses a XML Schema identity-constraint definition.
8273 *
8274 * Returns the parsed identity-constraint definition.
8275 */
8276 static xmlSchemaIDCPtr
xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType idcCategory,const xmlChar * targetNamespace)8277 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8278 xmlSchemaPtr schema,
8279 xmlNodePtr node,
8280 xmlSchemaTypeType idcCategory,
8281 const xmlChar *targetNamespace)
8282 {
8283 xmlSchemaIDCPtr item = NULL;
8284 xmlNodePtr child = NULL;
8285 xmlAttrPtr attr;
8286 const xmlChar *name = NULL;
8287 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8288
8289 /*
8290 * Check for illegal attributes.
8291 */
8292 attr = node->properties;
8293 while (attr != NULL) {
8294 if (attr->ns == NULL) {
8295 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8296 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8297 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8298 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8299 xmlSchemaPIllegalAttrErr(ctxt,
8300 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8301 }
8302 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8303 xmlSchemaPIllegalAttrErr(ctxt,
8304 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8305 }
8306 attr = attr->next;
8307 }
8308 /*
8309 * Attribute "name" (mandatory).
8310 */
8311 attr = xmlSchemaGetPropNode(node, "name");
8312 if (attr == NULL) {
8313 xmlSchemaPMissingAttrErr(ctxt,
8314 XML_SCHEMAP_S4S_ATTR_MISSING,
8315 NULL, node,
8316 "name", NULL);
8317 return (NULL);
8318 } else if (xmlSchemaPValAttrNode(ctxt,
8319 NULL, attr,
8320 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8321 return (NULL);
8322 }
8323 /* Create the component. */
8324 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8325 idcCategory, node);
8326 if (item == NULL)
8327 return(NULL);
8328
8329 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8330 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8331 /*
8332 * Attribute "refer" (mandatory).
8333 */
8334 attr = xmlSchemaGetPropNode(node, "refer");
8335 if (attr == NULL) {
8336 xmlSchemaPMissingAttrErr(ctxt,
8337 XML_SCHEMAP_S4S_ATTR_MISSING,
8338 NULL, node,
8339 "refer", NULL);
8340 } else {
8341 /*
8342 * Create a reference item.
8343 */
8344 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8345 NULL, NULL);
8346 if (item->ref == NULL)
8347 return (NULL);
8348 xmlSchemaPValAttrNodeQName(ctxt, schema,
8349 NULL, attr,
8350 &(item->ref->targetNamespace),
8351 &(item->ref->name));
8352 xmlSchemaCheckReference(ctxt, schema, node, attr,
8353 item->ref->targetNamespace);
8354 }
8355 }
8356 /*
8357 * And now for the children...
8358 */
8359 child = node->children;
8360 if (IS_SCHEMA(child, "annotation")) {
8361 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8362 child = child->next;
8363 }
8364 if (child == NULL) {
8365 xmlSchemaPContentErr(ctxt,
8366 XML_SCHEMAP_S4S_ELEM_MISSING,
8367 NULL, node, child,
8368 "A child element is missing",
8369 "(annotation?, (selector, field+))");
8370 }
8371 /*
8372 * Child element <selector>.
8373 */
8374 if (IS_SCHEMA(child, "selector")) {
8375 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8376 item, child, 0);
8377 child = child->next;
8378 /*
8379 * Child elements <field>.
8380 */
8381 if (IS_SCHEMA(child, "field")) {
8382 do {
8383 field = xmlSchemaParseIDCSelectorAndField(ctxt,
8384 item, child, 1);
8385 if (field != NULL) {
8386 field->index = item->nbFields;
8387 item->nbFields++;
8388 if (lastField != NULL)
8389 lastField->next = field;
8390 else
8391 item->fields = field;
8392 lastField = field;
8393 }
8394 child = child->next;
8395 } while (IS_SCHEMA(child, "field"));
8396 } else {
8397 xmlSchemaPContentErr(ctxt,
8398 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8399 NULL, node, child,
8400 NULL, "(annotation?, (selector, field+))");
8401 }
8402 }
8403 if (child != NULL) {
8404 xmlSchemaPContentErr(ctxt,
8405 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8406 NULL, node, child,
8407 NULL, "(annotation?, (selector, field+))");
8408 }
8409
8410 return (item);
8411 }
8412
8413 /**
8414 * xmlSchemaParseElement:
8415 * @ctxt: a schema validation context
8416 * @schema: the schema being built
8417 * @node: a subtree containing XML Schema information
8418 * @topLevel: indicates if this is global declaration
8419 *
8420 * Parses a XML schema element declaration.
8421 * *WARNING* this interface is highly subject to change
8422 *
8423 * Returns the element declaration or a particle; NULL in case
8424 * of an error or if the particle has minOccurs==maxOccurs==0.
8425 */
8426 static xmlSchemaBasicItemPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * isElemRef,int topLevel)8427 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8428 xmlNodePtr node, int *isElemRef, int topLevel)
8429 {
8430 xmlSchemaElementPtr decl = NULL;
8431 xmlSchemaParticlePtr particle = NULL;
8432 xmlSchemaAnnotPtr annot = NULL;
8433 xmlNodePtr child = NULL;
8434 xmlAttrPtr attr, nameAttr;
8435 int min, max, isRef = 0;
8436 xmlChar *des = NULL;
8437
8438 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8439 /* TODO: Complete implementation of 3.3.6 */
8440
8441 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8442 return (NULL);
8443
8444 if (isElemRef != NULL)
8445 *isElemRef = 0;
8446 /*
8447 * If we get a "ref" attribute on a local <element> we will assume it's
8448 * a reference - even if there's a "name" attribute; this seems to be more
8449 * robust.
8450 */
8451 nameAttr = xmlSchemaGetPropNode(node, "name");
8452 attr = xmlSchemaGetPropNode(node, "ref");
8453 if ((topLevel) || (attr == NULL)) {
8454 if (nameAttr == NULL) {
8455 xmlSchemaPMissingAttrErr(ctxt,
8456 XML_SCHEMAP_S4S_ATTR_MISSING,
8457 NULL, node, "name", NULL);
8458 return (NULL);
8459 }
8460 } else
8461 isRef = 1;
8462
8463 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8464 child = node->children;
8465 if (IS_SCHEMA(child, "annotation")) {
8466 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8467 child = child->next;
8468 }
8469 /*
8470 * Skip particle part if a global declaration.
8471 */
8472 if (topLevel)
8473 goto declaration_part;
8474 /*
8475 * The particle part ==================================================
8476 */
8477 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8478 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8479 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8480 particle = xmlSchemaAddParticle(ctxt, node, min, max);
8481 if (particle == NULL)
8482 goto return_null;
8483
8484 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8485
8486 if (isRef) {
8487 const xmlChar *refNs = NULL, *ref = NULL;
8488 xmlSchemaQNameRefPtr refer = NULL;
8489 /*
8490 * The reference part =============================================
8491 */
8492 if (isElemRef != NULL)
8493 *isElemRef = 1;
8494
8495 xmlSchemaPValAttrNodeQName(ctxt, schema,
8496 NULL, attr, &refNs, &ref);
8497 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8498 /*
8499 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8500 */
8501 if (nameAttr != NULL) {
8502 xmlSchemaPMutualExclAttrErr(ctxt,
8503 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8504 }
8505 /*
8506 * Check for illegal attributes.
8507 */
8508 attr = node->properties;
8509 while (attr != NULL) {
8510 if (attr->ns == NULL) {
8511 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8512 xmlStrEqual(attr->name, BAD_CAST "name") ||
8513 xmlStrEqual(attr->name, BAD_CAST "id") ||
8514 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8515 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8516 {
8517 attr = attr->next;
8518 continue;
8519 } else {
8520 /* SPEC (3.3.3 : 2.2) */
8521 xmlSchemaPCustomAttrErr(ctxt,
8522 XML_SCHEMAP_SRC_ELEMENT_2_2,
8523 NULL, NULL, attr,
8524 "Only the attributes 'minOccurs', 'maxOccurs' and "
8525 "'id' are allowed in addition to 'ref'");
8526 break;
8527 }
8528 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8529 xmlSchemaPIllegalAttrErr(ctxt,
8530 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8531 }
8532 attr = attr->next;
8533 }
8534 /*
8535 * No children except <annotation> expected.
8536 */
8537 if (child != NULL) {
8538 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8539 NULL, node, child, NULL, "(annotation?)");
8540 }
8541 if ((min == 0) && (max == 0))
8542 goto return_null;
8543 /*
8544 * Create the reference item and attach it to the particle.
8545 */
8546 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8547 ref, refNs);
8548 if (refer == NULL)
8549 goto return_null;
8550 particle->children = (xmlSchemaTreeItemPtr) refer;
8551 particle->annot = annot;
8552 /*
8553 * Add the particle to pending components, since the reference
8554 * need to be resolved.
8555 */
8556 WXS_ADD_PENDING(ctxt, particle);
8557 return ((xmlSchemaBasicItemPtr) particle);
8558 }
8559 /*
8560 * The declaration part ===============================================
8561 */
8562 declaration_part:
8563 {
8564 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8565 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8566
8567 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8568 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8569 goto return_null;
8570 /*
8571 * Evaluate the target namespace.
8572 */
8573 if (topLevel) {
8574 ns = ctxt->targetNamespace;
8575 } else {
8576 attr = xmlSchemaGetPropNode(node, "form");
8577 if (attr != NULL) {
8578 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8579 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8580 ns = ctxt->targetNamespace;
8581 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8582 xmlSchemaPSimpleTypeErr(ctxt,
8583 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8584 NULL, (xmlNodePtr) attr,
8585 NULL, "(qualified | unqualified)",
8586 attrValue, NULL, NULL, NULL);
8587 }
8588 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8589 ns = ctxt->targetNamespace;
8590 }
8591 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8592 if (decl == NULL) {
8593 goto return_null;
8594 }
8595 /*
8596 * Check for illegal attributes.
8597 */
8598 attr = node->properties;
8599 while (attr != NULL) {
8600 if (attr->ns == NULL) {
8601 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8602 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8603 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8604 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8605 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8606 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8607 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8608 {
8609 if (topLevel == 0) {
8610 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8611 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8612 (!xmlStrEqual(attr->name, BAD_CAST "form")))
8613 {
8614 xmlSchemaPIllegalAttrErr(ctxt,
8615 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8616 }
8617 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8618 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8619 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8620
8621 xmlSchemaPIllegalAttrErr(ctxt,
8622 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8623 }
8624 }
8625 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8626
8627 xmlSchemaPIllegalAttrErr(ctxt,
8628 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8629 }
8630 attr = attr->next;
8631 }
8632 /*
8633 * Extract/validate attributes.
8634 */
8635 if (topLevel) {
8636 /*
8637 * Process top attributes of global element declarations here.
8638 */
8639 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8640 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8641 xmlSchemaPValAttrQName(ctxt, schema,
8642 NULL, node, "substitutionGroup",
8643 &(decl->substGroupNs), &(decl->substGroup));
8644 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8645 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8646 /*
8647 * Attribute "final".
8648 */
8649 attr = xmlSchemaGetPropNode(node, "final");
8650 if (attr == NULL) {
8651 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8652 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8653 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8654 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8655 } else {
8656 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8657 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8658 -1,
8659 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8660 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8661 xmlSchemaPSimpleTypeErr(ctxt,
8662 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8663 NULL, (xmlNodePtr) attr,
8664 NULL, "(#all | List of (extension | restriction))",
8665 attrValue, NULL, NULL, NULL);
8666 }
8667 }
8668 }
8669 /*
8670 * Attribute "block".
8671 */
8672 attr = xmlSchemaGetPropNode(node, "block");
8673 if (attr == NULL) {
8674 /*
8675 * Apply default "block" values.
8676 */
8677 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8678 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8679 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8680 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8681 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8682 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8683 } else {
8684 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8685 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8686 -1,
8687 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8688 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8689 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8690 xmlSchemaPSimpleTypeErr(ctxt,
8691 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8692 NULL, (xmlNodePtr) attr,
8693 NULL, "(#all | List of (extension | "
8694 "restriction | substitution))", attrValue,
8695 NULL, NULL, NULL);
8696 }
8697 }
8698 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8699 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8700
8701 attr = xmlSchemaGetPropNode(node, "type");
8702 if (attr != NULL) {
8703 xmlSchemaPValAttrNodeQName(ctxt, schema,
8704 NULL, attr,
8705 &(decl->namedTypeNs), &(decl->namedType));
8706 xmlSchemaCheckReference(ctxt, schema, node,
8707 attr, decl->namedTypeNs);
8708 }
8709 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8710 attr = xmlSchemaGetPropNode(node, "fixed");
8711 if (attr != NULL) {
8712 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8713 if (decl->value != NULL) {
8714 /*
8715 * 3.3.3 : 1
8716 * default and fixed must not both be present.
8717 */
8718 xmlSchemaPMutualExclAttrErr(ctxt,
8719 XML_SCHEMAP_SRC_ELEMENT_1,
8720 NULL, attr, "default", "fixed");
8721 } else {
8722 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8723 decl->value = fixed;
8724 }
8725 }
8726 /*
8727 * And now for the children...
8728 */
8729 if (IS_SCHEMA(child, "complexType")) {
8730 /*
8731 * 3.3.3 : 3
8732 * "type" and either <simpleType> or <complexType> are mutually
8733 * exclusive
8734 */
8735 if (decl->namedType != NULL) {
8736 xmlSchemaPContentErr(ctxt,
8737 XML_SCHEMAP_SRC_ELEMENT_3,
8738 NULL, node, child,
8739 "The attribute 'type' and the <complexType> child are "
8740 "mutually exclusive", NULL);
8741 } else
8742 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8743 child = child->next;
8744 } else if (IS_SCHEMA(child, "simpleType")) {
8745 /*
8746 * 3.3.3 : 3
8747 * "type" and either <simpleType> or <complexType> are
8748 * mutually exclusive
8749 */
8750 if (decl->namedType != NULL) {
8751 xmlSchemaPContentErr(ctxt,
8752 XML_SCHEMAP_SRC_ELEMENT_3,
8753 NULL, node, child,
8754 "The attribute 'type' and the <simpleType> child are "
8755 "mutually exclusive", NULL);
8756 } else
8757 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8758 child = child->next;
8759 }
8760 while ((IS_SCHEMA(child, "unique")) ||
8761 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8762 if (IS_SCHEMA(child, "unique")) {
8763 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8764 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8765 } else if (IS_SCHEMA(child, "key")) {
8766 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8767 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8768 } else if (IS_SCHEMA(child, "keyref")) {
8769 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8770 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8771 }
8772 if (lastIDC != NULL)
8773 lastIDC->next = curIDC;
8774 else
8775 decl->idcs = (void *) curIDC;
8776 lastIDC = curIDC;
8777 child = child->next;
8778 }
8779 if (child != NULL) {
8780 xmlSchemaPContentErr(ctxt,
8781 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8782 NULL, node, child,
8783 NULL, "(annotation?, ((simpleType | complexType)?, "
8784 "(unique | key | keyref)*))");
8785 }
8786 decl->annot = annot;
8787 }
8788 /*
8789 * NOTE: Element Declaration Representation OK 4. will be checked at a
8790 * different layer.
8791 */
8792 FREE_AND_NULL(des)
8793 if (topLevel)
8794 return ((xmlSchemaBasicItemPtr) decl);
8795 else {
8796 particle->children = (xmlSchemaTreeItemPtr) decl;
8797 return ((xmlSchemaBasicItemPtr) particle);
8798 }
8799
8800 return_null:
8801 FREE_AND_NULL(des);
8802 if (annot != NULL) {
8803 if (particle != NULL)
8804 particle->annot = NULL;
8805 if (decl != NULL)
8806 decl->annot = NULL;
8807 xmlSchemaFreeAnnot(annot);
8808 }
8809 return (NULL);
8810 }
8811
8812 /**
8813 * xmlSchemaParseUnion:
8814 * @ctxt: a schema validation context
8815 * @schema: the schema being built
8816 * @node: a subtree containing XML Schema information
8817 *
8818 * parse a XML schema Union definition
8819 * *WARNING* this interface is highly subject to change
8820 *
8821 * Returns -1 in case of internal error, 0 in case of success and a positive
8822 * error code otherwise.
8823 */
8824 static int
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)8825 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8826 xmlNodePtr node)
8827 {
8828 xmlSchemaTypePtr type;
8829 xmlNodePtr child = NULL;
8830 xmlAttrPtr attr;
8831 const xmlChar *cur = NULL;
8832
8833 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8834 return (-1);
8835 /* Not a component, don't create it. */
8836 type = ctxt->ctxtType;
8837 /*
8838 * Mark the simple type as being of variety "union".
8839 */
8840 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8841 /*
8842 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8843 * then the `simple ur-type definition`."
8844 */
8845 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8846 /*
8847 * Check for illegal attributes.
8848 */
8849 attr = node->properties;
8850 while (attr != NULL) {
8851 if (attr->ns == NULL) {
8852 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8853 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8854 xmlSchemaPIllegalAttrErr(ctxt,
8855 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8856 }
8857 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8858 xmlSchemaPIllegalAttrErr(ctxt,
8859 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8860 }
8861 attr = attr->next;
8862 }
8863 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8864 /*
8865 * Attribute "memberTypes". This is a list of QNames.
8866 * TODO: Check the value to contain anything.
8867 */
8868 attr = xmlSchemaGetPropNode(node, "memberTypes");
8869 if (attr != NULL) {
8870 const xmlChar *end;
8871 xmlChar *tmp;
8872 const xmlChar *localName, *nsName;
8873 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8874 xmlSchemaQNameRefPtr ref;
8875
8876 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8877 if (cur == NULL)
8878 return (-1);
8879 type->base = cur;
8880 do {
8881 while (IS_BLANK_CH(*cur))
8882 cur++;
8883 end = cur;
8884 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8885 end++;
8886 if (end == cur)
8887 break;
8888 tmp = xmlStrndup(cur, end - cur);
8889 if (tmp == NULL) {
8890 xmlSchemaPErrMemory(ctxt);
8891 return (-1);
8892 }
8893 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8894 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8895 /*
8896 * Create the member type link.
8897 */
8898 link = (xmlSchemaTypeLinkPtr)
8899 xmlMalloc(sizeof(xmlSchemaTypeLink));
8900 if (link == NULL) {
8901 xmlSchemaPErrMemory(ctxt);
8902 FREE_AND_NULL(tmp)
8903 return (-1);
8904 }
8905 link->type = NULL;
8906 link->next = NULL;
8907 if (lastLink == NULL)
8908 type->memberTypes = link;
8909 else
8910 lastLink->next = link;
8911 lastLink = link;
8912 /*
8913 * Create a reference item.
8914 */
8915 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8916 localName, nsName);
8917 if (ref == NULL) {
8918 FREE_AND_NULL(tmp)
8919 return (-1);
8920 }
8921 /*
8922 * Assign the reference to the link, it will be resolved
8923 * later during fixup of the union simple type.
8924 */
8925 link->type = (xmlSchemaTypePtr) ref;
8926 }
8927 FREE_AND_NULL(tmp)
8928 cur = end;
8929 } while (*cur != 0);
8930
8931 }
8932 /*
8933 * And now for the children...
8934 */
8935 child = node->children;
8936 if (IS_SCHEMA(child, "annotation")) {
8937 /*
8938 * Add the annotation to the simple type ancestor.
8939 */
8940 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8941 xmlSchemaParseAnnotation(ctxt, child, 1));
8942 child = child->next;
8943 }
8944 if (IS_SCHEMA(child, "simpleType")) {
8945 xmlSchemaTypePtr subtype, last = NULL;
8946
8947 /*
8948 * Anchor the member types in the "subtypes" field of the
8949 * simple type.
8950 */
8951 while (IS_SCHEMA(child, "simpleType")) {
8952 subtype = (xmlSchemaTypePtr)
8953 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8954 if (subtype != NULL) {
8955 if (last == NULL) {
8956 type->subtypes = subtype;
8957 last = subtype;
8958 } else {
8959 last->next = subtype;
8960 last = subtype;
8961 }
8962 last->next = NULL;
8963 }
8964 child = child->next;
8965 }
8966 }
8967 if (child != NULL) {
8968 xmlSchemaPContentErr(ctxt,
8969 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8970 NULL, node, child, NULL, "(annotation?, simpleType*)");
8971 }
8972 if ((attr == NULL) && (type->subtypes == NULL)) {
8973 /*
8974 * src-union-memberTypes-or-simpleTypes
8975 * Either the memberTypes [attribute] of the <union> element must
8976 * be non-empty or there must be at least one simpleType [child].
8977 */
8978 xmlSchemaPCustomErr(ctxt,
8979 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8980 NULL, node,
8981 "Either the attribute 'memberTypes' or "
8982 "at least one <simpleType> child must be present", NULL);
8983 }
8984 return (0);
8985 }
8986
8987 /**
8988 * xmlSchemaParseList:
8989 * @ctxt: a schema validation context
8990 * @schema: the schema being built
8991 * @node: a subtree containing XML Schema information
8992 *
8993 * parse a XML schema List definition
8994 * *WARNING* this interface is highly subject to change
8995 *
8996 * Returns -1 in case of error, 0 if the declaration is improper and
8997 * 1 in case of success.
8998 */
8999 static xmlSchemaTypePtr
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9000 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9001 xmlNodePtr node)
9002 {
9003 xmlSchemaTypePtr type;
9004 xmlNodePtr child = NULL;
9005 xmlAttrPtr attr;
9006
9007 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9008 return (NULL);
9009 /* Not a component, don't create it. */
9010 type = ctxt->ctxtType;
9011 /*
9012 * Mark the type as being of variety "list".
9013 */
9014 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9015 /*
9016 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9017 * then the `simple ur-type definition`."
9018 */
9019 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9020 /*
9021 * Check for illegal attributes.
9022 */
9023 attr = node->properties;
9024 while (attr != NULL) {
9025 if (attr->ns == NULL) {
9026 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9027 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9028 xmlSchemaPIllegalAttrErr(ctxt,
9029 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9030 }
9031 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9032 xmlSchemaPIllegalAttrErr(ctxt,
9033 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9034 }
9035 attr = attr->next;
9036 }
9037
9038 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9039
9040 /*
9041 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9042 * fields for holding the reference to the itemType.
9043 *
9044 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9045 * the "ref" fields.
9046 */
9047 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9048 node, "itemType", &(type->baseNs), &(type->base));
9049 /*
9050 * And now for the children...
9051 */
9052 child = node->children;
9053 if (IS_SCHEMA(child, "annotation")) {
9054 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9055 xmlSchemaParseAnnotation(ctxt, child, 1));
9056 child = child->next;
9057 }
9058 if (IS_SCHEMA(child, "simpleType")) {
9059 /*
9060 * src-list-itemType-or-simpleType
9061 * Either the itemType [attribute] or the <simpleType> [child] of
9062 * the <list> element must be present, but not both.
9063 */
9064 if (type->base != NULL) {
9065 xmlSchemaPCustomErr(ctxt,
9066 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9067 NULL, node,
9068 "The attribute 'itemType' and the <simpleType> child "
9069 "are mutually exclusive", NULL);
9070 } else {
9071 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9072 }
9073 child = child->next;
9074 } else if (type->base == NULL) {
9075 xmlSchemaPCustomErr(ctxt,
9076 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9077 NULL, node,
9078 "Either the attribute 'itemType' or the <simpleType> child "
9079 "must be present", NULL);
9080 }
9081 if (child != NULL) {
9082 xmlSchemaPContentErr(ctxt,
9083 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9084 NULL, node, child, NULL, "(annotation?, simpleType?)");
9085 }
9086 if ((type->base == NULL) &&
9087 (type->subtypes == NULL) &&
9088 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9089 xmlSchemaPCustomErr(ctxt,
9090 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9091 NULL, node,
9092 "Either the attribute 'itemType' or the <simpleType> child "
9093 "must be present", NULL);
9094 }
9095 return (NULL);
9096 }
9097
9098 /**
9099 * xmlSchemaParseSimpleType:
9100 * @ctxt: a schema validation context
9101 * @schema: the schema being built
9102 * @node: a subtree containing XML Schema information
9103 *
9104 * parse a XML schema Simple Type definition
9105 * *WARNING* this interface is highly subject to change
9106 *
9107 * Returns -1 in case of error, 0 if the declaration is improper and
9108 * 1 in case of success.
9109 */
9110 static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)9111 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9112 xmlNodePtr node, int topLevel)
9113 {
9114 xmlSchemaTypePtr type, oldCtxtType;
9115 xmlNodePtr child = NULL;
9116 const xmlChar *attrValue = NULL;
9117 xmlAttrPtr attr;
9118 int hasRestriction = 0;
9119
9120 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9121 return (NULL);
9122
9123 if (topLevel) {
9124 attr = xmlSchemaGetPropNode(node, "name");
9125 if (attr == NULL) {
9126 xmlSchemaPMissingAttrErr(ctxt,
9127 XML_SCHEMAP_S4S_ATTR_MISSING,
9128 NULL, node,
9129 "name", NULL);
9130 return (NULL);
9131 } else {
9132 if (xmlSchemaPValAttrNode(ctxt,
9133 NULL, attr,
9134 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9135 return (NULL);
9136 /*
9137 * Skip built-in types.
9138 */
9139 if (ctxt->isS4S) {
9140 xmlSchemaTypePtr biType;
9141
9142 if (ctxt->isRedefine) {
9143 /*
9144 * REDEFINE: Disallow redefinition of built-in-types.
9145 * TODO: It seems that the spec does not say anything
9146 * about this case.
9147 */
9148 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9149 NULL, node,
9150 "Redefinition of built-in simple types is not "
9151 "supported", NULL);
9152 return(NULL);
9153 }
9154 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9155 if (biType != NULL)
9156 return (biType);
9157 }
9158 }
9159 }
9160 /*
9161 * TargetNamespace:
9162 * SPEC "The `actual value` of the targetNamespace [attribute]
9163 * of the <schema> ancestor element information item if present,
9164 * otherwise `absent`.
9165 */
9166 if (topLevel == 0) {
9167 #ifdef ENABLE_NAMED_LOCALS
9168 char buf[40];
9169 #endif
9170 /*
9171 * Parse as local simple type definition.
9172 */
9173 #ifdef ENABLE_NAMED_LOCALS
9174 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9175 type = xmlSchemaAddType(ctxt, schema,
9176 XML_SCHEMA_TYPE_SIMPLE,
9177 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9178 ctxt->targetNamespace, node, 0);
9179 #else
9180 type = xmlSchemaAddType(ctxt, schema,
9181 XML_SCHEMA_TYPE_SIMPLE,
9182 NULL, ctxt->targetNamespace, node, 0);
9183 #endif
9184 if (type == NULL)
9185 return (NULL);
9186 type->type = XML_SCHEMA_TYPE_SIMPLE;
9187 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9188 /*
9189 * Check for illegal attributes.
9190 */
9191 attr = node->properties;
9192 while (attr != NULL) {
9193 if (attr->ns == NULL) {
9194 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9195 xmlSchemaPIllegalAttrErr(ctxt,
9196 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9197 }
9198 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9199 xmlSchemaPIllegalAttrErr(ctxt,
9200 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9201 }
9202 attr = attr->next;
9203 }
9204 } else {
9205 /*
9206 * Parse as global simple type definition.
9207 *
9208 * Note that attrValue is the value of the attribute "name" here.
9209 */
9210 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9211 attrValue, ctxt->targetNamespace, node, 1);
9212 if (type == NULL)
9213 return (NULL);
9214 type->type = XML_SCHEMA_TYPE_SIMPLE;
9215 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9216 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9217 /*
9218 * Check for illegal attributes.
9219 */
9220 attr = node->properties;
9221 while (attr != NULL) {
9222 if (attr->ns == NULL) {
9223 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9224 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9225 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9226 xmlSchemaPIllegalAttrErr(ctxt,
9227 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9228 }
9229 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9230 xmlSchemaPIllegalAttrErr(ctxt,
9231 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9232 }
9233 attr = attr->next;
9234 }
9235 /*
9236 * Attribute "final".
9237 */
9238 attr = xmlSchemaGetPropNode(node, "final");
9239 if (attr == NULL) {
9240 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9241 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9242 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9243 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9244 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9245 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9246 } else {
9247 attrValue = xmlSchemaGetProp(ctxt, node, "final");
9248 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9249 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9250 XML_SCHEMAS_TYPE_FINAL_LIST,
9251 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9252
9253 xmlSchemaPSimpleTypeErr(ctxt,
9254 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9255 WXS_BASIC_CAST type, (xmlNodePtr) attr,
9256 NULL, "(#all | List of (list | union | restriction)",
9257 attrValue, NULL, NULL, NULL);
9258 }
9259 }
9260 }
9261 type->targetNamespace = ctxt->targetNamespace;
9262 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9263 /*
9264 * And now for the children...
9265 */
9266 oldCtxtType = ctxt->ctxtType;
9267
9268 ctxt->ctxtType = type;
9269
9270 child = node->children;
9271 if (IS_SCHEMA(child, "annotation")) {
9272 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9273 child = child->next;
9274 }
9275 if (child == NULL) {
9276 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9277 NULL, node, child, NULL,
9278 "(annotation?, (restriction | list | union))");
9279 } else if (IS_SCHEMA(child, "restriction")) {
9280 xmlSchemaParseRestriction(ctxt, schema, child,
9281 XML_SCHEMA_TYPE_SIMPLE);
9282 hasRestriction = 1;
9283 child = child->next;
9284 } else if (IS_SCHEMA(child, "list")) {
9285 xmlSchemaParseList(ctxt, schema, child);
9286 child = child->next;
9287 } else if (IS_SCHEMA(child, "union")) {
9288 xmlSchemaParseUnion(ctxt, schema, child);
9289 child = child->next;
9290 }
9291 if (child != NULL) {
9292 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9293 NULL, node, child, NULL,
9294 "(annotation?, (restriction | list | union))");
9295 }
9296 /*
9297 * REDEFINE: SPEC src-redefine (5)
9298 * "Within the [children], each <simpleType> must have a
9299 * <restriction> among its [children] ... the `actual value` of whose
9300 * base [attribute] must be the same as the `actual value` of its own
9301 * name attribute plus target namespace;"
9302 */
9303 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9304 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9305 NULL, node, "This is a redefinition, thus the "
9306 "<simpleType> must have a <restriction> child", NULL);
9307 }
9308
9309 ctxt->ctxtType = oldCtxtType;
9310 return (type);
9311 }
9312
9313 /**
9314 * xmlSchemaParseModelGroupDefRef:
9315 * @ctxt: the parser context
9316 * @schema: the schema being built
9317 * @node: the node
9318 *
9319 * Parses a reference to a model group definition.
9320 *
9321 * We will return a particle component with a qname-component or
9322 * NULL in case of an error.
9323 */
9324 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9325 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9326 xmlSchemaPtr schema,
9327 xmlNodePtr node)
9328 {
9329 xmlSchemaParticlePtr item;
9330 xmlNodePtr child = NULL;
9331 xmlAttrPtr attr;
9332 const xmlChar *ref = NULL, *refNs = NULL;
9333 int min, max;
9334
9335 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9336 return (NULL);
9337
9338 attr = xmlSchemaGetPropNode(node, "ref");
9339 if (attr == NULL) {
9340 xmlSchemaPMissingAttrErr(ctxt,
9341 XML_SCHEMAP_S4S_ATTR_MISSING,
9342 NULL, node, "ref", NULL);
9343 return (NULL);
9344 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9345 attr, &refNs, &ref) != 0) {
9346 return (NULL);
9347 }
9348 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9349 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9350 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9351 "(xs:nonNegativeInteger | unbounded)");
9352 /*
9353 * Check for illegal attributes.
9354 */
9355 attr = node->properties;
9356 while (attr != NULL) {
9357 if (attr->ns == NULL) {
9358 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9359 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9360 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9361 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9362 xmlSchemaPIllegalAttrErr(ctxt,
9363 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9364 }
9365 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9366 xmlSchemaPIllegalAttrErr(ctxt,
9367 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9368 }
9369 attr = attr->next;
9370 }
9371 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9372 item = xmlSchemaAddParticle(ctxt, node, min, max);
9373 if (item == NULL)
9374 return (NULL);
9375 /*
9376 * Create a qname-reference and set as the term; it will be substituted
9377 * for the model group after the reference has been resolved.
9378 */
9379 item->children = (xmlSchemaTreeItemPtr)
9380 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9381 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9382 /*
9383 * And now for the children...
9384 */
9385 child = node->children;
9386 /* TODO: Is annotation even allowed for a model group reference? */
9387 if (IS_SCHEMA(child, "annotation")) {
9388 /*
9389 * TODO: What to do exactly with the annotation?
9390 */
9391 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9392 child = child->next;
9393 }
9394 if (child != NULL) {
9395 xmlSchemaPContentErr(ctxt,
9396 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9397 NULL, node, child, NULL,
9398 "(annotation?)");
9399 }
9400 /*
9401 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9402 */
9403 if ((min == 0) && (max == 0))
9404 return (NULL);
9405
9406 return ((xmlSchemaTreeItemPtr) item);
9407 }
9408
9409 /**
9410 * xmlSchemaParseModelGroupDefinition:
9411 * @ctxt: a schema validation context
9412 * @schema: the schema being built
9413 * @node: a subtree containing XML Schema information
9414 *
9415 * Parses a XML schema model group definition.
9416 *
9417 * Note that the constraint src-redefine (6.2) can't be applied until
9418 * references have been resolved. So we will do this at the
9419 * component fixup level.
9420 *
9421 * *WARNING* this interface is highly subject to change
9422 *
9423 * Returns -1 in case of error, 0 if the declaration is improper and
9424 * 1 in case of success.
9425 */
9426 static xmlSchemaModelGroupDefPtr
xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9427 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9428 xmlSchemaPtr schema,
9429 xmlNodePtr node)
9430 {
9431 xmlSchemaModelGroupDefPtr item;
9432 xmlNodePtr child = NULL;
9433 xmlAttrPtr attr;
9434 const xmlChar *name;
9435
9436 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9437 return (NULL);
9438
9439 attr = xmlSchemaGetPropNode(node, "name");
9440 if (attr == NULL) {
9441 xmlSchemaPMissingAttrErr(ctxt,
9442 XML_SCHEMAP_S4S_ATTR_MISSING,
9443 NULL, node,
9444 "name", NULL);
9445 return (NULL);
9446 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9447 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9448 return (NULL);
9449 }
9450 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9451 ctxt->targetNamespace, node);
9452 if (item == NULL)
9453 return (NULL);
9454 /*
9455 * Check for illegal attributes.
9456 */
9457 attr = node->properties;
9458 while (attr != NULL) {
9459 if (attr->ns == NULL) {
9460 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9461 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9462 xmlSchemaPIllegalAttrErr(ctxt,
9463 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9464 }
9465 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9466 xmlSchemaPIllegalAttrErr(ctxt,
9467 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9468 }
9469 attr = attr->next;
9470 }
9471 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9472 /*
9473 * And now for the children...
9474 */
9475 child = node->children;
9476 if (IS_SCHEMA(child, "annotation")) {
9477 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9478 child = child->next;
9479 }
9480 if (IS_SCHEMA(child, "all")) {
9481 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9482 XML_SCHEMA_TYPE_ALL, 0);
9483 child = child->next;
9484 } else if (IS_SCHEMA(child, "choice")) {
9485 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9486 XML_SCHEMA_TYPE_CHOICE, 0);
9487 child = child->next;
9488 } else if (IS_SCHEMA(child, "sequence")) {
9489 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9490 XML_SCHEMA_TYPE_SEQUENCE, 0);
9491 child = child->next;
9492 }
9493
9494
9495
9496 if (child != NULL) {
9497 xmlSchemaPContentErr(ctxt,
9498 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9499 NULL, node, child, NULL,
9500 "(annotation?, (all | choice | sequence)?)");
9501 }
9502 return (item);
9503 }
9504
9505 /**
9506 * xmlSchemaCleanupDoc:
9507 * @ctxt: a schema validation context
9508 * @node: the root of the document.
9509 *
9510 * removes unwanted nodes in a schemas document tree
9511 */
9512 static void
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr root)9513 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9514 {
9515 xmlNodePtr delete, cur;
9516
9517 if ((ctxt == NULL) || (root == NULL)) return;
9518
9519 /*
9520 * Remove all the blank text nodes
9521 */
9522 delete = NULL;
9523 cur = root;
9524 while (cur != NULL) {
9525 if (delete != NULL) {
9526 xmlUnlinkNode(delete);
9527 xmlFreeNode(delete);
9528 delete = NULL;
9529 }
9530 if (cur->type == XML_TEXT_NODE) {
9531 if (IS_BLANK_NODE(cur)) {
9532 if (xmlNodeGetSpacePreserve(cur) != 1) {
9533 delete = cur;
9534 }
9535 }
9536 } else if ((cur->type != XML_ELEMENT_NODE) &&
9537 (cur->type != XML_CDATA_SECTION_NODE)) {
9538 delete = cur;
9539 goto skip_children;
9540 }
9541
9542 /*
9543 * Skip to next node
9544 */
9545 if (cur->children != NULL) {
9546 if ((cur->children->type != XML_ENTITY_DECL) &&
9547 (cur->children->type != XML_ENTITY_REF_NODE) &&
9548 (cur->children->type != XML_ENTITY_NODE)) {
9549 cur = cur->children;
9550 continue;
9551 }
9552 }
9553 skip_children:
9554 if (cur->next != NULL) {
9555 cur = cur->next;
9556 continue;
9557 }
9558
9559 do {
9560 cur = cur->parent;
9561 if (cur == NULL)
9562 break;
9563 if (cur == root) {
9564 cur = NULL;
9565 break;
9566 }
9567 if (cur->next != NULL) {
9568 cur = cur->next;
9569 break;
9570 }
9571 } while (cur != NULL);
9572 }
9573 if (delete != NULL) {
9574 xmlUnlinkNode(delete);
9575 xmlFreeNode(delete);
9576 delete = NULL;
9577 }
9578 }
9579
9580
9581 static void
xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)9582 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9583 {
9584 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9585 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9586
9587 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9588 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9589
9590 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9591 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9592 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9593 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9594 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9595 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9596 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9597 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9598
9599 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9600 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9601 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9602 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9603 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9604 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9605 }
9606
9607 static int
xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9608 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9609 xmlSchemaPtr schema,
9610 xmlNodePtr node)
9611 {
9612 xmlAttrPtr attr;
9613 const xmlChar *val;
9614 int res = 0, oldErrs = ctxt->nberrors;
9615
9616 /*
9617 * Those flags should be moved to the parser context flags,
9618 * since they are not visible at the component level. I.e.
9619 * they are used if processing schema *documents* only.
9620 */
9621 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9622 HFAILURE;
9623
9624 /*
9625 * Since the version is of type xs:token, we won't bother to
9626 * check it.
9627 */
9628 /* REMOVED:
9629 attr = xmlSchemaGetPropNode(node, "version");
9630 if (attr != NULL) {
9631 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9632 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9633 HFAILURE;
9634 }
9635 */
9636 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9637 if (attr != NULL) {
9638 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9639 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9640 HFAILURE;
9641 if (res != 0) {
9642 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9643 goto exit;
9644 }
9645 }
9646 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9647 if (attr != NULL) {
9648 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9649 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9650 XML_SCHEMAS_QUALIF_ELEM);
9651 HFAILURE;
9652 if (res != 0) {
9653 xmlSchemaPSimpleTypeErr(ctxt,
9654 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9655 NULL, (xmlNodePtr) attr, NULL,
9656 "(qualified | unqualified)", val, NULL, NULL, NULL);
9657 }
9658 }
9659 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9660 if (attr != NULL) {
9661 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9662 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9663 XML_SCHEMAS_QUALIF_ATTR);
9664 HFAILURE;
9665 if (res != 0) {
9666 xmlSchemaPSimpleTypeErr(ctxt,
9667 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9668 NULL, (xmlNodePtr) attr, NULL,
9669 "(qualified | unqualified)", val, NULL, NULL, NULL);
9670 }
9671 }
9672 attr = xmlSchemaGetPropNode(node, "finalDefault");
9673 if (attr != NULL) {
9674 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9675 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9676 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9677 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9678 -1,
9679 XML_SCHEMAS_FINAL_DEFAULT_LIST,
9680 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9681 HFAILURE;
9682 if (res != 0) {
9683 xmlSchemaPSimpleTypeErr(ctxt,
9684 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9685 NULL, (xmlNodePtr) attr, NULL,
9686 "(#all | List of (extension | restriction | list | union))",
9687 val, NULL, NULL, NULL);
9688 }
9689 }
9690 attr = xmlSchemaGetPropNode(node, "blockDefault");
9691 if (attr != NULL) {
9692 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9693 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9694 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9695 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9696 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9697 HFAILURE;
9698 if (res != 0) {
9699 xmlSchemaPSimpleTypeErr(ctxt,
9700 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9701 NULL, (xmlNodePtr) attr, NULL,
9702 "(#all | List of (extension | restriction | substitution))",
9703 val, NULL, NULL, NULL);
9704 }
9705 }
9706
9707 exit:
9708 if (oldErrs != ctxt->nberrors)
9709 res = ctxt->err;
9710 return(res);
9711 exit_failure:
9712 return(-1);
9713 }
9714
9715 /**
9716 * xmlSchemaParseSchemaTopLevel:
9717 * @ctxt: a schema validation context
9718 * @schema: the schemas
9719 * @nodes: the list of top level nodes
9720 *
9721 * Returns the internal XML Schema structure built from the resource or
9722 * NULL in case of error
9723 */
9724 static int
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr nodes)9725 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9726 xmlSchemaPtr schema, xmlNodePtr nodes)
9727 {
9728 xmlNodePtr child;
9729 xmlSchemaAnnotPtr annot;
9730 int res = 0, oldErrs, tmpOldErrs;
9731
9732 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9733 return(-1);
9734
9735 oldErrs = ctxt->nberrors;
9736 child = nodes;
9737 while ((IS_SCHEMA(child, "include")) ||
9738 (IS_SCHEMA(child, "import")) ||
9739 (IS_SCHEMA(child, "redefine")) ||
9740 (IS_SCHEMA(child, "annotation"))) {
9741 if (IS_SCHEMA(child, "annotation")) {
9742 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9743 if (schema->annot == NULL)
9744 schema->annot = annot;
9745 else
9746 xmlSchemaFreeAnnot(annot);
9747 } else if (IS_SCHEMA(child, "import")) {
9748 tmpOldErrs = ctxt->nberrors;
9749 res = xmlSchemaParseImport(ctxt, schema, child);
9750 HFAILURE;
9751 HSTOP(ctxt);
9752 if (tmpOldErrs != ctxt->nberrors)
9753 goto exit;
9754 } else if (IS_SCHEMA(child, "include")) {
9755 tmpOldErrs = ctxt->nberrors;
9756 res = xmlSchemaParseInclude(ctxt, schema, child);
9757 HFAILURE;
9758 HSTOP(ctxt);
9759 if (tmpOldErrs != ctxt->nberrors)
9760 goto exit;
9761 } else if (IS_SCHEMA(child, "redefine")) {
9762 tmpOldErrs = ctxt->nberrors;
9763 res = xmlSchemaParseRedefine(ctxt, schema, child);
9764 HFAILURE;
9765 HSTOP(ctxt);
9766 if (tmpOldErrs != ctxt->nberrors)
9767 goto exit;
9768 }
9769 child = child->next;
9770 }
9771 /*
9772 * URGENT TODO: Change the functions to return int results.
9773 * We need especially to catch internal errors.
9774 */
9775 while (child != NULL) {
9776 if (IS_SCHEMA(child, "complexType")) {
9777 xmlSchemaParseComplexType(ctxt, schema, child, 1);
9778 child = child->next;
9779 } else if (IS_SCHEMA(child, "simpleType")) {
9780 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9781 child = child->next;
9782 } else if (IS_SCHEMA(child, "element")) {
9783 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9784 child = child->next;
9785 } else if (IS_SCHEMA(child, "attribute")) {
9786 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9787 child = child->next;
9788 } else if (IS_SCHEMA(child, "attributeGroup")) {
9789 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9790 child = child->next;
9791 } else if (IS_SCHEMA(child, "group")) {
9792 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9793 child = child->next;
9794 } else if (IS_SCHEMA(child, "notation")) {
9795 xmlSchemaParseNotation(ctxt, schema, child);
9796 child = child->next;
9797 } else {
9798 xmlSchemaPContentErr(ctxt,
9799 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9800 NULL, child->parent, child,
9801 NULL, "((include | import | redefine | annotation)*, "
9802 "(((simpleType | complexType | group | attributeGroup) "
9803 "| element | attribute | notation), annotation*)*)");
9804 child = child->next;
9805 }
9806 while (IS_SCHEMA(child, "annotation")) {
9807 /*
9808 * TODO: We should add all annotations.
9809 */
9810 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9811 if (schema->annot == NULL)
9812 schema->annot = annot;
9813 else
9814 xmlSchemaFreeAnnot(annot);
9815 child = child->next;
9816 }
9817 }
9818 exit:
9819 ctxt->ctxtType = NULL;
9820 if (oldErrs != ctxt->nberrors)
9821 res = ctxt->err;
9822 return(res);
9823 exit_failure:
9824 return(-1);
9825 }
9826
9827 static xmlSchemaSchemaRelationPtr
xmlSchemaSchemaRelationCreate(void)9828 xmlSchemaSchemaRelationCreate(void)
9829 {
9830 xmlSchemaSchemaRelationPtr ret;
9831
9832 ret = (xmlSchemaSchemaRelationPtr)
9833 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9834 if (ret == NULL) {
9835 xmlSchemaPErrMemory(NULL);
9836 return(NULL);
9837 }
9838 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9839 return(ret);
9840 }
9841
9842 #if 0
9843 static void
9844 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9845 {
9846 xmlFree(rel);
9847 }
9848 #endif
9849
9850 static void
xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)9851 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9852 {
9853 xmlSchemaRedefPtr prev;
9854
9855 while (redef != NULL) {
9856 prev = redef;
9857 redef = redef->next;
9858 xmlFree(prev);
9859 }
9860 }
9861
9862 static void
xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)9863 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9864 {
9865 /*
9866 * After the construction context has been freed, there will be
9867 * no schema graph available any more. Only the schema buckets
9868 * will stay alive, which are put into the "schemasImports" and
9869 * "includes" slots of the xmlSchema.
9870 */
9871 if (con->buckets != NULL)
9872 xmlSchemaItemListFree(con->buckets);
9873 if (con->pending != NULL)
9874 xmlSchemaItemListFree(con->pending);
9875 if (con->substGroups != NULL)
9876 xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
9877 if (con->redefs != NULL)
9878 xmlSchemaRedefListFree(con->redefs);
9879 if (con->dict != NULL)
9880 xmlDictFree(con->dict);
9881 xmlFree(con);
9882 }
9883
9884 static xmlSchemaConstructionCtxtPtr
xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)9885 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9886 {
9887 xmlSchemaConstructionCtxtPtr ret;
9888
9889 ret = (xmlSchemaConstructionCtxtPtr)
9890 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9891 if (ret == NULL) {
9892 xmlSchemaPErrMemory(NULL);
9893 return (NULL);
9894 }
9895 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9896
9897 ret->buckets = xmlSchemaItemListCreate();
9898 if (ret->buckets == NULL) {
9899 xmlSchemaPErrMemory(NULL);
9900 xmlFree(ret);
9901 return (NULL);
9902 }
9903 ret->pending = xmlSchemaItemListCreate();
9904 if (ret->pending == NULL) {
9905 xmlSchemaPErrMemory(NULL);
9906 xmlSchemaConstructionCtxtFree(ret);
9907 return (NULL);
9908 }
9909 ret->dict = dict;
9910 xmlDictReference(dict);
9911 return(ret);
9912 }
9913
9914 static xmlSchemaParserCtxtPtr
xmlSchemaParserCtxtCreate(void)9915 xmlSchemaParserCtxtCreate(void)
9916 {
9917 xmlSchemaParserCtxtPtr ret;
9918
9919 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9920 if (ret == NULL) {
9921 xmlSchemaPErrMemory(NULL);
9922 return (NULL);
9923 }
9924 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9925 ret->type = XML_SCHEMA_CTXT_PARSER;
9926 ret->attrProhibs = xmlSchemaItemListCreate();
9927 if (ret->attrProhibs == NULL) {
9928 xmlFree(ret);
9929 return(NULL);
9930 }
9931 return(ret);
9932 }
9933
9934 /**
9935 * xmlSchemaNewParserCtxtUseDict:
9936 * @URL: the location of the schema
9937 * @dict: the dictionary to be used
9938 *
9939 * Create an XML Schemas parse context for that file/resource expected
9940 * to contain an XML Schemas file.
9941 *
9942 * Returns the parser context or NULL in case of error
9943 */
9944 static xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxtUseDict(const char * URL,xmlDictPtr dict)9945 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9946 {
9947 xmlSchemaParserCtxtPtr ret;
9948
9949 ret = xmlSchemaParserCtxtCreate();
9950 if (ret == NULL)
9951 return (NULL);
9952 ret->dict = dict;
9953 xmlDictReference(dict);
9954 if (URL != NULL)
9955 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9956 return (ret);
9957 }
9958
9959 static int
xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)9960 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9961 {
9962 if (vctxt->pctxt == NULL) {
9963 if (vctxt->schema != NULL)
9964 vctxt->pctxt =
9965 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9966 else
9967 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9968 if (vctxt->pctxt == NULL) {
9969 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9970 "failed to create a temp. parser context");
9971 return (-1);
9972 }
9973 /* TODO: Pass user data. */
9974 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9975 vctxt->warning, vctxt->errCtxt);
9976 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9977 vctxt->errCtxt);
9978 }
9979 return (0);
9980 }
9981
9982 /**
9983 * xmlSchemaGetSchemaBucket:
9984 * @pctxt: the schema parser context
9985 * @schemaLocation: the URI of the schema document
9986 *
9987 * Returns a schema bucket if it was already parsed.
9988 *
9989 * Returns a schema bucket if it was already parsed from
9990 * @schemaLocation, NULL otherwise.
9991 */
9992 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation)9993 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9994 const xmlChar *schemaLocation)
9995 {
9996 xmlSchemaBucketPtr cur;
9997 xmlSchemaItemListPtr list;
9998
9999 list = pctxt->constructor->buckets;
10000 if (list->nbItems == 0)
10001 return(NULL);
10002 else {
10003 int i;
10004 for (i = 0; i < list->nbItems; i++) {
10005 cur = (xmlSchemaBucketPtr) list->items[i];
10006 /* Pointer comparison! */
10007 if (cur->schemaLocation == schemaLocation)
10008 return(cur);
10009 }
10010 }
10011 return(NULL);
10012 }
10013
10014 static xmlSchemaBucketPtr
xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation,const xmlChar * targetNamespace)10015 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10016 const xmlChar *schemaLocation,
10017 const xmlChar *targetNamespace)
10018 {
10019 xmlSchemaBucketPtr cur;
10020 xmlSchemaItemListPtr list;
10021
10022 list = pctxt->constructor->buckets;
10023 if (list->nbItems == 0)
10024 return(NULL);
10025 else {
10026 int i;
10027 for (i = 0; i < list->nbItems; i++) {
10028 cur = (xmlSchemaBucketPtr) list->items[i];
10029 /* Pointer comparison! */
10030 if ((cur->origTargetNamespace == NULL) &&
10031 (cur->schemaLocation == schemaLocation) &&
10032 (cur->targetNamespace == targetNamespace))
10033 return(cur);
10034 }
10035 }
10036 return(NULL);
10037 }
10038
10039
10040 #define IS_BAD_SCHEMA_DOC(b) \
10041 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10042
10043 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,const xmlChar * targetNamespace,int imported)10044 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10045 const xmlChar *targetNamespace,
10046 int imported)
10047 {
10048 xmlSchemaBucketPtr cur;
10049 xmlSchemaItemListPtr list;
10050
10051 list = pctxt->constructor->buckets;
10052 if (list->nbItems == 0)
10053 return(NULL);
10054 else {
10055 int i;
10056 for (i = 0; i < list->nbItems; i++) {
10057 cur = (xmlSchemaBucketPtr) list->items[i];
10058 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10059 (cur->origTargetNamespace == targetNamespace) &&
10060 ((imported && cur->imported) ||
10061 ((!imported) && (!cur->imported))))
10062 return(cur);
10063 }
10064 }
10065 return(NULL);
10066 }
10067
10068 static int
xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10069 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10070 xmlSchemaPtr schema,
10071 xmlSchemaBucketPtr bucket)
10072 {
10073 int oldFlags;
10074 xmlDocPtr oldDoc;
10075 xmlNodePtr node;
10076 int ret, oldErrs;
10077 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10078
10079 /*
10080 * Save old values; reset the *main* schema.
10081 * URGENT TODO: This is not good; move the per-document information
10082 * to the parser. Get rid of passing the main schema to the
10083 * parsing functions.
10084 */
10085 oldFlags = schema->flags;
10086 oldDoc = schema->doc;
10087 if (schema->flags != 0)
10088 xmlSchemaClearSchemaDefaults(schema);
10089 schema->doc = bucket->doc;
10090 pctxt->schema = schema;
10091 /*
10092 * Keep the current target namespace on the parser *not* on the
10093 * main schema.
10094 */
10095 pctxt->targetNamespace = bucket->targetNamespace;
10096 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10097
10098 if ((bucket->targetNamespace != NULL) &&
10099 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10100 /*
10101 * We are parsing the schema for schemas!
10102 */
10103 pctxt->isS4S = 1;
10104 }
10105 /* Mark it as parsed, even if parsing fails. */
10106 bucket->parsed++;
10107 /* Compile the schema doc. */
10108 node = xmlDocGetRootElement(bucket->doc);
10109 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10110 if (ret != 0)
10111 goto exit;
10112 /* An empty schema; just get out. */
10113 if (node->children == NULL)
10114 goto exit;
10115 oldErrs = pctxt->nberrors;
10116 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10117 if (ret != 0)
10118 goto exit;
10119 /*
10120 * TODO: Not nice, but I'm not 100% sure we will get always an error
10121 * as a result of the above functions; so better rely on pctxt->err
10122 * as well.
10123 */
10124 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10125 ret = pctxt->err;
10126 goto exit;
10127 }
10128
10129 exit:
10130 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10131 /* Restore schema values. */
10132 schema->doc = oldDoc;
10133 schema->flags = oldFlags;
10134 return(ret);
10135 }
10136
10137 static int
xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10138 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10139 xmlSchemaPtr schema,
10140 xmlSchemaBucketPtr bucket)
10141 {
10142 xmlSchemaParserCtxtPtr newpctxt;
10143 int res = 0;
10144
10145 if (bucket == NULL)
10146 return(0);
10147 if (bucket->parsed) {
10148 PERROR_INT("xmlSchemaParseNewDoc",
10149 "reparsing a schema doc");
10150 return(-1);
10151 }
10152 if (bucket->doc == NULL) {
10153 PERROR_INT("xmlSchemaParseNewDoc",
10154 "parsing a schema doc, but there's no doc");
10155 return(-1);
10156 }
10157 if (pctxt->constructor == NULL) {
10158 PERROR_INT("xmlSchemaParseNewDoc",
10159 "no constructor");
10160 return(-1);
10161 }
10162 /* Create and init the temporary parser context. */
10163 newpctxt = xmlSchemaNewParserCtxtUseDict(
10164 (const char *) bucket->schemaLocation, pctxt->dict);
10165 if (newpctxt == NULL)
10166 return(-1);
10167 newpctxt->constructor = pctxt->constructor;
10168 /*
10169 * TODO: Can we avoid that the parser knows about the main schema?
10170 * It would be better if he knows about the current schema bucket
10171 * only.
10172 */
10173 newpctxt->schema = schema;
10174 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10175 pctxt->errCtxt);
10176 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10177 pctxt->errCtxt);
10178 newpctxt->counter = pctxt->counter;
10179
10180
10181 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10182
10183 /* Channel back errors and cleanup the temporary parser context. */
10184 if (res != 0)
10185 pctxt->err = res;
10186 pctxt->nberrors += newpctxt->nberrors;
10187 pctxt->counter = newpctxt->counter;
10188 newpctxt->constructor = NULL;
10189 /* Free the parser context. */
10190 xmlSchemaFreeParserCtxt(newpctxt);
10191 return(res);
10192 }
10193
10194 static void
xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,xmlSchemaSchemaRelationPtr rel)10195 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10196 xmlSchemaSchemaRelationPtr rel)
10197 {
10198 xmlSchemaSchemaRelationPtr cur = bucket->relations;
10199
10200 if (cur == NULL) {
10201 bucket->relations = rel;
10202 return;
10203 }
10204 while (cur->next != NULL)
10205 cur = cur->next;
10206 cur->next = rel;
10207 }
10208
10209
10210 static const xmlChar *
xmlSchemaBuildAbsoluteURI(xmlDictPtr dict,const xmlChar * location,xmlNodePtr ctxtNode)10211 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10212 xmlNodePtr ctxtNode)
10213 {
10214 /*
10215 * Build an absolute location URI.
10216 */
10217 if (location != NULL) {
10218 if (ctxtNode == NULL)
10219 return(location);
10220 else {
10221 xmlChar *base, *URI;
10222 const xmlChar *ret = NULL;
10223
10224 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10225 if (base == NULL) {
10226 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10227 } else {
10228 URI = xmlBuildURI(location, base);
10229 xmlFree(base);
10230 }
10231 if (URI != NULL) {
10232 ret = xmlDictLookup(dict, URI, -1);
10233 xmlFree(URI);
10234 return(ret);
10235 }
10236 }
10237 }
10238 return(NULL);
10239 }
10240
10241
10242
10243 /**
10244 * xmlSchemaAddSchemaDoc:
10245 * @pctxt: a schema validation context
10246 * @schema: the schema being built
10247 * @node: a subtree containing XML Schema information
10248 *
10249 * Parse an included (and to-be-redefined) XML schema document.
10250 *
10251 * Returns 0 on success, a positive error code on errors and
10252 * -1 in case of an internal or API error.
10253 */
10254
10255 static int
xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * schemaLocation,xmlDocPtr schemaDoc,const char * schemaBuffer,int schemaBufferLen,xmlNodePtr invokingNode,const xmlChar * sourceTargetNamespace,const xmlChar * importNamespace,xmlSchemaBucketPtr * bucket)10256 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10257 int type, /* import or include or redefine */
10258 const xmlChar *schemaLocation,
10259 xmlDocPtr schemaDoc,
10260 const char *schemaBuffer,
10261 int schemaBufferLen,
10262 xmlNodePtr invokingNode,
10263 const xmlChar *sourceTargetNamespace,
10264 const xmlChar *importNamespace,
10265 xmlSchemaBucketPtr *bucket)
10266 {
10267 const xmlChar *targetNamespace = NULL;
10268 xmlSchemaSchemaRelationPtr relation = NULL;
10269 xmlDocPtr doc = NULL;
10270 int res = 0, err = 0, located = 0, preserveDoc = 0;
10271 xmlSchemaBucketPtr bkt = NULL;
10272
10273 if (bucket != NULL)
10274 *bucket = NULL;
10275
10276 switch (type) {
10277 case XML_SCHEMA_SCHEMA_IMPORT:
10278 case XML_SCHEMA_SCHEMA_MAIN:
10279 err = XML_SCHEMAP_SRC_IMPORT;
10280 break;
10281 case XML_SCHEMA_SCHEMA_INCLUDE:
10282 err = XML_SCHEMAP_SRC_INCLUDE;
10283 break;
10284 case XML_SCHEMA_SCHEMA_REDEFINE:
10285 err = XML_SCHEMAP_SRC_REDEFINE;
10286 break;
10287 }
10288
10289
10290 /* Special handling for the main schema:
10291 * skip the location and relation logic and just parse the doc.
10292 * We need just a bucket to be returned in this case.
10293 */
10294 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10295 goto doc_load;
10296
10297 /* Note that we expect the location to be an absolute URI. */
10298 if (schemaLocation != NULL) {
10299 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10300 if ((bkt != NULL) &&
10301 (pctxt->constructor->bucket == bkt)) {
10302 /* Report self-imports/inclusions/redefinitions. */
10303
10304 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10305 invokingNode, NULL,
10306 "The schema must not import/include/redefine itself",
10307 NULL, NULL);
10308 goto exit;
10309 }
10310 }
10311 /*
10312 * Create a relation for the graph of schemas.
10313 */
10314 relation = xmlSchemaSchemaRelationCreate();
10315 if (relation == NULL)
10316 return(-1);
10317 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10318 relation);
10319 relation->type = type;
10320
10321 /*
10322 * Save the namespace import information.
10323 */
10324 if (WXS_IS_BUCKET_IMPMAIN(type)) {
10325 relation->importNamespace = importNamespace;
10326 if (schemaLocation == NULL) {
10327 /*
10328 * No location; this is just an import of the namespace.
10329 * Note that we don't assign a bucket to the relation
10330 * in this case.
10331 */
10332 goto exit;
10333 }
10334 targetNamespace = importNamespace;
10335 }
10336
10337 /* Did we already fetch the doc? */
10338 if (bkt != NULL) {
10339 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10340 /*
10341 * We included/redefined and then try to import a schema,
10342 * but the new location provided for import was different.
10343 */
10344 if (schemaLocation == NULL)
10345 schemaLocation = BAD_CAST "in_memory_buffer";
10346 if (!xmlStrEqual(schemaLocation,
10347 bkt->schemaLocation)) {
10348 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10349 invokingNode, NULL,
10350 "The schema document '%s' cannot be imported, since "
10351 "it was already included or redefined",
10352 schemaLocation, NULL);
10353 goto exit;
10354 }
10355 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10356 /*
10357 * We imported and then try to include/redefine a schema,
10358 * but the new location provided for the include/redefine
10359 * was different.
10360 */
10361 if (schemaLocation == NULL)
10362 schemaLocation = BAD_CAST "in_memory_buffer";
10363 if (!xmlStrEqual(schemaLocation,
10364 bkt->schemaLocation)) {
10365 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10366 invokingNode, NULL,
10367 "The schema document '%s' cannot be included or "
10368 "redefined, since it was already imported",
10369 schemaLocation, NULL);
10370 goto exit;
10371 }
10372 }
10373 }
10374
10375 if (WXS_IS_BUCKET_IMPMAIN(type)) {
10376 /*
10377 * Given that the schemaLocation [attribute] is only a hint, it is open
10378 * to applications to ignore all but the first <import> for a given
10379 * namespace, regardless of the `actual value` of schemaLocation, but
10380 * such a strategy risks missing useful information when new
10381 * schemaLocations are offered.
10382 *
10383 * We will use the first <import> that comes with a location.
10384 * Further <import>s *with* a location, will result in an error.
10385 * TODO: Better would be to just report a warning here, but
10386 * we'll try it this way until someone complains.
10387 *
10388 * Schema Document Location Strategy:
10389 * 3 Based on the namespace name, identify an existing schema document,
10390 * either as a resource which is an XML document or a <schema> element
10391 * information item, in some local schema repository;
10392 * 5 Attempt to resolve the namespace name to locate such a resource.
10393 *
10394 * NOTE: (3) and (5) are not supported.
10395 */
10396 if (bkt != NULL) {
10397 relation->bucket = bkt;
10398 goto exit;
10399 }
10400 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10401 importNamespace, 1);
10402
10403 if (bkt != NULL) {
10404 relation->bucket = bkt;
10405 if (bkt->schemaLocation == NULL) {
10406 /* First given location of the schema; load the doc. */
10407 bkt->schemaLocation = schemaLocation;
10408 } else {
10409 if (!xmlStrEqual(schemaLocation,
10410 bkt->schemaLocation)) {
10411 /*
10412 * Additional location given; just skip it.
10413 * URGENT TODO: We should report a warning here.
10414 * res = XML_SCHEMAP_SRC_IMPORT;
10415 */
10416 if (schemaLocation == NULL)
10417 schemaLocation = BAD_CAST "in_memory_buffer";
10418
10419 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10420 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10421 invokingNode, NULL,
10422 "Skipping import of schema located at '%s' for the "
10423 "namespace '%s', since this namespace was already "
10424 "imported with the schema located at '%s'",
10425 schemaLocation, importNamespace, bkt->schemaLocation);
10426 }
10427 goto exit;
10428 }
10429 }
10430 /*
10431 * No bucket + first location: load the doc and create a
10432 * bucket.
10433 */
10434 } else {
10435 /* <include> and <redefine> */
10436 if (bkt != NULL) {
10437
10438 if ((bkt->origTargetNamespace == NULL) &&
10439 (bkt->targetNamespace != sourceTargetNamespace)) {
10440 xmlSchemaBucketPtr chamel;
10441
10442 /*
10443 * Chameleon include/redefine: skip loading only if it was
10444 * already build for the targetNamespace of the including
10445 * schema.
10446 */
10447 /*
10448 * URGENT TODO: If the schema is a chameleon-include then copy
10449 * the components into the including schema and modify the
10450 * targetNamespace of those components, do nothing otherwise.
10451 * NOTE: This is currently worked-around by compiling the
10452 * chameleon for every distinct including targetNamespace; thus
10453 * not performant at the moment.
10454 * TODO: Check when the namespace in wildcards for chameleons
10455 * needs to be converted: before we built wildcard intersections
10456 * or after.
10457 * Answer: after!
10458 */
10459 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10460 schemaLocation, sourceTargetNamespace);
10461 if (chamel != NULL) {
10462 /* A fitting chameleon was already parsed; NOP. */
10463 relation->bucket = chamel;
10464 goto exit;
10465 }
10466 /*
10467 * We need to parse the chameleon again for a different
10468 * targetNamespace.
10469 * CHAMELEON TODO: Optimize this by only parsing the
10470 * chameleon once, and then copying the components to
10471 * the new targetNamespace.
10472 */
10473 bkt = NULL;
10474 } else {
10475 relation->bucket = bkt;
10476 goto exit;
10477 }
10478 }
10479 }
10480 if ((bkt != NULL) && (bkt->doc != NULL)) {
10481 PERROR_INT("xmlSchemaAddSchemaDoc",
10482 "trying to load a schema doc, but a doc is already "
10483 "assigned to the schema bucket");
10484 goto exit_failure;
10485 }
10486
10487 doc_load:
10488 /*
10489 * Load the document.
10490 */
10491 if (schemaDoc != NULL) {
10492 doc = schemaDoc;
10493 /* Don' free this one, since it was provided by the caller. */
10494 preserveDoc = 1;
10495 /* TODO: Does the context or the doc hold the location? */
10496 if (schemaDoc->URL != NULL)
10497 schemaLocation = xmlDictLookup(pctxt->dict,
10498 schemaDoc->URL, -1);
10499 else
10500 schemaLocation = BAD_CAST "in_memory_buffer";
10501 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10502 xmlParserCtxtPtr parserCtxt;
10503
10504 parserCtxt = xmlNewParserCtxt();
10505 if (parserCtxt == NULL) {
10506 xmlSchemaPErrMemory(NULL);
10507 goto exit_failure;
10508 }
10509
10510 if (pctxt->serror != NULL)
10511 xmlCtxtSetErrorHandler(parserCtxt, pctxt->serror, pctxt->errCtxt);
10512 if (pctxt->resourceLoader != NULL)
10513 xmlCtxtSetResourceLoader(parserCtxt, pctxt->resourceLoader,
10514 pctxt->resourceCtxt);
10515
10516 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10517 /*
10518 * TODO: Do we have to burden the schema parser dict with all
10519 * the content of the schema doc?
10520 */
10521 xmlDictFree(parserCtxt->dict);
10522 parserCtxt->dict = pctxt->dict;
10523 xmlDictReference(parserCtxt->dict);
10524 }
10525 if (schemaLocation != NULL) {
10526 /* Parse from file. */
10527 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10528 NULL, SCHEMAS_PARSE_OPTIONS);
10529 } else if (schemaBuffer != NULL) {
10530 /* Parse from memory buffer. */
10531 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10532 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10533 schemaLocation = BAD_CAST "in_memory_buffer";
10534 if (doc != NULL)
10535 doc->URL = xmlStrdup(schemaLocation);
10536 }
10537 /*
10538 * For <import>:
10539 * 2.1 The referent is (a fragment of) a resource which is an
10540 * XML document (see clause 1.1), which in turn corresponds to
10541 * a <schema> element information item in a well-formed information
10542 * set, which in turn corresponds to a valid schema.
10543 * TODO: (2.1) fragments of XML documents are not supported.
10544 *
10545 * 2.2 The referent is a <schema> element information item in
10546 * a well-formed information set, which in turn corresponds
10547 * to a valid schema.
10548 * TODO: (2.2) is not supported.
10549 */
10550 if (doc == NULL) {
10551 const xmlError *lerr;
10552 lerr = xmlGetLastError();
10553 /*
10554 * Check if this a parser error, or if the document could
10555 * just not be located.
10556 * TODO: Try to find specific error codes to react only on
10557 * localisation failures.
10558 */
10559 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10560 /*
10561 * We assume a parser error here.
10562 */
10563 located = 1;
10564 /* TODO: Error code ?? */
10565 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10566 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10567 invokingNode, NULL,
10568 "Failed to parse the XML resource '%s'",
10569 schemaLocation, NULL);
10570 }
10571 }
10572 xmlFreeParserCtxt(parserCtxt);
10573 if ((doc == NULL) && located)
10574 goto exit_error;
10575 } else {
10576 xmlSchemaPErr(pctxt, NULL,
10577 XML_SCHEMAP_NOTHING_TO_PARSE,
10578 "No information for parsing was provided with the "
10579 "given schema parser context.\n",
10580 NULL, NULL);
10581 goto exit_failure;
10582 }
10583 /*
10584 * Preprocess the document.
10585 */
10586 if (doc != NULL) {
10587 xmlNodePtr docElem = NULL;
10588
10589 located = 1;
10590 docElem = xmlDocGetRootElement(doc);
10591 if (docElem == NULL) {
10592 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10593 invokingNode, NULL,
10594 "The document '%s' has no document element",
10595 schemaLocation, NULL);
10596 goto exit_error;
10597 }
10598 /*
10599 * Remove all the blank text nodes.
10600 */
10601 xmlSchemaCleanupDoc(pctxt, docElem);
10602 /*
10603 * Check the schema's top level element.
10604 */
10605 if (!IS_SCHEMA(docElem, "schema")) {
10606 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10607 invokingNode, NULL,
10608 "The XML document '%s' is not a schema document",
10609 schemaLocation, NULL);
10610 goto exit_error;
10611 }
10612 /*
10613 * Note that we don't apply a type check for the
10614 * targetNamespace value here.
10615 */
10616 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10617 "targetNamespace");
10618 }
10619
10620 /* after_doc_loading: */
10621 if ((bkt == NULL) && located) {
10622 /* Only create a bucket if the schema was located. */
10623 bkt = xmlSchemaBucketCreate(pctxt, type,
10624 targetNamespace);
10625 if (bkt == NULL)
10626 goto exit_failure;
10627 }
10628 if (bkt != NULL) {
10629 bkt->schemaLocation = schemaLocation;
10630 bkt->located = located;
10631 if (doc != NULL) {
10632 bkt->doc = doc;
10633 bkt->targetNamespace = targetNamespace;
10634 bkt->origTargetNamespace = targetNamespace;
10635 if (preserveDoc)
10636 bkt->preserveDoc = 1;
10637 }
10638 if (WXS_IS_BUCKET_IMPMAIN(type))
10639 bkt->imported++;
10640 /*
10641 * Add it to the graph of schemas.
10642 */
10643 if (relation != NULL)
10644 relation->bucket = bkt;
10645 }
10646
10647 exit:
10648 /*
10649 * Return the bucket explicitly; this is needed for the
10650 * main schema.
10651 */
10652 if (bucket != NULL)
10653 *bucket = bkt;
10654 return (0);
10655
10656 exit_error:
10657 if ((doc != NULL) && (! preserveDoc)) {
10658 xmlFreeDoc(doc);
10659 if (bkt != NULL)
10660 bkt->doc = NULL;
10661 }
10662 return(pctxt->err);
10663
10664 exit_failure:
10665 if ((doc != NULL) && (! preserveDoc)) {
10666 xmlFreeDoc(doc);
10667 if (bkt != NULL)
10668 bkt->doc = NULL;
10669 }
10670 return (-1);
10671 }
10672
10673 /**
10674 * xmlSchemaParseImport:
10675 * @ctxt: a schema validation context
10676 * @schema: the schema being built
10677 * @node: a subtree containing XML Schema information
10678 *
10679 * parse a XML schema Import definition
10680 * *WARNING* this interface is highly subject to change
10681 *
10682 * Returns 0 in case of success, a positive error code if
10683 * not valid and -1 in case of an internal error.
10684 */
10685 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)10686 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10687 xmlNodePtr node)
10688 {
10689 xmlNodePtr child;
10690 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10691 const xmlChar *thisTargetNamespace;
10692 xmlAttrPtr attr;
10693 int ret = 0;
10694 xmlSchemaBucketPtr bucket = NULL;
10695
10696 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10697 return (-1);
10698
10699 /*
10700 * Check for illegal attributes.
10701 */
10702 attr = node->properties;
10703 while (attr != NULL) {
10704 if (attr->ns == NULL) {
10705 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10706 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10707 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10708 xmlSchemaPIllegalAttrErr(pctxt,
10709 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10710 }
10711 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10712 xmlSchemaPIllegalAttrErr(pctxt,
10713 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10714 }
10715 attr = attr->next;
10716 }
10717 /*
10718 * Extract and validate attributes.
10719 */
10720 if (xmlSchemaPValAttr(pctxt, NULL, node,
10721 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10722 &namespaceName) != 0) {
10723 xmlSchemaPSimpleTypeErr(pctxt,
10724 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10725 NULL, node,
10726 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10727 NULL, namespaceName, NULL, NULL, NULL);
10728 return (pctxt->err);
10729 }
10730
10731 if (xmlSchemaPValAttr(pctxt, NULL, node,
10732 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10733 &schemaLocation) != 0) {
10734 xmlSchemaPSimpleTypeErr(pctxt,
10735 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10736 NULL, node,
10737 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10738 NULL, schemaLocation, NULL, NULL, NULL);
10739 return (pctxt->err);
10740 }
10741 /*
10742 * And now for the children...
10743 */
10744 child = node->children;
10745 if (IS_SCHEMA(child, "annotation")) {
10746 /*
10747 * the annotation here is simply discarded ...
10748 * TODO: really?
10749 */
10750 child = child->next;
10751 }
10752 if (child != NULL) {
10753 xmlSchemaPContentErr(pctxt,
10754 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10755 NULL, node, child, NULL,
10756 "(annotation?)");
10757 }
10758 /*
10759 * Apply additional constraints.
10760 *
10761 * Note that it is important to use the original @targetNamespace
10762 * (or none at all), to rule out imports of schemas _with_ a
10763 * @targetNamespace if the importing schema is a chameleon schema
10764 * (with no @targetNamespace).
10765 */
10766 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10767 if (namespaceName != NULL) {
10768 /*
10769 * 1.1 If the namespace [attribute] is present, then its `actual value`
10770 * must not match the `actual value` of the enclosing <schema>'s
10771 * targetNamespace [attribute].
10772 */
10773 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10774 xmlSchemaPCustomErr(pctxt,
10775 XML_SCHEMAP_SRC_IMPORT_1_1,
10776 NULL, node,
10777 "The value of the attribute 'namespace' must not match "
10778 "the target namespace '%s' of the importing schema",
10779 thisTargetNamespace);
10780 return (pctxt->err);
10781 }
10782 } else {
10783 /*
10784 * 1.2 If the namespace [attribute] is not present, then the enclosing
10785 * <schema> must have a targetNamespace [attribute].
10786 */
10787 if (thisTargetNamespace == NULL) {
10788 xmlSchemaPCustomErr(pctxt,
10789 XML_SCHEMAP_SRC_IMPORT_1_2,
10790 NULL, node,
10791 "The attribute 'namespace' must be existent if "
10792 "the importing schema has no target namespace",
10793 NULL);
10794 return (pctxt->err);
10795 }
10796 }
10797 /*
10798 * Locate and acquire the schema document.
10799 */
10800 if (schemaLocation != NULL)
10801 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10802 schemaLocation, node);
10803 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10804 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10805 namespaceName, &bucket);
10806
10807 if (ret != 0)
10808 return(ret);
10809
10810 /*
10811 * For <import>: "It is *not* an error for the application
10812 * schema reference strategy to fail."
10813 * So just don't parse if no schema document was found.
10814 * Note that we will get no bucket if the schema could not be
10815 * located or if there was no schemaLocation.
10816 */
10817 if ((bucket == NULL) && (schemaLocation != NULL)) {
10818 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10819 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10820 node, NULL,
10821 "Failed to locate a schema at location '%s'. "
10822 "Skipping the import", schemaLocation, NULL, NULL);
10823 }
10824
10825 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10826 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10827 }
10828
10829 return (ret);
10830 }
10831
10832 static int
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlChar ** schemaLocation,int type)10833 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10834 xmlSchemaPtr schema,
10835 xmlNodePtr node,
10836 xmlChar **schemaLocation,
10837 int type)
10838 {
10839 xmlAttrPtr attr;
10840
10841 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10842 (schemaLocation == NULL))
10843 return (-1);
10844
10845 *schemaLocation = NULL;
10846 /*
10847 * Check for illegal attributes.
10848 * Applies for both <include> and <redefine>.
10849 */
10850 attr = node->properties;
10851 while (attr != NULL) {
10852 if (attr->ns == NULL) {
10853 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10854 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10855 xmlSchemaPIllegalAttrErr(pctxt,
10856 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10857 }
10858 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10859 xmlSchemaPIllegalAttrErr(pctxt,
10860 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10861 }
10862 attr = attr->next;
10863 }
10864 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10865 /*
10866 * Preliminary step, extract the URI-Reference and make an URI
10867 * from the base.
10868 */
10869 /*
10870 * Attribute "schemaLocation" is mandatory.
10871 */
10872 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10873 if (attr != NULL) {
10874 xmlChar *base = NULL;
10875 xmlChar *uri = NULL;
10876
10877 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10878 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10879 (const xmlChar **) schemaLocation) != 0)
10880 goto exit_error;
10881 base = xmlNodeGetBase(node->doc, node);
10882 if (base == NULL) {
10883 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10884 } else {
10885 uri = xmlBuildURI(*schemaLocation, base);
10886 xmlFree(base);
10887 }
10888 if (uri == NULL) {
10889 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10890 "could not build an URI from the schemaLocation")
10891 goto exit_failure;
10892 }
10893 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10894 xmlFree(uri);
10895 } else {
10896 xmlSchemaPMissingAttrErr(pctxt,
10897 XML_SCHEMAP_S4S_ATTR_MISSING,
10898 NULL, node, "schemaLocation", NULL);
10899 goto exit_error;
10900 }
10901 /*
10902 * Report self-inclusion and self-redefinition.
10903 */
10904 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10905 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10906 xmlSchemaPCustomErr(pctxt,
10907 XML_SCHEMAP_SRC_REDEFINE,
10908 NULL, node,
10909 "The schema document '%s' cannot redefine itself.",
10910 *schemaLocation);
10911 } else {
10912 xmlSchemaPCustomErr(pctxt,
10913 XML_SCHEMAP_SRC_INCLUDE,
10914 NULL, node,
10915 "The schema document '%s' cannot include itself.",
10916 *schemaLocation);
10917 }
10918 goto exit_error;
10919 }
10920
10921 return(0);
10922 exit_error:
10923 return(pctxt->err);
10924 exit_failure:
10925 return(-1);
10926 }
10927
10928 static int
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,int type)10929 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10930 xmlSchemaPtr schema,
10931 xmlNodePtr node,
10932 int type)
10933 {
10934 xmlNodePtr child = NULL;
10935 const xmlChar *schemaLocation = NULL;
10936 int res = 0; /* hasRedefinitions = 0 */
10937 int isChameleon = 0, wasChameleon = 0;
10938 xmlSchemaBucketPtr bucket = NULL;
10939
10940 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10941 return (-1);
10942
10943 /*
10944 * Parse attributes. Note that the returned schemaLocation will
10945 * be already converted to an absolute URI.
10946 */
10947 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10948 node, (xmlChar **) (&schemaLocation), type);
10949 if (res != 0)
10950 return(res);
10951 /*
10952 * Load and add the schema document.
10953 */
10954 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10955 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10956 if (res != 0)
10957 return(res);
10958 /*
10959 * If we get no schema bucket back, then this means that the schema
10960 * document could not be located or was broken XML or was not
10961 * a schema document.
10962 */
10963 if ((bucket == NULL) || (bucket->doc == NULL)) {
10964 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10965 /*
10966 * WARNING for <include>:
10967 * We will raise an error if the schema cannot be located
10968 * for inclusions, since the that was the feedback from the
10969 * schema people. I.e. the following spec piece will *not* be
10970 * satisfied:
10971 * SPEC src-include: "It is not an error for the `actual value` of the
10972 * schemaLocation [attribute] to fail to resolve it all, in which
10973 * case no corresponding inclusion is performed.
10974 * So do we need a warning report here?"
10975 */
10976 res = XML_SCHEMAP_SRC_INCLUDE;
10977 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10978 node, NULL,
10979 "Failed to load the document '%s' for inclusion",
10980 schemaLocation, NULL);
10981 } else {
10982 /*
10983 * NOTE: This was changed to raise an error even if no redefinitions
10984 * are specified.
10985 *
10986 * SPEC src-redefine (1)
10987 * "If there are any element information items among the [children]
10988 * other than <annotation> then the `actual value` of the
10989 * schemaLocation [attribute] must successfully resolve."
10990 * TODO: Ask the WG if a the location has always to resolve
10991 * here as well!
10992 */
10993 res = XML_SCHEMAP_SRC_REDEFINE;
10994 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10995 node, NULL,
10996 "Failed to load the document '%s' for redefinition",
10997 schemaLocation, NULL);
10998 }
10999 } else {
11000 /*
11001 * Check targetNamespace sanity before parsing the new schema.
11002 * TODO: Note that we won't check further content if the
11003 * targetNamespace was bad.
11004 */
11005 if (bucket->origTargetNamespace != NULL) {
11006 /*
11007 * SPEC src-include (2.1)
11008 * "SII has a targetNamespace [attribute], and its `actual
11009 * value` is identical to the `actual value` of the targetNamespace
11010 * [attribute] of SII' (which must have such an [attribute])."
11011 */
11012 if (pctxt->targetNamespace == NULL) {
11013 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11014 XML_SCHEMAP_SRC_INCLUDE,
11015 node, NULL,
11016 "The target namespace of the included/redefined schema "
11017 "'%s' has to be absent, since the including/redefining "
11018 "schema has no target namespace",
11019 schemaLocation, NULL);
11020 goto exit_error;
11021 } else if (!xmlStrEqual(bucket->origTargetNamespace,
11022 pctxt->targetNamespace)) {
11023 /* TODO: Change error function. */
11024 xmlSchemaPCustomErrExt(pctxt,
11025 XML_SCHEMAP_SRC_INCLUDE,
11026 NULL, node,
11027 "The target namespace '%s' of the included/redefined "
11028 "schema '%s' differs from '%s' of the "
11029 "including/redefining schema",
11030 bucket->origTargetNamespace, schemaLocation,
11031 pctxt->targetNamespace);
11032 goto exit_error;
11033 }
11034 } else if (pctxt->targetNamespace != NULL) {
11035 /*
11036 * Chameleons: the original target namespace will
11037 * differ from the resulting namespace.
11038 */
11039 isChameleon = 1;
11040 bucket->targetNamespace = pctxt->targetNamespace;
11041 }
11042 }
11043 /*
11044 * Parse the schema.
11045 */
11046 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11047 if (isChameleon) {
11048 /* TODO: Get rid of this flag on the schema itself. */
11049 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11050 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11051 } else
11052 wasChameleon = 1;
11053 }
11054 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11055 /* Restore chameleon flag. */
11056 if (isChameleon && (!wasChameleon))
11057 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11058 }
11059 /*
11060 * And now for the children...
11061 */
11062 child = node->children;
11063 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11064 /*
11065 * Parse (simpleType | complexType | group | attributeGroup))*
11066 */
11067 pctxt->redefined = bucket;
11068 /*
11069 * How to proceed if the redefined schema was not located?
11070 */
11071 pctxt->isRedefine = 1;
11072 while (IS_SCHEMA(child, "annotation") ||
11073 IS_SCHEMA(child, "simpleType") ||
11074 IS_SCHEMA(child, "complexType") ||
11075 IS_SCHEMA(child, "group") ||
11076 IS_SCHEMA(child, "attributeGroup")) {
11077 if (IS_SCHEMA(child, "annotation")) {
11078 /*
11079 * TODO: discard or not?
11080 */
11081 } else if (IS_SCHEMA(child, "simpleType")) {
11082 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11083 } else if (IS_SCHEMA(child, "complexType")) {
11084 xmlSchemaParseComplexType(pctxt, schema, child, 1);
11085 /* hasRedefinitions = 1; */
11086 } else if (IS_SCHEMA(child, "group")) {
11087 /* hasRedefinitions = 1; */
11088 xmlSchemaParseModelGroupDefinition(pctxt,
11089 schema, child);
11090 } else if (IS_SCHEMA(child, "attributeGroup")) {
11091 /* hasRedefinitions = 1; */
11092 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11093 child);
11094 }
11095 child = child->next;
11096 }
11097 pctxt->redefined = NULL;
11098 pctxt->isRedefine = 0;
11099 } else {
11100 if (IS_SCHEMA(child, "annotation")) {
11101 /*
11102 * TODO: discard or not?
11103 */
11104 child = child->next;
11105 }
11106 }
11107 if (child != NULL) {
11108 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11109 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11110 xmlSchemaPContentErr(pctxt, res,
11111 NULL, node, child, NULL,
11112 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11113 } else {
11114 xmlSchemaPContentErr(pctxt, res,
11115 NULL, node, child, NULL,
11116 "(annotation?)");
11117 }
11118 }
11119 return(res);
11120
11121 exit_error:
11122 return(pctxt->err);
11123 }
11124
11125 static int
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11126 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11127 xmlNodePtr node)
11128 {
11129 int res;
11130 #ifndef ENABLE_REDEFINE
11131 TODO
11132 return(0);
11133 #endif
11134 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11135 XML_SCHEMA_SCHEMA_REDEFINE);
11136 if (res != 0)
11137 return(res);
11138 return(0);
11139 }
11140
11141 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11142 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11143 xmlNodePtr node)
11144 {
11145 int res;
11146
11147 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11148 XML_SCHEMA_SCHEMA_INCLUDE);
11149 if (res != 0)
11150 return(res);
11151 return(0);
11152 }
11153
11154 /**
11155 * xmlSchemaParseModelGroup:
11156 * @ctxt: a schema validation context
11157 * @schema: the schema being built
11158 * @node: a subtree containing XML Schema information
11159 * @type: the "compositor" type
11160 * @particleNeeded: if a a model group with a particle
11161 *
11162 * parse a XML schema Sequence definition.
11163 * Applies parts of:
11164 * Schema Representation Constraint:
11165 * Redefinition Constraints and Semantics (src-redefine)
11166 * (6.1), (6.1.1), (6.1.2)
11167 *
11168 * Schema Component Constraint:
11169 * All Group Limited (cos-all-limited) (2)
11170 * TODO: Actually this should go to component-level checks,
11171 * but is done here due to performance. Move it to an other layer
11172 * is schema construction via an API is implemented.
11173 *
11174 * *WARNING* this interface is highly subject to change
11175 *
11176 * Returns -1 in case of error, 0 if the declaration is improper and
11177 * 1 in case of success.
11178 */
11179 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType type,int withParticle)11180 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11181 xmlNodePtr node, xmlSchemaTypeType type,
11182 int withParticle)
11183 {
11184 xmlSchemaModelGroupPtr item;
11185 xmlSchemaParticlePtr particle = NULL;
11186 xmlNodePtr child = NULL;
11187 xmlAttrPtr attr;
11188 int min = 1, max = 1, isElemRef, hasRefs = 0;
11189
11190 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11191 return (NULL);
11192 /*
11193 * Create a model group with the given compositor.
11194 */
11195 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11196 if (item == NULL)
11197 return (NULL);
11198
11199 if (withParticle) {
11200 if (type == XML_SCHEMA_TYPE_ALL) {
11201 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11202 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11203 } else {
11204 /* choice + sequence */
11205 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11206 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11207 "(xs:nonNegativeInteger | unbounded)");
11208 }
11209 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11210 /*
11211 * Create a particle
11212 */
11213 particle = xmlSchemaAddParticle(ctxt, node, min, max);
11214 if (particle == NULL)
11215 return (NULL);
11216 particle->children = (xmlSchemaTreeItemPtr) item;
11217 /*
11218 * Check for illegal attributes.
11219 */
11220 attr = node->properties;
11221 while (attr != NULL) {
11222 if (attr->ns == NULL) {
11223 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11224 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11225 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11226 xmlSchemaPIllegalAttrErr(ctxt,
11227 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11228 }
11229 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11230 xmlSchemaPIllegalAttrErr(ctxt,
11231 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11232 }
11233 attr = attr->next;
11234 }
11235 } else {
11236 /*
11237 * Check for illegal attributes.
11238 */
11239 attr = node->properties;
11240 while (attr != NULL) {
11241 if (attr->ns == NULL) {
11242 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11243 xmlSchemaPIllegalAttrErr(ctxt,
11244 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11245 }
11246 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11247 xmlSchemaPIllegalAttrErr(ctxt,
11248 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11249 }
11250 attr = attr->next;
11251 }
11252 }
11253
11254 /*
11255 * Extract and validate attributes.
11256 */
11257 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11258 /*
11259 * And now for the children...
11260 */
11261 child = node->children;
11262 if (IS_SCHEMA(child, "annotation")) {
11263 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11264 child = child->next;
11265 }
11266 if (type == XML_SCHEMA_TYPE_ALL) {
11267 xmlSchemaParticlePtr part, last = NULL;
11268
11269 while (IS_SCHEMA(child, "element")) {
11270 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11271 schema, child, &isElemRef, 0);
11272 /*
11273 * SPEC cos-all-limited (2)
11274 * "The {max occurs} of all the particles in the {particles}
11275 * of the ('all') group must be 0 or 1.
11276 */
11277 if (part != NULL) {
11278 if (isElemRef)
11279 hasRefs++;
11280 if (part->minOccurs > 1) {
11281 xmlSchemaPCustomErr(ctxt,
11282 XML_SCHEMAP_COS_ALL_LIMITED,
11283 NULL, child,
11284 "Invalid value for minOccurs (must be 0 or 1)",
11285 NULL);
11286 /* Reset to 1. */
11287 part->minOccurs = 1;
11288 }
11289 if (part->maxOccurs > 1) {
11290 xmlSchemaPCustomErr(ctxt,
11291 XML_SCHEMAP_COS_ALL_LIMITED,
11292 NULL, child,
11293 "Invalid value for maxOccurs (must be 0 or 1)",
11294 NULL);
11295 /* Reset to 1. */
11296 part->maxOccurs = 1;
11297 }
11298 if (last == NULL)
11299 item->children = (xmlSchemaTreeItemPtr) part;
11300 else
11301 last->next = (xmlSchemaTreeItemPtr) part;
11302 last = part;
11303 }
11304 child = child->next;
11305 }
11306 if (child != NULL) {
11307 xmlSchemaPContentErr(ctxt,
11308 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11309 NULL, node, child, NULL,
11310 "(annotation?, (annotation?, element*)");
11311 }
11312 } else {
11313 /* choice + sequence */
11314 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11315
11316 while ((IS_SCHEMA(child, "element")) ||
11317 (IS_SCHEMA(child, "group")) ||
11318 (IS_SCHEMA(child, "any")) ||
11319 (IS_SCHEMA(child, "choice")) ||
11320 (IS_SCHEMA(child, "sequence"))) {
11321
11322 if (IS_SCHEMA(child, "element")) {
11323 part = (xmlSchemaTreeItemPtr)
11324 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11325 if (part && isElemRef)
11326 hasRefs++;
11327 } else if (IS_SCHEMA(child, "group")) {
11328 part =
11329 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11330 if (part != NULL)
11331 hasRefs++;
11332 /*
11333 * Handle redefinitions.
11334 */
11335 if (ctxt->isRedefine && ctxt->redef &&
11336 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11337 part && part->children)
11338 {
11339 if ((xmlSchemaGetQNameRefName(part->children) ==
11340 ctxt->redef->refName) &&
11341 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11342 ctxt->redef->refTargetNs))
11343 {
11344 /*
11345 * SPEC src-redefine:
11346 * (6.1) "If it has a <group> among its contents at
11347 * some level the `actual value` of whose ref
11348 * [attribute] is the same as the `actual value` of
11349 * its own name attribute plus target namespace, then
11350 * all of the following must be true:"
11351 * (6.1.1) "It must have exactly one such group."
11352 */
11353 if (ctxt->redefCounter != 0) {
11354 xmlChar *str = NULL;
11355
11356 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11357 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11358 "The redefining model group definition "
11359 "'%s' must not contain more than one "
11360 "reference to the redefined definition",
11361 xmlSchemaFormatQName(&str,
11362 ctxt->redef->refTargetNs,
11363 ctxt->redef->refName),
11364 NULL);
11365 FREE_AND_NULL(str)
11366 part = NULL;
11367 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11368 ((WXS_PARTICLE(part))->maxOccurs != 1))
11369 {
11370 xmlChar *str = NULL;
11371 /*
11372 * SPEC src-redefine:
11373 * (6.1.2) "The `actual value` of both that
11374 * group's minOccurs and maxOccurs [attribute]
11375 * must be 1 (or `absent`).
11376 */
11377 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11378 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11379 "The redefining model group definition "
11380 "'%s' must not contain a reference to the "
11381 "redefined definition with a "
11382 "maxOccurs/minOccurs other than 1",
11383 xmlSchemaFormatQName(&str,
11384 ctxt->redef->refTargetNs,
11385 ctxt->redef->refName),
11386 NULL);
11387 FREE_AND_NULL(str)
11388 part = NULL;
11389 }
11390 ctxt->redef->reference = WXS_BASIC_CAST part;
11391 ctxt->redefCounter++;
11392 }
11393 }
11394 } else if (IS_SCHEMA(child, "any")) {
11395 part = (xmlSchemaTreeItemPtr)
11396 xmlSchemaParseAny(ctxt, schema, child);
11397 } else if (IS_SCHEMA(child, "choice")) {
11398 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11399 XML_SCHEMA_TYPE_CHOICE, 1);
11400 } else if (IS_SCHEMA(child, "sequence")) {
11401 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11402 XML_SCHEMA_TYPE_SEQUENCE, 1);
11403 }
11404 if (part != NULL) {
11405 if (last == NULL)
11406 item->children = part;
11407 else
11408 last->next = part;
11409 last = part;
11410 }
11411 child = child->next;
11412 }
11413 if (child != NULL) {
11414 xmlSchemaPContentErr(ctxt,
11415 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11416 NULL, node, child, NULL,
11417 "(annotation?, (element | group | choice | sequence | any)*)");
11418 }
11419 }
11420 if ((max == 0) && (min == 0))
11421 return (NULL);
11422 if (hasRefs) {
11423 /*
11424 * We need to resolve references.
11425 */
11426 WXS_ADD_PENDING(ctxt, item);
11427 }
11428 if (withParticle)
11429 return ((xmlSchemaTreeItemPtr) particle);
11430 else
11431 return ((xmlSchemaTreeItemPtr) item);
11432 }
11433
11434 /**
11435 * xmlSchemaParseRestriction:
11436 * @ctxt: a schema validation context
11437 * @schema: the schema being built
11438 * @node: a subtree containing XML Schema information
11439 *
11440 * parse a XML schema Restriction definition
11441 * *WARNING* this interface is highly subject to change
11442 *
11443 * Returns the type definition or NULL in case of error
11444 */
11445 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11446 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11447 xmlNodePtr node, xmlSchemaTypeType parentType)
11448 {
11449 xmlSchemaTypePtr type;
11450 xmlNodePtr child = NULL;
11451 xmlAttrPtr attr;
11452
11453 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11454 return (NULL);
11455 /* Not a component, don't create it. */
11456 type = ctxt->ctxtType;
11457 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11458
11459 /*
11460 * Check for illegal attributes.
11461 */
11462 attr = node->properties;
11463 while (attr != NULL) {
11464 if (attr->ns == NULL) {
11465 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11466 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11467 xmlSchemaPIllegalAttrErr(ctxt,
11468 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11469 }
11470 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11471 xmlSchemaPIllegalAttrErr(ctxt,
11472 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11473 }
11474 attr = attr->next;
11475 }
11476 /*
11477 * Extract and validate attributes.
11478 */
11479 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11480 /*
11481 * Attribute
11482 */
11483 /*
11484 * Extract the base type. The "base" attribute is mandatory if inside
11485 * a complex type or if redefining.
11486 *
11487 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11488 * among its [children]), the simple type definition which is
11489 * the {content type} of the type definition `resolved` to by
11490 * the `actual value` of the base [attribute]"
11491 */
11492 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11493 &(type->baseNs), &(type->base)) == 0)
11494 {
11495 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11496 xmlSchemaPMissingAttrErr(ctxt,
11497 XML_SCHEMAP_S4S_ATTR_MISSING,
11498 NULL, node, "base", NULL);
11499 } else if ((ctxt->isRedefine) &&
11500 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11501 {
11502 if (type->base == NULL) {
11503 xmlSchemaPMissingAttrErr(ctxt,
11504 XML_SCHEMAP_S4S_ATTR_MISSING,
11505 NULL, node, "base", NULL);
11506 } else if ((! xmlStrEqual(type->base, type->name)) ||
11507 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11508 {
11509 xmlChar *str1 = NULL, *str2 = NULL;
11510 /*
11511 * REDEFINE: SPEC src-redefine (5)
11512 * "Within the [children], each <simpleType> must have a
11513 * <restriction> among its [children] ... the `actual value` of
11514 * whose base [attribute] must be the same as the `actual value`
11515 * of its own name attribute plus target namespace;"
11516 */
11517 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11518 NULL, node, "This is a redefinition, but the QName "
11519 "value '%s' of the 'base' attribute does not match the "
11520 "type's designation '%s'",
11521 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11522 xmlSchemaFormatQName(&str2, type->targetNamespace,
11523 type->name), NULL);
11524 FREE_AND_NULL(str1);
11525 FREE_AND_NULL(str2);
11526 /* Avoid confusion and erase the values. */
11527 type->base = NULL;
11528 type->baseNs = NULL;
11529 }
11530 }
11531 }
11532 /*
11533 * And now for the children...
11534 */
11535 child = node->children;
11536 if (IS_SCHEMA(child, "annotation")) {
11537 /*
11538 * Add the annotation to the simple type ancestor.
11539 */
11540 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11541 xmlSchemaParseAnnotation(ctxt, child, 1));
11542 child = child->next;
11543 }
11544 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11545 /*
11546 * Corresponds to <simpleType><restriction><simpleType>.
11547 */
11548 if (IS_SCHEMA(child, "simpleType")) {
11549 if (type->base != NULL) {
11550 /*
11551 * src-restriction-base-or-simpleType
11552 * Either the base [attribute] or the simpleType [child] of the
11553 * <restriction> element must be present, but not both.
11554 */
11555 xmlSchemaPContentErr(ctxt,
11556 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11557 NULL, node, child,
11558 "The attribute 'base' and the <simpleType> child are "
11559 "mutually exclusive", NULL);
11560 } else {
11561 type->baseType = (xmlSchemaTypePtr)
11562 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11563 }
11564 child = child->next;
11565 } else if (type->base == NULL) {
11566 xmlSchemaPContentErr(ctxt,
11567 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11568 NULL, node, child,
11569 "Either the attribute 'base' or a <simpleType> child "
11570 "must be present", NULL);
11571 }
11572 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11573 /*
11574 * Corresponds to <complexType><complexContent><restriction>...
11575 * followed by:
11576 *
11577 * Model groups <all>, <choice> and <sequence>.
11578 */
11579 if (IS_SCHEMA(child, "all")) {
11580 type->subtypes = (xmlSchemaTypePtr)
11581 xmlSchemaParseModelGroup(ctxt, schema, child,
11582 XML_SCHEMA_TYPE_ALL, 1);
11583 child = child->next;
11584 } else if (IS_SCHEMA(child, "choice")) {
11585 type->subtypes = (xmlSchemaTypePtr)
11586 xmlSchemaParseModelGroup(ctxt,
11587 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11588 child = child->next;
11589 } else if (IS_SCHEMA(child, "sequence")) {
11590 type->subtypes = (xmlSchemaTypePtr)
11591 xmlSchemaParseModelGroup(ctxt, schema, child,
11592 XML_SCHEMA_TYPE_SEQUENCE, 1);
11593 child = child->next;
11594 /*
11595 * Model group reference <group>.
11596 */
11597 } else if (IS_SCHEMA(child, "group")) {
11598 type->subtypes = (xmlSchemaTypePtr)
11599 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11600 /*
11601 * Note that the reference will be resolved in
11602 * xmlSchemaResolveTypeReferences();
11603 */
11604 child = child->next;
11605 }
11606 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11607 /*
11608 * Corresponds to <complexType><simpleContent><restriction>...
11609 *
11610 * "1.1 the simple type definition corresponding to the <simpleType>
11611 * among the [children] of <restriction> if there is one;"
11612 */
11613 if (IS_SCHEMA(child, "simpleType")) {
11614 /*
11615 * We will store the to-be-restricted simple type in
11616 * type->contentTypeDef *temporarily*.
11617 */
11618 type->contentTypeDef = (xmlSchemaTypePtr)
11619 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11620 if ( type->contentTypeDef == NULL)
11621 return (NULL);
11622 child = child->next;
11623 }
11624 }
11625
11626 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11627 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11628 xmlSchemaFacetPtr facet, lastfacet = NULL;
11629 /*
11630 * Corresponds to <complexType><simpleContent><restriction>...
11631 * <simpleType><restriction>...
11632 */
11633
11634 /*
11635 * Add the facets to the simple type ancestor.
11636 */
11637 /*
11638 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11639 * Simple Type Definition Schema Representation Constraint:
11640 * *Single Facet Value*
11641 */
11642 while ((IS_SCHEMA(child, "minInclusive")) ||
11643 (IS_SCHEMA(child, "minExclusive")) ||
11644 (IS_SCHEMA(child, "maxInclusive")) ||
11645 (IS_SCHEMA(child, "maxExclusive")) ||
11646 (IS_SCHEMA(child, "totalDigits")) ||
11647 (IS_SCHEMA(child, "fractionDigits")) ||
11648 (IS_SCHEMA(child, "pattern")) ||
11649 (IS_SCHEMA(child, "enumeration")) ||
11650 (IS_SCHEMA(child, "whiteSpace")) ||
11651 (IS_SCHEMA(child, "length")) ||
11652 (IS_SCHEMA(child, "maxLength")) ||
11653 (IS_SCHEMA(child, "minLength"))) {
11654 facet = xmlSchemaParseFacet(ctxt, schema, child);
11655 if (facet != NULL) {
11656 if (lastfacet == NULL)
11657 type->facets = facet;
11658 else
11659 lastfacet->next = facet;
11660 lastfacet = facet;
11661 lastfacet->next = NULL;
11662 }
11663 child = child->next;
11664 }
11665 /*
11666 * Create links for derivation and validation.
11667 */
11668 if (type->facets != NULL) {
11669 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11670
11671 facet = type->facets;
11672 do {
11673 facetLink = (xmlSchemaFacetLinkPtr)
11674 xmlMalloc(sizeof(xmlSchemaFacetLink));
11675 if (facetLink == NULL) {
11676 xmlSchemaPErrMemory(ctxt);
11677 xmlFree(facetLink);
11678 return (NULL);
11679 }
11680 facetLink->facet = facet;
11681 facetLink->next = NULL;
11682 if (lastFacetLink == NULL)
11683 type->facetSet = facetLink;
11684 else
11685 lastFacetLink->next = facetLink;
11686 lastFacetLink = facetLink;
11687 facet = facet->next;
11688 } while (facet != NULL);
11689 }
11690 }
11691 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11692 /*
11693 * Attribute uses/declarations.
11694 */
11695 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11696 (xmlSchemaItemListPtr *) &(type->attrUses),
11697 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11698 return(NULL);
11699 /*
11700 * Attribute wildcard.
11701 */
11702 if (IS_SCHEMA(child, "anyAttribute")) {
11703 type->attributeWildcard =
11704 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11705 child = child->next;
11706 }
11707 }
11708 if (child != NULL) {
11709 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11710 xmlSchemaPContentErr(ctxt,
11711 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11712 NULL, node, child, NULL,
11713 "annotation?, (group | all | choice | sequence)?, "
11714 "((attribute | attributeGroup)*, anyAttribute?))");
11715 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11716 xmlSchemaPContentErr(ctxt,
11717 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11718 NULL, node, child, NULL,
11719 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11720 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11721 "length | minLength | maxLength | enumeration | whiteSpace | "
11722 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11723 } else {
11724 /* Simple type */
11725 xmlSchemaPContentErr(ctxt,
11726 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11727 NULL, node, child, NULL,
11728 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11729 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11730 "length | minLength | maxLength | enumeration | whiteSpace | "
11731 "pattern)*))");
11732 }
11733 }
11734 return (NULL);
11735 }
11736
11737 /**
11738 * xmlSchemaParseExtension:
11739 * @ctxt: a schema validation context
11740 * @schema: the schema being built
11741 * @node: a subtree containing XML Schema information
11742 *
11743 * Parses an <extension>, which is found inside a
11744 * <simpleContent> or <complexContent>.
11745 * *WARNING* this interface is highly subject to change.
11746 *
11747 * TODO: Returns the type definition or NULL in case of error
11748 */
11749 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11750 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11751 xmlNodePtr node, xmlSchemaTypeType parentType)
11752 {
11753 xmlSchemaTypePtr type;
11754 xmlNodePtr child = NULL;
11755 xmlAttrPtr attr;
11756
11757 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11758 return (NULL);
11759 /* Not a component, don't create it. */
11760 type = ctxt->ctxtType;
11761 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11762
11763 /*
11764 * Check for illegal attributes.
11765 */
11766 attr = node->properties;
11767 while (attr != NULL) {
11768 if (attr->ns == NULL) {
11769 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11770 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11771 xmlSchemaPIllegalAttrErr(ctxt,
11772 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11773 }
11774 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11775 xmlSchemaPIllegalAttrErr(ctxt,
11776 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11777 }
11778 attr = attr->next;
11779 }
11780
11781 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11782
11783 /*
11784 * Attribute "base" - mandatory.
11785 */
11786 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11787 "base", &(type->baseNs), &(type->base)) == 0) &&
11788 (type->base == NULL)) {
11789 xmlSchemaPMissingAttrErr(ctxt,
11790 XML_SCHEMAP_S4S_ATTR_MISSING,
11791 NULL, node, "base", NULL);
11792 }
11793 /*
11794 * And now for the children...
11795 */
11796 child = node->children;
11797 if (IS_SCHEMA(child, "annotation")) {
11798 /*
11799 * Add the annotation to the type ancestor.
11800 */
11801 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11802 xmlSchemaParseAnnotation(ctxt, child, 1));
11803 child = child->next;
11804 }
11805 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11806 /*
11807 * Corresponds to <complexType><complexContent><extension>... and:
11808 *
11809 * Model groups <all>, <choice>, <sequence> and <group>.
11810 */
11811 if (IS_SCHEMA(child, "all")) {
11812 type->subtypes = (xmlSchemaTypePtr)
11813 xmlSchemaParseModelGroup(ctxt, schema,
11814 child, XML_SCHEMA_TYPE_ALL, 1);
11815 child = child->next;
11816 } else if (IS_SCHEMA(child, "choice")) {
11817 type->subtypes = (xmlSchemaTypePtr)
11818 xmlSchemaParseModelGroup(ctxt, schema,
11819 child, XML_SCHEMA_TYPE_CHOICE, 1);
11820 child = child->next;
11821 } else if (IS_SCHEMA(child, "sequence")) {
11822 type->subtypes = (xmlSchemaTypePtr)
11823 xmlSchemaParseModelGroup(ctxt, schema,
11824 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11825 child = child->next;
11826 } else if (IS_SCHEMA(child, "group")) {
11827 type->subtypes = (xmlSchemaTypePtr)
11828 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11829 /*
11830 * Note that the reference will be resolved in
11831 * xmlSchemaResolveTypeReferences();
11832 */
11833 child = child->next;
11834 }
11835 }
11836 if (child != NULL) {
11837 /*
11838 * Attribute uses/declarations.
11839 */
11840 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11841 (xmlSchemaItemListPtr *) &(type->attrUses),
11842 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11843 return(NULL);
11844 /*
11845 * Attribute wildcard.
11846 */
11847 if (IS_SCHEMA(child, "anyAttribute")) {
11848 ctxt->ctxtType->attributeWildcard =
11849 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11850 child = child->next;
11851 }
11852 }
11853 if (child != NULL) {
11854 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11855 /* Complex content extension. */
11856 xmlSchemaPContentErr(ctxt,
11857 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11858 NULL, node, child, NULL,
11859 "(annotation?, ((group | all | choice | sequence)?, "
11860 "((attribute | attributeGroup)*, anyAttribute?)))");
11861 } else {
11862 /* Simple content extension. */
11863 xmlSchemaPContentErr(ctxt,
11864 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11865 NULL, node, child, NULL,
11866 "(annotation?, ((attribute | attributeGroup)*, "
11867 "anyAttribute?))");
11868 }
11869 }
11870 return (NULL);
11871 }
11872
11873 /**
11874 * xmlSchemaParseSimpleContent:
11875 * @ctxt: a schema validation context
11876 * @schema: the schema being built
11877 * @node: a subtree containing XML Schema information
11878 *
11879 * parse a XML schema SimpleContent definition
11880 * *WARNING* this interface is highly subject to change
11881 *
11882 * Returns the type definition or NULL in case of error
11883 */
11884 static int
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)11885 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11886 xmlSchemaPtr schema, xmlNodePtr node,
11887 int *hasRestrictionOrExtension)
11888 {
11889 xmlSchemaTypePtr type;
11890 xmlNodePtr child = NULL;
11891 xmlAttrPtr attr;
11892
11893 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11894 (hasRestrictionOrExtension == NULL))
11895 return (-1);
11896 *hasRestrictionOrExtension = 0;
11897 /* Not a component, don't create it. */
11898 type = ctxt->ctxtType;
11899 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11900 /*
11901 * Check for illegal attributes.
11902 */
11903 attr = node->properties;
11904 while (attr != NULL) {
11905 if (attr->ns == NULL) {
11906 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11907 xmlSchemaPIllegalAttrErr(ctxt,
11908 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11909 }
11910 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11911 xmlSchemaPIllegalAttrErr(ctxt,
11912 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11913 }
11914 attr = attr->next;
11915 }
11916
11917 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11918
11919 /*
11920 * And now for the children...
11921 */
11922 child = node->children;
11923 if (IS_SCHEMA(child, "annotation")) {
11924 /*
11925 * Add the annotation to the complex type ancestor.
11926 */
11927 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11928 xmlSchemaParseAnnotation(ctxt, child, 1));
11929 child = child->next;
11930 }
11931 if (child == NULL) {
11932 xmlSchemaPContentErr(ctxt,
11933 XML_SCHEMAP_S4S_ELEM_MISSING,
11934 NULL, node, NULL, NULL,
11935 "(annotation?, (restriction | extension))");
11936 }
11937 if (child == NULL) {
11938 xmlSchemaPContentErr(ctxt,
11939 XML_SCHEMAP_S4S_ELEM_MISSING,
11940 NULL, node, NULL, NULL,
11941 "(annotation?, (restriction | extension))");
11942 }
11943 if (IS_SCHEMA(child, "restriction")) {
11944 xmlSchemaParseRestriction(ctxt, schema, child,
11945 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11946 (*hasRestrictionOrExtension) = 1;
11947 child = child->next;
11948 } else if (IS_SCHEMA(child, "extension")) {
11949 xmlSchemaParseExtension(ctxt, schema, child,
11950 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11951 (*hasRestrictionOrExtension) = 1;
11952 child = child->next;
11953 }
11954 if (child != NULL) {
11955 xmlSchemaPContentErr(ctxt,
11956 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11957 NULL, node, child, NULL,
11958 "(annotation?, (restriction | extension))");
11959 }
11960 return (0);
11961 }
11962
11963 /**
11964 * xmlSchemaParseComplexContent:
11965 * @ctxt: a schema validation context
11966 * @schema: the schema being built
11967 * @node: a subtree containing XML Schema information
11968 *
11969 * parse a XML schema ComplexContent definition
11970 * *WARNING* this interface is highly subject to change
11971 *
11972 * Returns the type definition or NULL in case of error
11973 */
11974 static int
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)11975 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11976 xmlSchemaPtr schema, xmlNodePtr node,
11977 int *hasRestrictionOrExtension)
11978 {
11979 xmlSchemaTypePtr type;
11980 xmlNodePtr child = NULL;
11981 xmlAttrPtr attr;
11982
11983 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11984 (hasRestrictionOrExtension == NULL))
11985 return (-1);
11986 *hasRestrictionOrExtension = 0;
11987 /* Not a component, don't create it. */
11988 type = ctxt->ctxtType;
11989 /*
11990 * Check for illegal attributes.
11991 */
11992 attr = node->properties;
11993 while (attr != NULL) {
11994 if (attr->ns == NULL) {
11995 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11996 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
11997 {
11998 xmlSchemaPIllegalAttrErr(ctxt,
11999 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12000 }
12001 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12002 xmlSchemaPIllegalAttrErr(ctxt,
12003 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12004 }
12005 attr = attr->next;
12006 }
12007
12008 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12009
12010 /*
12011 * Set the 'mixed' on the complex type ancestor.
12012 */
12013 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
12014 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12015 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12016 }
12017 child = node->children;
12018 if (IS_SCHEMA(child, "annotation")) {
12019 /*
12020 * Add the annotation to the complex type ancestor.
12021 */
12022 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12023 xmlSchemaParseAnnotation(ctxt, child, 1));
12024 child = child->next;
12025 }
12026 if (child == NULL) {
12027 xmlSchemaPContentErr(ctxt,
12028 XML_SCHEMAP_S4S_ELEM_MISSING,
12029 NULL, node, NULL,
12030 NULL, "(annotation?, (restriction | extension))");
12031 }
12032 if (child == NULL) {
12033 xmlSchemaPContentErr(ctxt,
12034 XML_SCHEMAP_S4S_ELEM_MISSING,
12035 NULL, node, NULL,
12036 NULL, "(annotation?, (restriction | extension))");
12037 }
12038 if (IS_SCHEMA(child, "restriction")) {
12039 xmlSchemaParseRestriction(ctxt, schema, child,
12040 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12041 (*hasRestrictionOrExtension) = 1;
12042 child = child->next;
12043 } else if (IS_SCHEMA(child, "extension")) {
12044 xmlSchemaParseExtension(ctxt, schema, child,
12045 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12046 (*hasRestrictionOrExtension) = 1;
12047 child = child->next;
12048 }
12049 if (child != NULL) {
12050 xmlSchemaPContentErr(ctxt,
12051 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12052 NULL, node, child,
12053 NULL, "(annotation?, (restriction | extension))");
12054 }
12055 return (0);
12056 }
12057
12058 /**
12059 * xmlSchemaParseComplexType:
12060 * @ctxt: a schema validation context
12061 * @schema: the schema being built
12062 * @node: a subtree containing XML Schema information
12063 *
12064 * parse a XML schema Complex Type definition
12065 * *WARNING* this interface is highly subject to change
12066 *
12067 * Returns the type definition or NULL in case of error
12068 */
12069 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)12070 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12071 xmlNodePtr node, int topLevel)
12072 {
12073 xmlSchemaTypePtr type, ctxtType;
12074 xmlNodePtr child = NULL;
12075 const xmlChar *name = NULL;
12076 xmlAttrPtr attr;
12077 const xmlChar *attrValue;
12078 #ifdef ENABLE_NAMED_LOCALS
12079 char buf[40];
12080 #endif
12081 int final = 0, block = 0, hasRestrictionOrExtension = 0;
12082
12083
12084 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12085 return (NULL);
12086
12087 ctxtType = ctxt->ctxtType;
12088
12089 if (topLevel) {
12090 attr = xmlSchemaGetPropNode(node, "name");
12091 if (attr == NULL) {
12092 xmlSchemaPMissingAttrErr(ctxt,
12093 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12094 return (NULL);
12095 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12096 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12097 return (NULL);
12098 }
12099 }
12100
12101 if (topLevel == 0) {
12102 /*
12103 * Parse as local complex type definition.
12104 */
12105 #ifdef ENABLE_NAMED_LOCALS
12106 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12107 type = xmlSchemaAddType(ctxt, schema,
12108 XML_SCHEMA_TYPE_COMPLEX,
12109 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12110 ctxt->targetNamespace, node, 0);
12111 #else
12112 type = xmlSchemaAddType(ctxt, schema,
12113 XML_SCHEMA_TYPE_COMPLEX,
12114 NULL, ctxt->targetNamespace, node, 0);
12115 #endif
12116 if (type == NULL)
12117 return (NULL);
12118 name = type->name;
12119 type->node = node;
12120 type->type = XML_SCHEMA_TYPE_COMPLEX;
12121 /*
12122 * TODO: We need the target namespace.
12123 */
12124 } else {
12125 /*
12126 * Parse as global complex type definition.
12127 */
12128 type = xmlSchemaAddType(ctxt, schema,
12129 XML_SCHEMA_TYPE_COMPLEX,
12130 name, ctxt->targetNamespace, node, 1);
12131 if (type == NULL)
12132 return (NULL);
12133 type->node = node;
12134 type->type = XML_SCHEMA_TYPE_COMPLEX;
12135 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12136 }
12137 type->targetNamespace = ctxt->targetNamespace;
12138 /*
12139 * Handle attributes.
12140 */
12141 attr = node->properties;
12142 while (attr != NULL) {
12143 if (attr->ns == NULL) {
12144 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12145 /*
12146 * Attribute "id".
12147 */
12148 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12149 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12150 /*
12151 * Attribute "mixed".
12152 */
12153 if (xmlSchemaPGetBoolNodeValue(ctxt,
12154 NULL, (xmlNodePtr) attr))
12155 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12156 } else if (topLevel) {
12157 /*
12158 * Attributes of global complex type definitions.
12159 */
12160 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12161 /* Pass. */
12162 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12163 /*
12164 * Attribute "abstract".
12165 */
12166 if (xmlSchemaPGetBoolNodeValue(ctxt,
12167 NULL, (xmlNodePtr) attr))
12168 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12169 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12170 /*
12171 * Attribute "final".
12172 */
12173 attrValue = xmlSchemaGetNodeContent(ctxt,
12174 (xmlNodePtr) attr);
12175 if (xmlSchemaPValAttrBlockFinal(attrValue,
12176 &(type->flags),
12177 -1,
12178 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12179 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12180 -1, -1, -1) != 0)
12181 {
12182 xmlSchemaPSimpleTypeErr(ctxt,
12183 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12184 NULL, (xmlNodePtr) attr, NULL,
12185 "(#all | List of (extension | restriction))",
12186 attrValue, NULL, NULL, NULL);
12187 } else
12188 final = 1;
12189 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12190 /*
12191 * Attribute "block".
12192 */
12193 attrValue = xmlSchemaGetNodeContent(ctxt,
12194 (xmlNodePtr) attr);
12195 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12196 -1,
12197 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12198 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12199 -1, -1, -1) != 0) {
12200 xmlSchemaPSimpleTypeErr(ctxt,
12201 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12202 NULL, (xmlNodePtr) attr, NULL,
12203 "(#all | List of (extension | restriction)) ",
12204 attrValue, NULL, NULL, NULL);
12205 } else
12206 block = 1;
12207 } else {
12208 xmlSchemaPIllegalAttrErr(ctxt,
12209 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12210 }
12211 } else {
12212 xmlSchemaPIllegalAttrErr(ctxt,
12213 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12214 }
12215 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12216 xmlSchemaPIllegalAttrErr(ctxt,
12217 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12218 }
12219 attr = attr->next;
12220 }
12221 if (! block) {
12222 /*
12223 * Apply default "block" values.
12224 */
12225 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12226 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12227 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12228 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12229 }
12230 if (! final) {
12231 /*
12232 * Apply default "block" values.
12233 */
12234 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12235 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12236 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12237 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12238 }
12239 /*
12240 * And now for the children...
12241 */
12242 child = node->children;
12243 if (IS_SCHEMA(child, "annotation")) {
12244 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12245 child = child->next;
12246 }
12247 ctxt->ctxtType = type;
12248 if (IS_SCHEMA(child, "simpleContent")) {
12249 /*
12250 * <complexType><simpleContent>...
12251 * 3.4.3 : 2.2
12252 * Specifying mixed='true' when the <simpleContent>
12253 * alternative is chosen has no effect
12254 */
12255 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12256 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12257 xmlSchemaParseSimpleContent(ctxt, schema, child,
12258 &hasRestrictionOrExtension);
12259 child = child->next;
12260 } else if (IS_SCHEMA(child, "complexContent")) {
12261 /*
12262 * <complexType><complexContent>...
12263 */
12264 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12265 xmlSchemaParseComplexContent(ctxt, schema, child,
12266 &hasRestrictionOrExtension);
12267 child = child->next;
12268 } else {
12269 /*
12270 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12271 *
12272 * SPEC
12273 * "...the third alternative (neither <simpleContent> nor
12274 * <complexContent>) is chosen. This case is understood as shorthand
12275 * for complex content restricting the `ur-type definition`, and the
12276 * details of the mappings should be modified as necessary.
12277 */
12278 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12279 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12280 /*
12281 * Parse model groups.
12282 */
12283 if (IS_SCHEMA(child, "all")) {
12284 type->subtypes = (xmlSchemaTypePtr)
12285 xmlSchemaParseModelGroup(ctxt, schema, child,
12286 XML_SCHEMA_TYPE_ALL, 1);
12287 child = child->next;
12288 } else if (IS_SCHEMA(child, "choice")) {
12289 type->subtypes = (xmlSchemaTypePtr)
12290 xmlSchemaParseModelGroup(ctxt, schema, child,
12291 XML_SCHEMA_TYPE_CHOICE, 1);
12292 child = child->next;
12293 } else if (IS_SCHEMA(child, "sequence")) {
12294 type->subtypes = (xmlSchemaTypePtr)
12295 xmlSchemaParseModelGroup(ctxt, schema, child,
12296 XML_SCHEMA_TYPE_SEQUENCE, 1);
12297 child = child->next;
12298 } else if (IS_SCHEMA(child, "group")) {
12299 type->subtypes = (xmlSchemaTypePtr)
12300 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12301 /*
12302 * Note that the reference will be resolved in
12303 * xmlSchemaResolveTypeReferences();
12304 */
12305 child = child->next;
12306 }
12307 /*
12308 * Parse attribute decls/refs.
12309 */
12310 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12311 (xmlSchemaItemListPtr *) &(type->attrUses),
12312 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12313 return(NULL);
12314 /*
12315 * Parse attribute wildcard.
12316 */
12317 if (IS_SCHEMA(child, "anyAttribute")) {
12318 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12319 child = child->next;
12320 }
12321 }
12322 if (child != NULL) {
12323 xmlSchemaPContentErr(ctxt,
12324 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12325 NULL, node, child,
12326 NULL, "(annotation?, (simpleContent | complexContent | "
12327 "((group | all | choice | sequence)?, ((attribute | "
12328 "attributeGroup)*, anyAttribute?))))");
12329 }
12330 /*
12331 * REDEFINE: SPEC src-redefine (5)
12332 */
12333 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12334 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12335 NULL, node, "This is a redefinition, thus the "
12336 "<complexType> must have a <restriction> or <extension> "
12337 "grand-child", NULL);
12338 }
12339 ctxt->ctxtType = ctxtType;
12340 return (type);
12341 }
12342
12343 /************************************************************************
12344 * *
12345 * Validating using Schemas *
12346 * *
12347 ************************************************************************/
12348
12349 /************************************************************************
12350 * *
12351 * Reading/Writing Schemas *
12352 * *
12353 ************************************************************************/
12354
12355 #if 0 /* Will be enabled if it is clear what options are needed. */
12356 /**
12357 * xmlSchemaParserCtxtSetOptions:
12358 * @ctxt: a schema parser context
12359 * @options: a combination of xmlSchemaParserOption
12360 *
12361 * Sets the options to be used during the parse.
12362 *
12363 * Returns 0 in case of success, -1 in case of an
12364 * API error.
12365 */
12366 static int
12367 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12368 int options)
12369
12370 {
12371 int i;
12372
12373 if (ctxt == NULL)
12374 return (-1);
12375 /*
12376 * WARNING: Change the start value if adding to the
12377 * xmlSchemaParseOption.
12378 */
12379 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12380 if (options & 1<<i) {
12381 return (-1);
12382 }
12383 }
12384 ctxt->options = options;
12385 return (0);
12386 }
12387
12388 /**
12389 * xmlSchemaValidCtxtGetOptions:
12390 * @ctxt: a schema parser context
12391 *
12392 * Returns the option combination of the parser context.
12393 */
12394 static int
12395 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12396
12397 {
12398 if (ctxt == NULL)
12399 return (-1);
12400 else
12401 return (ctxt->options);
12402 }
12403 #endif
12404
12405 /**
12406 * xmlSchemaNewParserCtxt:
12407 * @URL: the location of the schema
12408 *
12409 * Create an XML Schemas parse context for that file/resource expected
12410 * to contain an XML Schemas file.
12411 *
12412 * Returns the parser context or NULL in case of error
12413 */
12414 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)12415 xmlSchemaNewParserCtxt(const char *URL)
12416 {
12417 xmlSchemaParserCtxtPtr ret;
12418
12419 if (URL == NULL)
12420 return (NULL);
12421
12422 ret = xmlSchemaParserCtxtCreate();
12423 if (ret == NULL)
12424 return(NULL);
12425 ret->dict = xmlDictCreate();
12426 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12427 return (ret);
12428 }
12429
12430 /**
12431 * xmlSchemaNewMemParserCtxt:
12432 * @buffer: a pointer to a char array containing the schemas
12433 * @size: the size of the array
12434 *
12435 * Create an XML Schemas parse context for that memory buffer expected
12436 * to contain an XML Schemas file.
12437 *
12438 * Returns the parser context or NULL in case of error
12439 */
12440 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)12441 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12442 {
12443 xmlSchemaParserCtxtPtr ret;
12444
12445 if ((buffer == NULL) || (size <= 0))
12446 return (NULL);
12447 ret = xmlSchemaParserCtxtCreate();
12448 if (ret == NULL)
12449 return(NULL);
12450 ret->buffer = buffer;
12451 ret->size = size;
12452 ret->dict = xmlDictCreate();
12453 return (ret);
12454 }
12455
12456 /**
12457 * xmlSchemaNewDocParserCtxt:
12458 * @doc: a preparsed document tree
12459 *
12460 * Create an XML Schemas parse context for that document.
12461 * NB. The document may be modified during the parsing process.
12462 *
12463 * Returns the parser context or NULL in case of error
12464 */
12465 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)12466 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12467 {
12468 xmlSchemaParserCtxtPtr ret;
12469
12470 if (doc == NULL)
12471 return (NULL);
12472 ret = xmlSchemaParserCtxtCreate();
12473 if (ret == NULL)
12474 return(NULL);
12475 ret->doc = doc;
12476 ret->dict = xmlDictCreate();
12477 /* The application has responsibility for the document */
12478 ret->preserve = 1;
12479
12480 return (ret);
12481 }
12482
12483 /**
12484 * xmlSchemaFreeParserCtxt:
12485 * @ctxt: the schema parser context
12486 *
12487 * Free the resources associated to the schema parser context
12488 */
12489 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)12490 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12491 {
12492 if (ctxt == NULL)
12493 return;
12494 if (ctxt->doc != NULL && !ctxt->preserve)
12495 xmlFreeDoc(ctxt->doc);
12496 if (ctxt->vctxt != NULL) {
12497 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12498 }
12499 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12500 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12501 ctxt->constructor = NULL;
12502 ctxt->ownsConstructor = 0;
12503 }
12504 if (ctxt->attrProhibs != NULL)
12505 xmlSchemaItemListFree(ctxt->attrProhibs);
12506 xmlDictFree(ctxt->dict);
12507 xmlFree(ctxt);
12508 }
12509
12510 /************************************************************************
12511 * *
12512 * Building the content models *
12513 * *
12514 ************************************************************************/
12515
12516 /**
12517 * xmlSchemaBuildContentModelForSubstGroup:
12518 *
12519 * Returns 1 if nillable, 0 otherwise
12520 */
12521 static int
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle,int counter,xmlAutomataStatePtr end)12522 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12523 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12524 {
12525 xmlAutomataStatePtr start, tmp;
12526 xmlSchemaElementPtr elemDecl, member;
12527 xmlSchemaSubstGroupPtr substGroup;
12528 int i;
12529 int ret = 0;
12530
12531 elemDecl = (xmlSchemaElementPtr) particle->children;
12532 /*
12533 * Wrap the substitution group with a CHOICE.
12534 */
12535 start = pctxt->state;
12536 if (end == NULL)
12537 end = xmlAutomataNewState(pctxt->am);
12538 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12539 if (substGroup == NULL) {
12540 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12541 XML_SCHEMAP_INTERNAL,
12542 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12543 "declaration is marked having a subst. group but none "
12544 "available.\n", elemDecl->name, NULL);
12545 return(0);
12546 }
12547 if (counter >= 0) {
12548 /*
12549 * NOTE that we put the declaration in, even if it's abstract.
12550 * However, an error will be raised during *validation* if an element
12551 * information item shall be validated against an abstract element
12552 * declaration.
12553 */
12554 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12555 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12556 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12557 /*
12558 * Add subst. group members.
12559 */
12560 for (i = 0; i < substGroup->members->nbItems; i++) {
12561 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12562 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12563 member->name, member->targetNamespace, member);
12564 }
12565 } else if (particle->maxOccurs == 1) {
12566 /*
12567 * NOTE that we put the declaration in, even if it's abstract,
12568 */
12569 xmlAutomataNewEpsilon(pctxt->am,
12570 xmlAutomataNewTransition2(pctxt->am,
12571 start, NULL,
12572 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12573 /*
12574 * Add subst. group members.
12575 */
12576 for (i = 0; i < substGroup->members->nbItems; i++) {
12577 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12578 /*
12579 * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12580 * was incorrectly used instead of xmlAutomataNewTransition2()
12581 * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12582 * section in xmlSchemaBuildAContentModel() ).
12583 * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12584 * intended for the above "counter" section originally. I.e.,
12585 * check xs:all with subst-groups.
12586 *
12587 * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12588 * member->name, member->targetNamespace,
12589 * 1, 1, member);
12590 */
12591 tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12592 member->name, member->targetNamespace, member);
12593 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12594 }
12595 } else {
12596 xmlAutomataStatePtr hop;
12597 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12598 UNBOUNDED : particle->maxOccurs - 1;
12599 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12600
12601 counter =
12602 xmlAutomataNewCounter(pctxt->am, minOccurs,
12603 maxOccurs);
12604 hop = xmlAutomataNewState(pctxt->am);
12605
12606 xmlAutomataNewEpsilon(pctxt->am,
12607 xmlAutomataNewTransition2(pctxt->am,
12608 start, NULL,
12609 elemDecl->name, elemDecl->targetNamespace, elemDecl),
12610 hop);
12611 /*
12612 * Add subst. group members.
12613 */
12614 for (i = 0; i < substGroup->members->nbItems; i++) {
12615 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12616 xmlAutomataNewEpsilon(pctxt->am,
12617 xmlAutomataNewTransition2(pctxt->am,
12618 start, NULL,
12619 member->name, member->targetNamespace, member),
12620 hop);
12621 }
12622 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12623 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12624 }
12625 if (particle->minOccurs == 0) {
12626 xmlAutomataNewEpsilon(pctxt->am, start, end);
12627 ret = 1;
12628 }
12629 pctxt->state = end;
12630 return(ret);
12631 }
12632
12633 /**
12634 * xmlSchemaBuildContentModelForElement:
12635 *
12636 * Returns 1 if nillable, 0 otherwise
12637 */
12638 static int
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr particle)12639 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12640 xmlSchemaParticlePtr particle)
12641 {
12642 int ret = 0;
12643
12644 if (((xmlSchemaElementPtr) particle->children)->flags &
12645 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12646 /*
12647 * Substitution groups.
12648 */
12649 ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12650 } else {
12651 xmlSchemaElementPtr elemDecl;
12652 xmlAutomataStatePtr start;
12653
12654 elemDecl = (xmlSchemaElementPtr) particle->children;
12655
12656 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12657 return(0);
12658 if (particle->maxOccurs == 1) {
12659 start = ctxt->state;
12660 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12661 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12662 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12663 (particle->minOccurs < 2)) {
12664 /* Special case. */
12665 start = ctxt->state;
12666 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12667 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12668 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12669 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12670 } else {
12671 int counter;
12672 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12673 UNBOUNDED : particle->maxOccurs - 1;
12674 int minOccurs = particle->minOccurs < 1 ?
12675 0 : particle->minOccurs - 1;
12676
12677 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12678 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12679 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12680 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12681 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12682 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12683 NULL, counter);
12684 }
12685 if (particle->minOccurs == 0) {
12686 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12687 ret = 1;
12688 }
12689 }
12690 return(ret);
12691 }
12692
12693 /**
12694 * xmlSchemaBuildAContentModel:
12695 * @ctxt: the schema parser context
12696 * @particle: the particle component
12697 * @name: the complex type's name whose content is being built
12698 *
12699 * Create the automaton for the {content type} of a complex type.
12700 *
12701 * Returns 1 if the content is nillable, 0 otherwise
12702 */
12703 static int
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle)12704 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12705 xmlSchemaParticlePtr particle)
12706 {
12707 int ret = 0, tmp2;
12708
12709 if (particle == NULL) {
12710 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12711 return(1);
12712 }
12713 if (particle->children == NULL) {
12714 /*
12715 * Just return in this case. A missing "term" of the particle
12716 * might arise due to an invalid "term" component.
12717 */
12718 return(1);
12719 }
12720
12721 switch (particle->children->type) {
12722 case XML_SCHEMA_TYPE_ANY: {
12723 xmlAutomataStatePtr start, end;
12724 xmlSchemaWildcardPtr wild;
12725 xmlSchemaWildcardNsPtr ns;
12726
12727 wild = (xmlSchemaWildcardPtr) particle->children;
12728
12729 start = pctxt->state;
12730 end = xmlAutomataNewState(pctxt->am);
12731
12732 if (particle->maxOccurs == 1) {
12733 if (wild->any == 1) {
12734 /*
12735 * We need to add both transitions:
12736 *
12737 * 1. the {"*", "*"} for elements in a namespace.
12738 */
12739 pctxt->state =
12740 xmlAutomataNewTransition2(pctxt->am,
12741 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12742 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12743 /*
12744 * 2. the {"*"} for elements in no namespace.
12745 */
12746 pctxt->state =
12747 xmlAutomataNewTransition2(pctxt->am,
12748 start, NULL, BAD_CAST "*", NULL, wild);
12749 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12750
12751 } else if (wild->nsSet != NULL) {
12752 ns = wild->nsSet;
12753 do {
12754 pctxt->state = start;
12755 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12756 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12757 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12758 ns = ns->next;
12759 } while (ns != NULL);
12760
12761 } else if (wild->negNsSet != NULL) {
12762 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12763 start, end, BAD_CAST "*", wild->negNsSet->value,
12764 wild);
12765 }
12766 } else {
12767 int counter;
12768 xmlAutomataStatePtr hop;
12769 int maxOccurs =
12770 particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12771 particle->maxOccurs - 1;
12772 int minOccurs =
12773 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12774
12775 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12776 hop = xmlAutomataNewState(pctxt->am);
12777 if (wild->any == 1) {
12778 pctxt->state =
12779 xmlAutomataNewTransition2(pctxt->am,
12780 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12781 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12782 pctxt->state =
12783 xmlAutomataNewTransition2(pctxt->am,
12784 start, NULL, BAD_CAST "*", NULL, wild);
12785 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12786 } else if (wild->nsSet != NULL) {
12787 ns = wild->nsSet;
12788 do {
12789 pctxt->state =
12790 xmlAutomataNewTransition2(pctxt->am,
12791 start, NULL, BAD_CAST "*", ns->value, wild);
12792 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12793 ns = ns->next;
12794 } while (ns != NULL);
12795
12796 } else if (wild->negNsSet != NULL) {
12797 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12798 start, hop, BAD_CAST "*", wild->negNsSet->value,
12799 wild);
12800 }
12801 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12802 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12803 }
12804 if (particle->minOccurs == 0) {
12805 xmlAutomataNewEpsilon(pctxt->am, start, end);
12806 ret = 1;
12807 }
12808 pctxt->state = end;
12809 break;
12810 }
12811 case XML_SCHEMA_TYPE_ELEMENT:
12812 ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12813 break;
12814 case XML_SCHEMA_TYPE_SEQUENCE:{
12815 xmlSchemaTreeItemPtr sub;
12816
12817 ret = 1;
12818 /*
12819 * If max and min occurrences are default (1) then
12820 * simply iterate over the particles of the <sequence>.
12821 */
12822 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12823 sub = particle->children->children;
12824
12825 while (sub != NULL) {
12826 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12827 (xmlSchemaParticlePtr) sub);
12828 if (tmp2 != 1) ret = 0;
12829 sub = sub->next;
12830 }
12831 } else {
12832 xmlAutomataStatePtr oldstate = pctxt->state;
12833
12834 if (particle->maxOccurs >= UNBOUNDED) {
12835 if (particle->minOccurs > 1) {
12836 xmlAutomataStatePtr tmp;
12837 int counter;
12838
12839 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12840 oldstate, NULL);
12841 oldstate = pctxt->state;
12842
12843 counter = xmlAutomataNewCounter(pctxt->am,
12844 particle->minOccurs - 1, UNBOUNDED);
12845
12846 sub = particle->children->children;
12847 while (sub != NULL) {
12848 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12849 (xmlSchemaParticlePtr) sub);
12850 if (tmp2 != 1) ret = 0;
12851 sub = sub->next;
12852 }
12853 tmp = pctxt->state;
12854 xmlAutomataNewCountedTrans(pctxt->am, tmp,
12855 oldstate, counter);
12856 pctxt->state =
12857 xmlAutomataNewCounterTrans(pctxt->am, tmp,
12858 NULL, counter);
12859 if (ret == 1)
12860 xmlAutomataNewEpsilon(pctxt->am,
12861 oldstate, pctxt->state);
12862
12863 } else {
12864 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12865 oldstate, NULL);
12866 oldstate = pctxt->state;
12867
12868 sub = particle->children->children;
12869 while (sub != NULL) {
12870 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12871 (xmlSchemaParticlePtr) sub);
12872 if (tmp2 != 1) ret = 0;
12873 sub = sub->next;
12874 }
12875 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12876 oldstate);
12877 /*
12878 * epsilon needed to block previous trans from
12879 * being allowed to enter back from another
12880 * construct
12881 */
12882 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12883 pctxt->state, NULL);
12884 if (particle->minOccurs == 0) {
12885 xmlAutomataNewEpsilon(pctxt->am,
12886 oldstate, pctxt->state);
12887 ret = 1;
12888 }
12889 }
12890 } else if ((particle->maxOccurs > 1)
12891 || (particle->minOccurs > 1)) {
12892 xmlAutomataStatePtr tmp;
12893 int counter;
12894
12895 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12896 oldstate, NULL);
12897 oldstate = pctxt->state;
12898
12899 counter = xmlAutomataNewCounter(pctxt->am,
12900 particle->minOccurs - 1,
12901 particle->maxOccurs - 1);
12902
12903 sub = particle->children->children;
12904 while (sub != NULL) {
12905 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12906 (xmlSchemaParticlePtr) sub);
12907 if (tmp2 != 1) ret = 0;
12908 sub = sub->next;
12909 }
12910 tmp = pctxt->state;
12911 xmlAutomataNewCountedTrans(pctxt->am,
12912 tmp, oldstate, counter);
12913 pctxt->state =
12914 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12915 counter);
12916 if ((particle->minOccurs == 0) || (ret == 1)) {
12917 xmlAutomataNewEpsilon(pctxt->am,
12918 oldstate, pctxt->state);
12919 ret = 1;
12920 }
12921 } else {
12922 sub = particle->children->children;
12923 while (sub != NULL) {
12924 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12925 (xmlSchemaParticlePtr) sub);
12926 if (tmp2 != 1) ret = 0;
12927 sub = sub->next;
12928 }
12929
12930 /*
12931 * epsilon needed to block previous trans from
12932 * being allowed to enter back from another
12933 * construct
12934 */
12935 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12936 pctxt->state, NULL);
12937
12938 if (particle->minOccurs == 0) {
12939 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12940 pctxt->state);
12941 ret = 1;
12942 }
12943 }
12944 }
12945 break;
12946 }
12947 case XML_SCHEMA_TYPE_CHOICE:{
12948 xmlSchemaTreeItemPtr sub;
12949 xmlAutomataStatePtr start, end;
12950
12951 ret = 0;
12952 start = pctxt->state;
12953 end = xmlAutomataNewState(pctxt->am);
12954
12955 /*
12956 * iterate over the subtypes and remerge the end with an
12957 * epsilon transition
12958 */
12959 if (particle->maxOccurs == 1) {
12960 sub = particle->children->children;
12961 while (sub != NULL) {
12962 pctxt->state = start;
12963 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12964 (xmlSchemaParticlePtr) sub);
12965 if (tmp2 == 1) ret = 1;
12966 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12967 sub = sub->next;
12968 }
12969 } else {
12970 int counter;
12971 xmlAutomataStatePtr hop, base;
12972 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12973 UNBOUNDED : particle->maxOccurs - 1;
12974 int minOccurs =
12975 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12976
12977 /*
12978 * use a counter to keep track of the number of transitions
12979 * which went through the choice.
12980 */
12981 counter =
12982 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12983 hop = xmlAutomataNewState(pctxt->am);
12984 base = xmlAutomataNewState(pctxt->am);
12985
12986 sub = particle->children->children;
12987 while (sub != NULL) {
12988 pctxt->state = base;
12989 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12990 (xmlSchemaParticlePtr) sub);
12991 if (tmp2 == 1) ret = 1;
12992 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12993 sub = sub->next;
12994 }
12995 xmlAutomataNewEpsilon(pctxt->am, start, base);
12996 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12997 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12998 if (ret == 1)
12999 xmlAutomataNewEpsilon(pctxt->am, base, end);
13000 }
13001 if (particle->minOccurs == 0) {
13002 xmlAutomataNewEpsilon(pctxt->am, start, end);
13003 ret = 1;
13004 }
13005 pctxt->state = end;
13006 break;
13007 }
13008 case XML_SCHEMA_TYPE_ALL:{
13009 xmlAutomataStatePtr start, tmp;
13010 xmlSchemaParticlePtr sub;
13011 xmlSchemaElementPtr elemDecl;
13012
13013 ret = 1;
13014
13015 sub = (xmlSchemaParticlePtr) particle->children->children;
13016 if (sub == NULL)
13017 break;
13018
13019 ret = 0;
13020
13021 start = pctxt->state;
13022 tmp = xmlAutomataNewState(pctxt->am);
13023 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13024 pctxt->state = tmp;
13025 while (sub != NULL) {
13026 pctxt->state = tmp;
13027
13028 elemDecl = (xmlSchemaElementPtr) sub->children;
13029 if (elemDecl == NULL) {
13030 PERROR_INT("xmlSchemaBuildAContentModel",
13031 "<element> particle has no term");
13032 return(ret);
13033 };
13034 /*
13035 * NOTE: The {max occurs} of all the particles in the
13036 * {particles} of the group must be 0 or 1; this is
13037 * already ensured during the parse of the content of
13038 * <all>.
13039 */
13040 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13041 int counter;
13042
13043 /*
13044 * This is an abstract group, we need to share
13045 * the same counter for all the element transitions
13046 * derived from the group
13047 */
13048 counter = xmlAutomataNewCounter(pctxt->am,
13049 sub->minOccurs, sub->maxOccurs);
13050 xmlSchemaBuildContentModelForSubstGroup(pctxt,
13051 sub, counter, pctxt->state);
13052 } else {
13053 if ((sub->minOccurs == 1) &&
13054 (sub->maxOccurs == 1)) {
13055 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13056 pctxt->state,
13057 elemDecl->name,
13058 elemDecl->targetNamespace,
13059 1, 1, elemDecl);
13060 } else if ((sub->minOccurs == 0) &&
13061 (sub->maxOccurs == 1)) {
13062
13063 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13064 pctxt->state,
13065 elemDecl->name,
13066 elemDecl->targetNamespace,
13067 0,
13068 1,
13069 elemDecl);
13070 }
13071 }
13072 sub = (xmlSchemaParticlePtr) sub->next;
13073 }
13074 pctxt->state =
13075 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13076 if (particle->minOccurs == 0) {
13077 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13078 ret = 1;
13079 }
13080 break;
13081 }
13082 case XML_SCHEMA_TYPE_GROUP:
13083 /*
13084 * If we hit a model group definition, then this means that
13085 * it was empty, thus was not substituted for the containing
13086 * model group. Just do nothing in this case.
13087 * TODO: But the group should be substituted and not occur at
13088 * all in the content model at this point. Fix this.
13089 */
13090 ret = 1;
13091 break;
13092 default:
13093 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13094 "xmlSchemaBuildAContentModel",
13095 "found unexpected term of type '%s' in content model",
13096 WXS_ITEM_TYPE_NAME(particle->children), NULL);
13097 return(ret);
13098 }
13099 return(ret);
13100 }
13101
13102 /**
13103 * xmlSchemaBuildContentModel:
13104 * @ctxt: the schema parser context
13105 * @type: the complex type definition
13106 * @name: the element name
13107 *
13108 * Builds the content model of the complex type.
13109 */
13110 static void
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)13111 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13112 xmlSchemaParserCtxtPtr ctxt)
13113 {
13114 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13115 (type->contModel != NULL) ||
13116 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13117 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13118 return;
13119
13120 ctxt->am = NULL;
13121 ctxt->am = xmlNewAutomata();
13122 if (ctxt->am == NULL) {
13123 xmlSchemaPErrMemory(ctxt);
13124 return;
13125 }
13126 ctxt->state = xmlAutomataGetInitState(ctxt->am);
13127 /*
13128 * Build the automaton.
13129 */
13130 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13131 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13132 type->contModel = xmlAutomataCompile(ctxt->am);
13133 if (type->contModel == NULL) {
13134 xmlSchemaPCustomErr(ctxt,
13135 XML_SCHEMAP_INTERNAL,
13136 WXS_BASIC_CAST type, type->node,
13137 "Failed to compile the content model", NULL);
13138 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13139 xmlSchemaPCustomErr(ctxt,
13140 XML_SCHEMAP_NOT_DETERMINISTIC,
13141 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13142 WXS_BASIC_CAST type, type->node,
13143 "The content model is not determinist", NULL);
13144 } else {
13145 }
13146 ctxt->state = NULL;
13147 xmlFreeAutomata(ctxt->am);
13148 ctxt->am = NULL;
13149 }
13150
13151 /**
13152 * xmlSchemaResolveElementReferences:
13153 * @elem: the schema element context
13154 * @ctxt: the schema parser context
13155 *
13156 * Resolves the references of an element declaration
13157 * or particle, which has an element declaration as it's
13158 * term.
13159 */
13160 static void
xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)13161 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13162 xmlSchemaParserCtxtPtr ctxt)
13163 {
13164 if ((ctxt == NULL) || (elemDecl == NULL) ||
13165 ((elemDecl != NULL) &&
13166 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13167 return;
13168 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13169
13170 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13171 xmlSchemaTypePtr type;
13172
13173 /* (type definition) ... otherwise the type definition `resolved`
13174 * to by the `actual value` of the type [attribute] ...
13175 */
13176 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13177 elemDecl->namedTypeNs);
13178 if (type == NULL) {
13179 xmlSchemaPResCompAttrErr(ctxt,
13180 XML_SCHEMAP_SRC_RESOLVE,
13181 WXS_BASIC_CAST elemDecl, elemDecl->node,
13182 "type", elemDecl->namedType, elemDecl->namedTypeNs,
13183 XML_SCHEMA_TYPE_BASIC, "type definition");
13184 } else
13185 elemDecl->subtypes = type;
13186 }
13187 if (elemDecl->substGroup != NULL) {
13188 xmlSchemaElementPtr substHead;
13189
13190 /*
13191 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13192 * substitutionGroup?
13193 */
13194 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13195 elemDecl->substGroupNs);
13196 if (substHead == NULL) {
13197 xmlSchemaPResCompAttrErr(ctxt,
13198 XML_SCHEMAP_SRC_RESOLVE,
13199 WXS_BASIC_CAST elemDecl, NULL,
13200 "substitutionGroup", elemDecl->substGroup,
13201 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13202 } else {
13203 xmlSchemaResolveElementReferences(substHead, ctxt);
13204 /*
13205 * Set the "substitution group affiliation".
13206 * NOTE that now we use the "refDecl" field for this.
13207 */
13208 WXS_SUBST_HEAD(elemDecl) = substHead;
13209 /*
13210 * The type definitions is set to:
13211 * SPEC "...the {type definition} of the element
13212 * declaration `resolved` to by the `actual value`
13213 * of the substitutionGroup [attribute], if present"
13214 */
13215 if (elemDecl->subtypes == NULL) {
13216 if (substHead->subtypes == NULL) {
13217 /*
13218 * This can happen with self-referencing substitution
13219 * groups. The cycle will be detected later, but we have
13220 * to set subtypes to avoid null-pointer dereferences.
13221 */
13222 elemDecl->subtypes = xmlSchemaGetBuiltInType(
13223 XML_SCHEMAS_ANYTYPE);
13224 } else {
13225 elemDecl->subtypes = substHead->subtypes;
13226 }
13227 }
13228 }
13229 }
13230 /*
13231 * SPEC "The definition of anyType serves as the default type definition
13232 * for element declarations whose XML representation does not specify one."
13233 */
13234 if ((elemDecl->subtypes == NULL) &&
13235 (elemDecl->namedType == NULL) &&
13236 (elemDecl->substGroup == NULL))
13237 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13238 }
13239
13240 /**
13241 * xmlSchemaResolveUnionMemberTypes:
13242 * @ctxt: the schema parser context
13243 * @type: the schema simple type definition
13244 *
13245 * Checks and builds the "member type definitions" property of the union
13246 * simple type. This handles part (1), part (2) is done in
13247 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13248 *
13249 * Returns -1 in case of an internal error, 0 otherwise.
13250 */
13251 static int
xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)13252 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13253 xmlSchemaTypePtr type)
13254 {
13255
13256 xmlSchemaTypeLinkPtr link, lastLink, newLink;
13257 xmlSchemaTypePtr memberType;
13258
13259 /*
13260 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13261 * define the explicit members as the type definitions `resolved`
13262 * to by the items in the `actual value` of the memberTypes [attribute],
13263 * if any, followed by the type definitions corresponding to the
13264 * <simpleType>s among the [children] of <union>, if any."
13265 */
13266 /*
13267 * Resolve references.
13268 */
13269 link = type->memberTypes;
13270 lastLink = NULL;
13271 while (link != NULL) {
13272 const xmlChar *name, *nsName;
13273
13274 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13275 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13276
13277 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13278 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13279 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13280 WXS_BASIC_CAST type, type->node, "memberTypes",
13281 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13282 /*
13283 * Remove the member type link.
13284 */
13285 if (lastLink == NULL)
13286 type->memberTypes = link->next;
13287 else
13288 lastLink->next = link->next;
13289 newLink = link;
13290 link = link->next;
13291 xmlFree(newLink);
13292 } else {
13293 link->type = memberType;
13294 lastLink = link;
13295 link = link->next;
13296 }
13297 }
13298 /*
13299 * Add local simple types,
13300 */
13301 memberType = type->subtypes;
13302 while (memberType != NULL) {
13303 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13304 if (link == NULL) {
13305 xmlSchemaPErrMemory(ctxt);
13306 return (-1);
13307 }
13308 link->type = memberType;
13309 link->next = NULL;
13310 if (lastLink == NULL)
13311 type->memberTypes = link;
13312 else
13313 lastLink->next = link;
13314 lastLink = link;
13315 memberType = memberType->next;
13316 }
13317 return (0);
13318 }
13319
13320 /**
13321 * xmlSchemaIsDerivedFromBuiltInType:
13322 * @ctxt: the schema parser context
13323 * @type: the type definition
13324 * @valType: the value type
13325 *
13326 *
13327 * Returns 1 if the type has the given value type, or
13328 * is derived from such a type.
13329 */
13330 static int
xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type,int valType)13331 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13332 {
13333 if (type == NULL)
13334 return (0);
13335 if (WXS_IS_COMPLEX(type))
13336 return (0);
13337 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13338 if (type->builtInType == valType)
13339 return(1);
13340 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13341 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13342 return (0);
13343 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13344 }
13345 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13346 }
13347
13348 #if 0
13349 /**
13350 * xmlSchemaIsDerivedFromBuiltInType:
13351 * @ctxt: the schema parser context
13352 * @type: the type definition
13353 * @valType: the value type
13354 *
13355 *
13356 * Returns 1 if the type has the given value type, or
13357 * is derived from such a type.
13358 */
13359 static int
13360 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13361 {
13362 if (type == NULL)
13363 return (0);
13364 if (WXS_IS_COMPLEX(type))
13365 return (0);
13366 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13367 if (type->builtInType == valType)
13368 return(1);
13369 return (0);
13370 } else
13371 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13372
13373 return (0);
13374 }
13375
13376 static xmlSchemaTypePtr
13377 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13378 {
13379 if (type == NULL)
13380 return (NULL);
13381 if (WXS_IS_COMPLEX(type))
13382 return (NULL);
13383 if (type->type == XML_SCHEMA_TYPE_BASIC)
13384 return(type);
13385 return(xmlSchemaQueryBuiltInType(type->subtypes));
13386 }
13387 #endif
13388
13389 /**
13390 * xmlSchemaGetPrimitiveType:
13391 * @type: the simpleType definition
13392 *
13393 * Returns the primitive type of the given type or
13394 * NULL in case of error.
13395 */
13396 static xmlSchemaTypePtr
xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)13397 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13398 {
13399
13400 while (type != NULL) {
13401 /*
13402 * Note that anySimpleType is actually not a primitive type
13403 * but we need that here.
13404 */
13405 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13406 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13407 return (type);
13408 type = type->baseType;
13409 }
13410
13411 return (NULL);
13412 }
13413
13414 #if 0
13415 /**
13416 * xmlSchemaGetBuiltInTypeAncestor:
13417 * @type: the simpleType definition
13418 *
13419 * Returns the primitive type of the given type or
13420 * NULL in case of error.
13421 */
13422 static xmlSchemaTypePtr
13423 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13424 {
13425 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13426 return (0);
13427 while (type != NULL) {
13428 if (type->type == XML_SCHEMA_TYPE_BASIC)
13429 return (type);
13430 type = type->baseType;
13431 }
13432
13433 return (NULL);
13434 }
13435 #endif
13436
13437 /**
13438 * xmlSchemaCloneWildcardNsConstraints:
13439 * @ctxt: the schema parser context
13440 * @dest: the destination wildcard
13441 * @source: the source wildcard
13442 *
13443 * Clones the namespace constraints of source
13444 * and assigns them to dest.
13445 * Returns -1 on internal error, 0 otherwise.
13446 */
13447 static int
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr dest,xmlSchemaWildcardPtr source)13448 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13449 xmlSchemaWildcardPtr dest,
13450 xmlSchemaWildcardPtr source)
13451 {
13452 xmlSchemaWildcardNsPtr cur, tmp, last;
13453
13454 if ((source == NULL) || (dest == NULL))
13455 return(-1);
13456 dest->any = source->any;
13457 cur = source->nsSet;
13458 last = NULL;
13459 while (cur != NULL) {
13460 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13461 if (tmp == NULL)
13462 return(-1);
13463 tmp->value = cur->value;
13464 if (last == NULL)
13465 dest->nsSet = tmp;
13466 else
13467 last->next = tmp;
13468 last = tmp;
13469 cur = cur->next;
13470 }
13471 if (dest->negNsSet != NULL)
13472 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13473 if (source->negNsSet != NULL) {
13474 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13475 if (dest->negNsSet == NULL)
13476 return(-1);
13477 dest->negNsSet->value = source->negNsSet->value;
13478 } else
13479 dest->negNsSet = NULL;
13480 return(0);
13481 }
13482
13483 /**
13484 * xmlSchemaUnionWildcards:
13485 * @ctxt: the schema parser context
13486 * @completeWild: the first wildcard
13487 * @curWild: the second wildcard
13488 *
13489 * Unions the namespace constraints of the given wildcards.
13490 * @completeWild will hold the resulting union.
13491 * Returns a positive error code on failure, -1 in case of an
13492 * internal error, 0 otherwise.
13493 */
13494 static int
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13495 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13496 xmlSchemaWildcardPtr completeWild,
13497 xmlSchemaWildcardPtr curWild)
13498 {
13499 xmlSchemaWildcardNsPtr cur, curB, tmp;
13500
13501 /*
13502 * 1 If O1 and O2 are the same value, then that value must be the
13503 * value.
13504 */
13505 if ((completeWild->any == curWild->any) &&
13506 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13507 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13508
13509 if ((completeWild->negNsSet == NULL) ||
13510 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13511
13512 if (completeWild->nsSet != NULL) {
13513 int found = 0;
13514
13515 /*
13516 * Check equality of sets.
13517 */
13518 cur = completeWild->nsSet;
13519 while (cur != NULL) {
13520 found = 0;
13521 curB = curWild->nsSet;
13522 while (curB != NULL) {
13523 if (cur->value == curB->value) {
13524 found = 1;
13525 break;
13526 }
13527 curB = curB->next;
13528 }
13529 if (!found)
13530 break;
13531 cur = cur->next;
13532 }
13533 if (found)
13534 return(0);
13535 } else
13536 return(0);
13537 }
13538 }
13539 /*
13540 * 2 If either O1 or O2 is any, then any must be the value
13541 */
13542 if (completeWild->any != curWild->any) {
13543 if (completeWild->any == 0) {
13544 completeWild->any = 1;
13545 if (completeWild->nsSet != NULL) {
13546 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13547 completeWild->nsSet = NULL;
13548 }
13549 if (completeWild->negNsSet != NULL) {
13550 xmlFree(completeWild->negNsSet);
13551 completeWild->negNsSet = NULL;
13552 }
13553 }
13554 return (0);
13555 }
13556 /*
13557 * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13558 * then the union of those sets must be the value.
13559 */
13560 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13561 int found;
13562 xmlSchemaWildcardNsPtr start;
13563
13564 cur = curWild->nsSet;
13565 start = completeWild->nsSet;
13566 while (cur != NULL) {
13567 found = 0;
13568 curB = start;
13569 while (curB != NULL) {
13570 if (cur->value == curB->value) {
13571 found = 1;
13572 break;
13573 }
13574 curB = curB->next;
13575 }
13576 if (!found) {
13577 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13578 if (tmp == NULL)
13579 return (-1);
13580 tmp->value = cur->value;
13581 tmp->next = completeWild->nsSet;
13582 completeWild->nsSet = tmp;
13583 }
13584 cur = cur->next;
13585 }
13586
13587 return(0);
13588 }
13589 /*
13590 * 4 If the two are negations of different values (namespace names
13591 * or `absent`), then a pair of not and `absent` must be the value.
13592 */
13593 if ((completeWild->negNsSet != NULL) &&
13594 (curWild->negNsSet != NULL) &&
13595 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13596 completeWild->negNsSet->value = NULL;
13597
13598 return(0);
13599 }
13600 /*
13601 * 5.
13602 */
13603 if (((completeWild->negNsSet != NULL) &&
13604 (completeWild->negNsSet->value != NULL) &&
13605 (curWild->nsSet != NULL)) ||
13606 ((curWild->negNsSet != NULL) &&
13607 (curWild->negNsSet->value != NULL) &&
13608 (completeWild->nsSet != NULL))) {
13609
13610 int nsFound, absentFound = 0;
13611
13612 if (completeWild->nsSet != NULL) {
13613 cur = completeWild->nsSet;
13614 curB = curWild->negNsSet;
13615 } else {
13616 cur = curWild->nsSet;
13617 curB = completeWild->negNsSet;
13618 }
13619 nsFound = 0;
13620 while (cur != NULL) {
13621 if (cur->value == NULL)
13622 absentFound = 1;
13623 else if (cur->value == curB->value)
13624 nsFound = 1;
13625 if (nsFound && absentFound)
13626 break;
13627 cur = cur->next;
13628 }
13629
13630 if (nsFound && absentFound) {
13631 /*
13632 * 5.1 If the set S includes both the negated namespace
13633 * name and `absent`, then any must be the value.
13634 */
13635 completeWild->any = 1;
13636 if (completeWild->nsSet != NULL) {
13637 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13638 completeWild->nsSet = NULL;
13639 }
13640 if (completeWild->negNsSet != NULL) {
13641 xmlFree(completeWild->negNsSet);
13642 completeWild->negNsSet = NULL;
13643 }
13644 } else if (nsFound && (!absentFound)) {
13645 /*
13646 * 5.2 If the set S includes the negated namespace name
13647 * but not `absent`, then a pair of not and `absent` must
13648 * be the value.
13649 */
13650 if (completeWild->nsSet != NULL) {
13651 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13652 completeWild->nsSet = NULL;
13653 }
13654 if (completeWild->negNsSet == NULL) {
13655 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13656 if (completeWild->negNsSet == NULL)
13657 return (-1);
13658 }
13659 completeWild->negNsSet->value = NULL;
13660 } else if ((!nsFound) && absentFound) {
13661 /*
13662 * 5.3 If the set S includes `absent` but not the negated
13663 * namespace name, then the union is not expressible.
13664 */
13665 xmlSchemaPErr(ctxt, completeWild->node,
13666 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13667 "The union of the wildcard is not expressible.\n",
13668 NULL, NULL);
13669 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13670 } else if ((!nsFound) && (!absentFound)) {
13671 /*
13672 * 5.4 If the set S does not include either the negated namespace
13673 * name or `absent`, then whichever of O1 or O2 is a pair of not
13674 * and a namespace name must be the value.
13675 */
13676 if (completeWild->negNsSet == NULL) {
13677 if (completeWild->nsSet != NULL) {
13678 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13679 completeWild->nsSet = NULL;
13680 }
13681 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13682 if (completeWild->negNsSet == NULL)
13683 return (-1);
13684 completeWild->negNsSet->value = curWild->negNsSet->value;
13685 }
13686 }
13687 return (0);
13688 }
13689 /*
13690 * 6.
13691 */
13692 if (((completeWild->negNsSet != NULL) &&
13693 (completeWild->negNsSet->value == NULL) &&
13694 (curWild->nsSet != NULL)) ||
13695 ((curWild->negNsSet != NULL) &&
13696 (curWild->negNsSet->value == NULL) &&
13697 (completeWild->nsSet != NULL))) {
13698
13699 if (completeWild->nsSet != NULL) {
13700 cur = completeWild->nsSet;
13701 } else {
13702 cur = curWild->nsSet;
13703 }
13704 while (cur != NULL) {
13705 if (cur->value == NULL) {
13706 /*
13707 * 6.1 If the set S includes `absent`, then any must be the
13708 * value.
13709 */
13710 completeWild->any = 1;
13711 if (completeWild->nsSet != NULL) {
13712 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13713 completeWild->nsSet = NULL;
13714 }
13715 if (completeWild->negNsSet != NULL) {
13716 xmlFree(completeWild->negNsSet);
13717 completeWild->negNsSet = NULL;
13718 }
13719 return (0);
13720 }
13721 cur = cur->next;
13722 }
13723 if (completeWild->negNsSet == NULL) {
13724 /*
13725 * 6.2 If the set S does not include `absent`, then a pair of not
13726 * and `absent` must be the value.
13727 */
13728 if (completeWild->nsSet != NULL) {
13729 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13730 completeWild->nsSet = NULL;
13731 }
13732 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13733 if (completeWild->negNsSet == NULL)
13734 return (-1);
13735 completeWild->negNsSet->value = NULL;
13736 }
13737 return (0);
13738 }
13739 return (0);
13740
13741 }
13742
13743 /**
13744 * xmlSchemaIntersectWildcards:
13745 * @ctxt: the schema parser context
13746 * @completeWild: the first wildcard
13747 * @curWild: the second wildcard
13748 *
13749 * Intersects the namespace constraints of the given wildcards.
13750 * @completeWild will hold the resulting intersection.
13751 * Returns a positive error code on failure, -1 in case of an
13752 * internal error, 0 otherwise.
13753 */
13754 static int
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13755 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13756 xmlSchemaWildcardPtr completeWild,
13757 xmlSchemaWildcardPtr curWild)
13758 {
13759 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
13760
13761 /*
13762 * 1 If O1 and O2 are the same value, then that value must be the
13763 * value.
13764 */
13765 if ((completeWild->any == curWild->any) &&
13766 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13767 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13768
13769 if ((completeWild->negNsSet == NULL) ||
13770 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13771
13772 if (completeWild->nsSet != NULL) {
13773 int found = 0;
13774
13775 /*
13776 * Check equality of sets.
13777 */
13778 cur = completeWild->nsSet;
13779 while (cur != NULL) {
13780 found = 0;
13781 curB = curWild->nsSet;
13782 while (curB != NULL) {
13783 if (cur->value == curB->value) {
13784 found = 1;
13785 break;
13786 }
13787 curB = curB->next;
13788 }
13789 if (!found)
13790 break;
13791 cur = cur->next;
13792 }
13793 if (found)
13794 return(0);
13795 } else
13796 return(0);
13797 }
13798 }
13799 /*
13800 * 2 If either O1 or O2 is any, then the other must be the value.
13801 */
13802 if ((completeWild->any != curWild->any) && (completeWild->any)) {
13803 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13804 return(-1);
13805 return(0);
13806 }
13807 /*
13808 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13809 * name or `absent`) and the other is a set of (namespace names or
13810 * `absent`), then that set, minus the negated value if it was in
13811 * the set, minus `absent` if it was in the set, must be the value.
13812 */
13813 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13814 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13815 const xmlChar *neg;
13816
13817 if (completeWild->nsSet == NULL) {
13818 neg = completeWild->negNsSet->value;
13819 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13820 return(-1);
13821 } else
13822 neg = curWild->negNsSet->value;
13823 /*
13824 * Remove absent and negated.
13825 */
13826 prev = NULL;
13827 cur = completeWild->nsSet;
13828 while (cur != NULL) {
13829 if (cur->value == NULL) {
13830 if (prev == NULL)
13831 completeWild->nsSet = cur->next;
13832 else
13833 prev->next = cur->next;
13834 xmlFree(cur);
13835 break;
13836 }
13837 prev = cur;
13838 cur = cur->next;
13839 }
13840 if (neg != NULL) {
13841 prev = NULL;
13842 cur = completeWild->nsSet;
13843 while (cur != NULL) {
13844 if (cur->value == neg) {
13845 if (prev == NULL)
13846 completeWild->nsSet = cur->next;
13847 else
13848 prev->next = cur->next;
13849 xmlFree(cur);
13850 break;
13851 }
13852 prev = cur;
13853 cur = cur->next;
13854 }
13855 }
13856
13857 return(0);
13858 }
13859 /*
13860 * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13861 * then the intersection of those sets must be the value.
13862 */
13863 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13864 int found;
13865
13866 cur = completeWild->nsSet;
13867 prev = NULL;
13868 while (cur != NULL) {
13869 found = 0;
13870 curB = curWild->nsSet;
13871 while (curB != NULL) {
13872 if (cur->value == curB->value) {
13873 found = 1;
13874 break;
13875 }
13876 curB = curB->next;
13877 }
13878 if (!found) {
13879 if (prev == NULL)
13880 completeWild->nsSet = cur->next;
13881 else
13882 prev->next = cur->next;
13883 tmp = cur->next;
13884 xmlFree(cur);
13885 cur = tmp;
13886 continue;
13887 }
13888 prev = cur;
13889 cur = cur->next;
13890 }
13891
13892 return(0);
13893 }
13894 /* 5 If the two are negations of different namespace names,
13895 * then the intersection is not expressible
13896 */
13897 if ((completeWild->negNsSet != NULL) &&
13898 (curWild->negNsSet != NULL) &&
13899 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13900 (completeWild->negNsSet->value != NULL) &&
13901 (curWild->negNsSet->value != NULL)) {
13902
13903 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13904 "The intersection of the wildcard is not expressible.\n",
13905 NULL, NULL);
13906 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13907 }
13908 /*
13909 * 6 If the one is a negation of a namespace name and the other
13910 * is a negation of `absent`, then the one which is the negation
13911 * of a namespace name must be the value.
13912 */
13913 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13914 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13915 (completeWild->negNsSet->value == NULL)) {
13916 completeWild->negNsSet->value = curWild->negNsSet->value;
13917 }
13918 return(0);
13919 }
13920
13921 /**
13922 * xmlSchemaIsWildcardNsConstraintSubset:
13923 * @ctxt: the schema parser context
13924 * @sub: the first wildcard
13925 * @super: the second wildcard
13926 *
13927 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13928 *
13929 * Returns 0 if the namespace constraint of @sub is an intensional
13930 * subset of @super, 1 otherwise.
13931 */
13932 static int
xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,xmlSchemaWildcardPtr super)13933 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13934 xmlSchemaWildcardPtr super)
13935 {
13936 /*
13937 * 1 super must be any.
13938 */
13939 if (super->any)
13940 return (0);
13941 /*
13942 * 2.1 sub must be a pair of not and a namespace name or `absent`.
13943 * 2.2 super must be a pair of not and the same value.
13944 */
13945 if ((sub->negNsSet != NULL) &&
13946 (super->negNsSet != NULL) &&
13947 (sub->negNsSet->value == super->negNsSet->value))
13948 return (0);
13949 /*
13950 * 3.1 sub must be a set whose members are either namespace names or `absent`.
13951 */
13952 if (sub->nsSet != NULL) {
13953 /*
13954 * 3.2.1 super must be the same set or a superset thereof.
13955 */
13956 if (super->nsSet != NULL) {
13957 xmlSchemaWildcardNsPtr cur, curB;
13958 int found = 0;
13959
13960 cur = sub->nsSet;
13961 while (cur != NULL) {
13962 found = 0;
13963 curB = super->nsSet;
13964 while (curB != NULL) {
13965 if (cur->value == curB->value) {
13966 found = 1;
13967 break;
13968 }
13969 curB = curB->next;
13970 }
13971 if (!found)
13972 return (1);
13973 cur = cur->next;
13974 }
13975 if (found)
13976 return (0);
13977 } else if (super->negNsSet != NULL) {
13978 xmlSchemaWildcardNsPtr cur;
13979 /*
13980 * 3.2.2 super must be a pair of not and a namespace name or
13981 * `absent` and that value must not be in sub's set.
13982 */
13983 cur = sub->nsSet;
13984 while (cur != NULL) {
13985 if (cur->value == super->negNsSet->value)
13986 return (1);
13987 cur = cur->next;
13988 }
13989 return (0);
13990 }
13991 }
13992 return (1);
13993 }
13994
13995 static int
xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,int * fixed,const xmlChar ** value,xmlSchemaValPtr * val)13996 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13997 int *fixed,
13998 const xmlChar **value,
13999 xmlSchemaValPtr *val)
14000 {
14001 *fixed = 0;
14002 *value = NULL;
14003 if (val != 0)
14004 *val = NULL;
14005
14006 if (attruse->defValue != NULL) {
14007 *value = attruse->defValue;
14008 if (val != NULL)
14009 *val = attruse->defVal;
14010 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14011 *fixed = 1;
14012 return(1);
14013 } else if ((attruse->attrDecl != NULL) &&
14014 (attruse->attrDecl->defValue != NULL)) {
14015 *value = attruse->attrDecl->defValue;
14016 if (val != NULL)
14017 *val = attruse->attrDecl->defVal;
14018 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14019 *fixed = 1;
14020 return(1);
14021 }
14022 return(0);
14023 }
14024 /**
14025 * xmlSchemaCheckCVCWildcardNamespace:
14026 * @wild: the wildcard
14027 * @ns: the namespace
14028 *
14029 * Validation Rule: Wildcard allows Namespace Name
14030 * (cvc-wildcard-namespace)
14031 *
14032 * Returns 0 if the given namespace matches the wildcard,
14033 * 1 otherwise and -1 on API errors.
14034 */
14035 static int
xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,const xmlChar * ns)14036 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14037 const xmlChar* ns)
14038 {
14039 if (wild == NULL)
14040 return(-1);
14041
14042 if (wild->any)
14043 return(0);
14044 else if (wild->nsSet != NULL) {
14045 xmlSchemaWildcardNsPtr cur;
14046
14047 cur = wild->nsSet;
14048 while (cur != NULL) {
14049 if (xmlStrEqual(cur->value, ns))
14050 return(0);
14051 cur = cur->next;
14052 }
14053 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14054 (!xmlStrEqual(wild->negNsSet->value, ns)))
14055 return(0);
14056
14057 return(1);
14058 }
14059
14060 #define XML_SCHEMA_ACTION_DERIVE 0
14061 #define XML_SCHEMA_ACTION_REDEFINE 1
14062
14063 #define WXS_ACTION_STR(a) \
14064 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14065
14066 /*
14067 * Schema Component Constraint:
14068 * Derivation Valid (Restriction, Complex)
14069 * derivation-ok-restriction (2) - (4)
14070 *
14071 * ATTENTION:
14072 * In XML Schema 1.1 this will be:
14073 * Validation Rule:
14074 * Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14075 *
14076 */
14077 static int
xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,int action,xmlSchemaBasicItemPtr item,xmlSchemaBasicItemPtr baseItem,xmlSchemaItemListPtr uses,xmlSchemaItemListPtr baseUses,xmlSchemaWildcardPtr wild,xmlSchemaWildcardPtr baseWild)14078 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14079 int action,
14080 xmlSchemaBasicItemPtr item,
14081 xmlSchemaBasicItemPtr baseItem,
14082 xmlSchemaItemListPtr uses,
14083 xmlSchemaItemListPtr baseUses,
14084 xmlSchemaWildcardPtr wild,
14085 xmlSchemaWildcardPtr baseWild)
14086 {
14087 xmlSchemaAttributeUsePtr cur = NULL, bcur;
14088 int i, j, found; /* err = 0; */
14089 const xmlChar *bEffValue;
14090 int effFixed;
14091
14092 if (uses != NULL) {
14093 for (i = 0; i < uses->nbItems; i++) {
14094 cur = uses->items[i];
14095 found = 0;
14096 if (baseUses == NULL)
14097 goto not_found;
14098 for (j = 0; j < baseUses->nbItems; j++) {
14099 bcur = baseUses->items[j];
14100 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14101 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14102 (WXS_ATTRUSE_DECL_TNS(cur) ==
14103 WXS_ATTRUSE_DECL_TNS(bcur)))
14104 {
14105 /*
14106 * (2.1) "If there is an attribute use in the {attribute
14107 * uses} of the {base type definition} (call this B) whose
14108 * {attribute declaration} has the same {name} and {target
14109 * namespace}, then all of the following must be true:"
14110 */
14111 found = 1;
14112
14113 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14114 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14115 {
14116 xmlChar *str = NULL;
14117 /*
14118 * (2.1.1) "one of the following must be true:"
14119 * (2.1.1.1) "B's {required} is false."
14120 * (2.1.1.2) "R's {required} is true."
14121 */
14122 xmlSchemaPAttrUseErr4(pctxt,
14123 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14124 WXS_ITEM_NODE(item), item, cur,
14125 "The 'optional' attribute use is inconsistent "
14126 "with the corresponding 'required' attribute use of "
14127 "the %s %s",
14128 WXS_ACTION_STR(action),
14129 xmlSchemaGetComponentDesignation(&str, baseItem),
14130 NULL, NULL);
14131 FREE_AND_NULL(str);
14132 /* err = pctxt->err; */
14133 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14134 WXS_ATTRUSE_TYPEDEF(cur),
14135 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14136 {
14137 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14138
14139 /*
14140 * SPEC (2.1.2) "R's {attribute declaration}'s
14141 * {type definition} must be validly derived from
14142 * B's {type definition} given the empty set as
14143 * defined in Type Derivation OK (Simple) ($3.14.6)."
14144 */
14145 xmlSchemaPAttrUseErr4(pctxt,
14146 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14147 WXS_ITEM_NODE(item), item, cur,
14148 "The attribute declaration's %s "
14149 "is not validly derived from "
14150 "the corresponding %s of the "
14151 "attribute declaration in the %s %s",
14152 xmlSchemaGetComponentDesignation(&strA,
14153 WXS_ATTRUSE_TYPEDEF(cur)),
14154 xmlSchemaGetComponentDesignation(&strB,
14155 WXS_ATTRUSE_TYPEDEF(bcur)),
14156 WXS_ACTION_STR(action),
14157 xmlSchemaGetComponentDesignation(&strC, baseItem));
14158 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14159 FREE_AND_NULL(strA);
14160 FREE_AND_NULL(strB);
14161 FREE_AND_NULL(strC);
14162 /* err = pctxt->err; */
14163 } else {
14164 /*
14165 * 2.1.3 [Definition:] Let the effective value
14166 * constraint of an attribute use be its {value
14167 * constraint}, if present, otherwise its {attribute
14168 * declaration}'s {value constraint} .
14169 */
14170 xmlSchemaGetEffectiveValueConstraint(bcur,
14171 &effFixed, &bEffValue, NULL);
14172 /*
14173 * 2.1.3 ... one of the following must be true
14174 *
14175 * 2.1.3.1 B's `effective value constraint` is
14176 * `absent` or default.
14177 */
14178 if ((bEffValue != NULL) &&
14179 (effFixed == 1)) {
14180 const xmlChar *rEffValue = NULL;
14181
14182 xmlSchemaGetEffectiveValueConstraint(bcur,
14183 &effFixed, &rEffValue, NULL);
14184 /*
14185 * 2.1.3.2 R's `effective value constraint` is
14186 * fixed with the same string as B's.
14187 * MAYBE TODO: Compare the computed values.
14188 * Hmm, it says "same string" so
14189 * string-equality might really be sufficient.
14190 */
14191 if ((effFixed == 0) ||
14192 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14193 {
14194 xmlChar *str = NULL;
14195
14196 xmlSchemaPAttrUseErr4(pctxt,
14197 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14198 WXS_ITEM_NODE(item), item, cur,
14199 "The effective value constraint of the "
14200 "attribute use is inconsistent with "
14201 "its correspondent in the %s %s",
14202 WXS_ACTION_STR(action),
14203 xmlSchemaGetComponentDesignation(&str,
14204 baseItem),
14205 NULL, NULL);
14206 FREE_AND_NULL(str);
14207 /* err = pctxt->err; */
14208 }
14209 }
14210 }
14211 break;
14212 }
14213 }
14214 not_found:
14215 if (!found) {
14216 /*
14217 * (2.2) "otherwise the {base type definition} must have an
14218 * {attribute wildcard} and the {target namespace} of the
14219 * R's {attribute declaration} must be `valid` with respect
14220 * to that wildcard, as defined in Wildcard allows Namespace
14221 * Name ($3.10.4)."
14222 */
14223 if ((baseWild == NULL) ||
14224 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14225 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14226 {
14227 xmlChar *str = NULL;
14228
14229 xmlSchemaPAttrUseErr4(pctxt,
14230 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14231 WXS_ITEM_NODE(item), item, cur,
14232 "Neither a matching attribute use, "
14233 "nor a matching wildcard exists in the %s %s",
14234 WXS_ACTION_STR(action),
14235 xmlSchemaGetComponentDesignation(&str, baseItem),
14236 NULL, NULL);
14237 FREE_AND_NULL(str);
14238 /* err = pctxt->err; */
14239 }
14240 }
14241 }
14242 }
14243 /*
14244 * SPEC derivation-ok-restriction (3):
14245 * (3) "For each attribute use in the {attribute uses} of the {base type
14246 * definition} whose {required} is true, there must be an attribute
14247 * use with an {attribute declaration} with the same {name} and
14248 * {target namespace} as its {attribute declaration} in the {attribute
14249 * uses} of the complex type definition itself whose {required} is true.
14250 */
14251 if (baseUses != NULL) {
14252 for (j = 0; j < baseUses->nbItems; j++) {
14253 bcur = baseUses->items[j];
14254 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14255 continue;
14256 found = 0;
14257 if (uses != NULL) {
14258 for (i = 0; i < uses->nbItems; i++) {
14259 cur = uses->items[i];
14260 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14261 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14262 (WXS_ATTRUSE_DECL_TNS(cur) ==
14263 WXS_ATTRUSE_DECL_TNS(bcur))) {
14264 found = 1;
14265 break;
14266 }
14267 }
14268 }
14269 if (!found) {
14270 xmlChar *strA = NULL, *strB = NULL;
14271
14272 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14273 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14274 NULL, item,
14275 "A matching attribute use for the "
14276 "'required' %s of the %s %s is missing",
14277 xmlSchemaGetComponentDesignation(&strA, bcur),
14278 WXS_ACTION_STR(action),
14279 xmlSchemaGetComponentDesignation(&strB, baseItem),
14280 NULL);
14281 FREE_AND_NULL(strA);
14282 FREE_AND_NULL(strB);
14283 }
14284 }
14285 }
14286 /*
14287 * derivation-ok-restriction (4)
14288 */
14289 if (wild != NULL) {
14290 /*
14291 * (4) "If there is an {attribute wildcard}, all of the
14292 * following must be true:"
14293 */
14294 if (baseWild == NULL) {
14295 xmlChar *str = NULL;
14296
14297 /*
14298 * (4.1) "The {base type definition} must also have one."
14299 */
14300 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14301 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14302 NULL, item,
14303 "The %s has an attribute wildcard, "
14304 "but the %s %s '%s' does not have one",
14305 WXS_ITEM_TYPE_NAME(item),
14306 WXS_ACTION_STR(action),
14307 WXS_ITEM_TYPE_NAME(baseItem),
14308 xmlSchemaGetComponentQName(&str, baseItem));
14309 FREE_AND_NULL(str);
14310 return(pctxt->err);
14311 } else if ((baseWild->any == 0) &&
14312 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14313 {
14314 xmlChar *str = NULL;
14315 /*
14316 * (4.2) "The complex type definition's {attribute wildcard}'s
14317 * {namespace constraint} must be a subset of the {base type
14318 * definition}'s {attribute wildcard}'s {namespace constraint},
14319 * as defined by Wildcard Subset ($3.10.6)."
14320 */
14321 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14322 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14323 NULL, item,
14324 "The attribute wildcard is not a valid "
14325 "subset of the wildcard in the %s %s '%s'",
14326 WXS_ACTION_STR(action),
14327 WXS_ITEM_TYPE_NAME(baseItem),
14328 xmlSchemaGetComponentQName(&str, baseItem),
14329 NULL);
14330 FREE_AND_NULL(str);
14331 return(pctxt->err);
14332 }
14333 /* 4.3 Unless the {base type definition} is the `ur-type
14334 * definition`, the complex type definition's {attribute
14335 * wildcard}'s {process contents} must be identical to or
14336 * stronger than the {base type definition}'s {attribute
14337 * wildcard}'s {process contents}, where strict is stronger
14338 * than lax is stronger than skip.
14339 */
14340 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14341 (wild->processContents < baseWild->processContents)) {
14342 xmlChar *str = NULL;
14343 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14344 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14345 NULL, baseItem,
14346 "The {process contents} of the attribute wildcard is "
14347 "weaker than the one in the %s %s '%s'",
14348 WXS_ACTION_STR(action),
14349 WXS_ITEM_TYPE_NAME(baseItem),
14350 xmlSchemaGetComponentQName(&str, baseItem),
14351 NULL);
14352 FREE_AND_NULL(str)
14353 return(pctxt->err);
14354 }
14355 }
14356 return(0);
14357 }
14358
14359
14360 static int
14361 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14362 xmlSchemaBasicItemPtr item,
14363 xmlSchemaWildcardPtr *completeWild,
14364 xmlSchemaItemListPtr list,
14365 xmlSchemaItemListPtr prohibs);
14366 /**
14367 * xmlSchemaFixupTypeAttributeUses:
14368 * @ctxt: the schema parser context
14369 * @type: the complex type definition
14370 *
14371 *
14372 * Builds the wildcard and the attribute uses on the given complex type.
14373 * Returns -1 if an internal error occurs, 0 otherwise.
14374 *
14375 * ATTENTION TODO: Experimentally this uses pointer comparisons for
14376 * strings, so recheck this if we start to hardcode some schemata, since
14377 * they might not be in the same dict.
14378 * NOTE: It is allowed to "extend" the xs:anyType type.
14379 */
14380 static int
xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14381 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14382 xmlSchemaTypePtr type)
14383 {
14384 xmlSchemaTypePtr baseType = NULL;
14385 xmlSchemaAttributeUsePtr use;
14386 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14387
14388 if (type->baseType == NULL) {
14389 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14390 "no base type");
14391 return (-1);
14392 }
14393 baseType = type->baseType;
14394 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14395 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14396 return(-1);
14397
14398 uses = type->attrUses;
14399 baseUses = baseType->attrUses;
14400 /*
14401 * Expand attribute group references. And build the 'complete'
14402 * wildcard, i.e. intersect multiple wildcards.
14403 * Move attribute prohibitions into a separate list.
14404 */
14405 if (uses != NULL) {
14406 if (WXS_IS_RESTRICTION(type)) {
14407 /*
14408 * This one will transfer all attr. prohibitions
14409 * into pctxt->attrProhibs.
14410 */
14411 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14412 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14413 pctxt->attrProhibs) == -1)
14414 {
14415 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14416 "failed to expand attributes");
14417 return(-1);
14418 }
14419 if (pctxt->attrProhibs->nbItems != 0)
14420 prohibs = pctxt->attrProhibs;
14421 } else {
14422 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14423 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14424 NULL) == -1)
14425 {
14426 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14427 "failed to expand attributes");
14428 return(-1);
14429 }
14430 }
14431 }
14432 /*
14433 * Inherit the attribute uses of the base type.
14434 */
14435 if (baseUses != NULL) {
14436 int i, j;
14437 xmlSchemaAttributeUseProhibPtr pro;
14438
14439 if (WXS_IS_RESTRICTION(type)) {
14440 int usesCount;
14441 xmlSchemaAttributeUsePtr tmp;
14442
14443 if (uses != NULL)
14444 usesCount = uses->nbItems;
14445 else
14446 usesCount = 0;
14447
14448 /* Restriction. */
14449 for (i = 0; i < baseUses->nbItems; i++) {
14450 use = baseUses->items[i];
14451 if (prohibs) {
14452 /*
14453 * Filter out prohibited uses.
14454 */
14455 for (j = 0; j < prohibs->nbItems; j++) {
14456 pro = prohibs->items[j];
14457 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14458 (WXS_ATTRUSE_DECL_TNS(use) ==
14459 pro->targetNamespace))
14460 {
14461 goto inherit_next;
14462 }
14463 }
14464 }
14465 if (usesCount) {
14466 /*
14467 * Filter out existing uses.
14468 */
14469 for (j = 0; j < usesCount; j++) {
14470 tmp = uses->items[j];
14471 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14472 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14473 (WXS_ATTRUSE_DECL_TNS(use) ==
14474 WXS_ATTRUSE_DECL_TNS(tmp)))
14475 {
14476 goto inherit_next;
14477 }
14478 }
14479 }
14480 if (uses == NULL) {
14481 type->attrUses = xmlSchemaItemListCreate();
14482 if (type->attrUses == NULL)
14483 goto exit_failure;
14484 uses = type->attrUses;
14485 }
14486 xmlSchemaItemListAddSize(uses, 2, use);
14487 inherit_next: {}
14488 }
14489 } else {
14490 /* Extension. */
14491 for (i = 0; i < baseUses->nbItems; i++) {
14492 use = baseUses->items[i];
14493 if (uses == NULL) {
14494 type->attrUses = xmlSchemaItemListCreate();
14495 if (type->attrUses == NULL)
14496 goto exit_failure;
14497 uses = type->attrUses;
14498 }
14499 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14500 }
14501 }
14502 }
14503 /*
14504 * Shrink attr. uses.
14505 */
14506 if (uses) {
14507 if (uses->nbItems == 0) {
14508 xmlSchemaItemListFree(uses);
14509 type->attrUses = NULL;
14510 }
14511 /*
14512 * TODO: We could shrink the size of the array
14513 * to fit the actual number of items.
14514 */
14515 }
14516 /*
14517 * Compute the complete wildcard.
14518 */
14519 if (WXS_IS_EXTENSION(type)) {
14520 if (baseType->attributeWildcard != NULL) {
14521 /*
14522 * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14523 * the appropriate case among the following:"
14524 */
14525 if (type->attributeWildcard != NULL) {
14526 /*
14527 * Union the complete wildcard with the base wildcard.
14528 * SPEC {attribute wildcard}
14529 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14530 * and {annotation} are those of the `complete wildcard`,
14531 * and whose {namespace constraint} is the intensional union
14532 * of the {namespace constraint} of the `complete wildcard`
14533 * and of the `base wildcard`, as defined in Attribute
14534 * Wildcard Union ($3.10.6)."
14535 */
14536 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14537 baseType->attributeWildcard) == -1)
14538 goto exit_failure;
14539 } else {
14540 /*
14541 * (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14542 * then the `base wildcard`."
14543 */
14544 type->attributeWildcard = baseType->attributeWildcard;
14545 }
14546 } else {
14547 /*
14548 * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14549 * `complete wildcard`"
14550 * NOOP
14551 */
14552 }
14553 } else {
14554 /*
14555 * SPEC {attribute wildcard}
14556 * (3.1) "If the <restriction> alternative is chosen, then the
14557 * `complete wildcard`;"
14558 * NOOP
14559 */
14560 }
14561
14562 return (0);
14563
14564 exit_failure:
14565 return(-1);
14566 }
14567
14568 /**
14569 * xmlSchemaTypeFinalContains:
14570 * @schema: the schema
14571 * @type: the type definition
14572 * @final: the final
14573 *
14574 * Evaluates if a type definition contains the given "final".
14575 * This does take "finalDefault" into account as well.
14576 *
14577 * Returns 1 if the type does contain the given "final",
14578 * 0 otherwise.
14579 */
14580 static int
xmlSchemaTypeFinalContains(xmlSchemaTypePtr type,int final)14581 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14582 {
14583 if (type == NULL)
14584 return (0);
14585 if (type->flags & final)
14586 return (1);
14587 else
14588 return (0);
14589 }
14590
14591 /**
14592 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14593 * @type: the Union Simple Type
14594 *
14595 * Returns a list of member types of @type if existing,
14596 * returns NULL otherwise.
14597 */
14598 static xmlSchemaTypeLinkPtr
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)14599 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14600 {
14601 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14602 if (type->memberTypes != NULL)
14603 return (type->memberTypes);
14604 else
14605 type = type->baseType;
14606 }
14607 return (NULL);
14608 }
14609
14610 #if 0
14611 /**
14612 * xmlSchemaGetParticleTotalRangeMin:
14613 * @particle: the particle
14614 *
14615 * Schema Component Constraint: Effective Total Range
14616 * (all and sequence) + (choice)
14617 *
14618 * Returns the minimum Effective Total Range.
14619 */
14620 static int
14621 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14622 {
14623 if ((particle->children == NULL) ||
14624 (particle->minOccurs == 0))
14625 return (0);
14626 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14627 int min = -1, cur;
14628 xmlSchemaParticlePtr part =
14629 (xmlSchemaParticlePtr) particle->children->children;
14630
14631 if (part == NULL)
14632 return (0);
14633 while (part != NULL) {
14634 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14635 (part->children->type == XML_SCHEMA_TYPE_ANY))
14636 cur = part->minOccurs;
14637 else
14638 cur = xmlSchemaGetParticleTotalRangeMin(part);
14639 if (cur == 0)
14640 return (0);
14641 if ((min > cur) || (min == -1))
14642 min = cur;
14643 part = (xmlSchemaParticlePtr) part->next;
14644 }
14645 return (particle->minOccurs * min);
14646 } else {
14647 /* <all> and <sequence> */
14648 int sum = 0;
14649 xmlSchemaParticlePtr part =
14650 (xmlSchemaParticlePtr) particle->children->children;
14651
14652 if (part == NULL)
14653 return (0);
14654 do {
14655 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14656 (part->children->type == XML_SCHEMA_TYPE_ANY))
14657 sum += part->minOccurs;
14658 else
14659 sum += xmlSchemaGetParticleTotalRangeMin(part);
14660 part = (xmlSchemaParticlePtr) part->next;
14661 } while (part != NULL);
14662 return (particle->minOccurs * sum);
14663 }
14664 }
14665
14666 /**
14667 * xmlSchemaGetParticleTotalRangeMax:
14668 * @particle: the particle
14669 *
14670 * Schema Component Constraint: Effective Total Range
14671 * (all and sequence) + (choice)
14672 *
14673 * Returns the maximum Effective Total Range.
14674 */
14675 static int
14676 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14677 {
14678 if ((particle->children == NULL) ||
14679 (particle->children->children == NULL))
14680 return (0);
14681 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14682 int max = -1, cur;
14683 xmlSchemaParticlePtr part =
14684 (xmlSchemaParticlePtr) particle->children->children;
14685
14686 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14687 if (part->children == NULL)
14688 continue;
14689 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14690 (part->children->type == XML_SCHEMA_TYPE_ANY))
14691 cur = part->maxOccurs;
14692 else
14693 cur = xmlSchemaGetParticleTotalRangeMax(part);
14694 if (cur == UNBOUNDED)
14695 return (UNBOUNDED);
14696 if ((max < cur) || (max == -1))
14697 max = cur;
14698 }
14699 /* TODO: Handle overflows? */
14700 return (particle->maxOccurs * max);
14701 } else {
14702 /* <all> and <sequence> */
14703 int sum = 0, cur;
14704 xmlSchemaParticlePtr part =
14705 (xmlSchemaParticlePtr) particle->children->children;
14706
14707 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14708 if (part->children == NULL)
14709 continue;
14710 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14711 (part->children->type == XML_SCHEMA_TYPE_ANY))
14712 cur = part->maxOccurs;
14713 else
14714 cur = xmlSchemaGetParticleTotalRangeMax(part);
14715 if (cur == UNBOUNDED)
14716 return (UNBOUNDED);
14717 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14718 return (UNBOUNDED);
14719 sum += cur;
14720 }
14721 /* TODO: Handle overflows? */
14722 return (particle->maxOccurs * sum);
14723 }
14724 }
14725 #endif
14726
14727 /**
14728 * xmlSchemaGetParticleEmptiable:
14729 * @particle: the particle
14730 *
14731 * Returns 1 if emptiable, 0 otherwise.
14732 */
14733 static int
xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)14734 xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
14735 {
14736 xmlSchemaParticlePtr part;
14737 int emptiable;
14738
14739 if ((particle->children == NULL) || (particle->minOccurs == 0))
14740 return (1);
14741
14742 part = (xmlSchemaParticlePtr) particle->children->children;
14743 if (part == NULL)
14744 return (1);
14745
14746 while (part != NULL) {
14747 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14748 (part->children->type == XML_SCHEMA_TYPE_ANY))
14749 emptiable = (part->minOccurs == 0);
14750 else
14751 emptiable = xmlSchemaGetParticleEmptiable(part);
14752 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14753 if (emptiable)
14754 return (1);
14755 } else {
14756 /* <all> and <sequence> */
14757 if (!emptiable)
14758 return (0);
14759 }
14760 part = (xmlSchemaParticlePtr) part->next;
14761 }
14762
14763 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
14764 return (0);
14765 else
14766 return (1);
14767 }
14768
14769 /**
14770 * xmlSchemaIsParticleEmptiable:
14771 * @particle: the particle
14772 *
14773 * Schema Component Constraint: Particle Emptiable
14774 * Checks whether the given particle is emptiable.
14775 *
14776 * Returns 1 if emptiable, 0 otherwise.
14777 */
14778 static int
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)14779 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14780 {
14781 /*
14782 * SPEC (1) "Its {min occurs} is 0."
14783 */
14784 if ((particle == NULL) || (particle->minOccurs == 0) ||
14785 (particle->children == NULL))
14786 return (1);
14787 /*
14788 * SPEC (2) "Its {term} is a group and the minimum part of the
14789 * effective total range of that group, [...] is 0."
14790 */
14791 if (WXS_IS_MODEL_GROUP(particle->children))
14792 return (xmlSchemaGetParticleEmptiable(particle));
14793 return (0);
14794 }
14795
14796 /**
14797 * xmlSchemaCheckCOSSTDerivedOK:
14798 * @actxt: a context
14799 * @type: the derived simple type definition
14800 * @baseType: the base type definition
14801 * @subset: the subset of ('restriction', etc.)
14802 *
14803 * Schema Component Constraint:
14804 * Type Derivation OK (Simple) (cos-st-derived-OK)
14805 *
14806 * Checks whether @type can be validly
14807 * derived from @baseType.
14808 *
14809 * Returns 0 on success, an positive error code otherwise.
14810 */
14811 static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int subset)14812 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14813 xmlSchemaTypePtr type,
14814 xmlSchemaTypePtr baseType,
14815 int subset)
14816 {
14817 /*
14818 * 1 They are the same type definition.
14819 * TODO: The identity check might have to be more complex than this.
14820 */
14821 if (type == baseType)
14822 return (0);
14823 /*
14824 * 2.1 restriction is not in the subset, or in the {final}
14825 * of its own {base type definition};
14826 *
14827 * NOTE that this will be used also via "xsi:type".
14828 *
14829 * TODO: Revise this, it looks strange. How can the "type"
14830 * not be fixed or *in* fixing?
14831 */
14832 if (WXS_IS_TYPE_NOT_FIXED(type))
14833 if (xmlSchemaTypeFixup(type, actxt) == -1)
14834 return(-1);
14835 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14836 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14837 return(-1);
14838 if ((subset & SUBSET_RESTRICTION) ||
14839 (xmlSchemaTypeFinalContains(type->baseType,
14840 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14841 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14842 }
14843 /* 2.2 */
14844 if (type->baseType == baseType) {
14845 /*
14846 * 2.2.1 D's `base type definition` is B.
14847 */
14848 return (0);
14849 }
14850 /*
14851 * 2.2.2 D's `base type definition` is not the `ur-type definition`
14852 * and is validly derived from B given the subset, as defined by this
14853 * constraint.
14854 */
14855 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14856 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14857 baseType, subset) == 0)) {
14858 return (0);
14859 }
14860 /*
14861 * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14862 * definition`.
14863 */
14864 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14865 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14866 return (0);
14867 }
14868 /*
14869 * 2.2.4 B's {variety} is union and D is validly derived from a type
14870 * definition in B's {member type definitions} given the subset, as
14871 * defined by this constraint.
14872 *
14873 * NOTE: This seems not to involve built-in types, since there is no
14874 * built-in Union Simple Type.
14875 */
14876 if (WXS_IS_UNION(baseType)) {
14877 xmlSchemaTypeLinkPtr cur;
14878
14879 cur = baseType->memberTypes;
14880 while (cur != NULL) {
14881 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14882 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14883 return(-1);
14884 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14885 type, cur->type, subset) == 0)
14886 {
14887 /*
14888 * It just has to be validly derived from at least one
14889 * member-type.
14890 */
14891 return (0);
14892 }
14893 cur = cur->next;
14894 }
14895 }
14896 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14897 }
14898
14899 /**
14900 * xmlSchemaCheckTypeDefCircularInternal:
14901 * @pctxt: the schema parser context
14902 * @ctxtType: the type definition
14903 * @ancestor: an ancestor of @ctxtType
14904 *
14905 * Checks st-props-correct (2) + ct-props-correct (3).
14906 * Circular type definitions are not allowed.
14907 *
14908 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14909 * circular, 0 otherwise.
14910 */
14911 static int
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxtType,xmlSchemaTypePtr ancestor)14912 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14913 xmlSchemaTypePtr ctxtType,
14914 xmlSchemaTypePtr ancestor)
14915 {
14916 int ret;
14917
14918 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14919 return (0);
14920
14921 if (ctxtType == ancestor) {
14922 xmlSchemaPCustomErr(pctxt,
14923 XML_SCHEMAP_ST_PROPS_CORRECT_2,
14924 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14925 "The definition is circular", NULL);
14926 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14927 }
14928 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14929 /*
14930 * Avoid infinite recursion on circular types not yet checked.
14931 */
14932 return (0);
14933 }
14934 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14935 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14936 ancestor->baseType);
14937 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14938 return (ret);
14939 }
14940
14941 /**
14942 * xmlSchemaCheckTypeDefCircular:
14943 * @item: the complex/simple type definition
14944 * @ctxt: the parser context
14945 * @name: the name
14946 *
14947 * Checks for circular type definitions.
14948 */
14949 static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,xmlSchemaParserCtxtPtr ctxt)14950 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14951 xmlSchemaParserCtxtPtr ctxt)
14952 {
14953 if ((item == NULL) ||
14954 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14955 (item->baseType == NULL))
14956 return;
14957 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14958 item->baseType);
14959 }
14960
14961 /*
14962 * Simple Type Definition Representation OK (src-simple-type) 4
14963 *
14964 * "4 Circular union type definition is disallowed. That is, if the
14965 * <union> alternative is chosen, there must not be any entries in the
14966 * memberTypes [attribute] at any depth which resolve to the component
14967 * corresponding to the <simpleType>."
14968 *
14969 * Note that this should work on the *representation* of a component,
14970 * thus assumes any union types in the member types not being yet
14971 * substituted. At this stage we need the variety of the types
14972 * to be already computed.
14973 */
14974 static int
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxType,xmlSchemaTypeLinkPtr members)14975 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14976 xmlSchemaTypePtr ctxType,
14977 xmlSchemaTypeLinkPtr members)
14978 {
14979 xmlSchemaTypeLinkPtr member;
14980 xmlSchemaTypePtr memberType;
14981
14982 member = members;
14983 while (member != NULL) {
14984 memberType = member->type;
14985 while ((memberType != NULL) &&
14986 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14987 if (memberType == ctxType) {
14988 xmlSchemaPCustomErr(pctxt,
14989 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14990 WXS_BASIC_CAST ctxType, NULL,
14991 "The union type definition is circular", NULL);
14992 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14993 }
14994 if ((WXS_IS_UNION(memberType)) &&
14995 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14996 {
14997 int res;
14998 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14999 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15000 ctxType,
15001 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15002 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15003 if (res != 0)
15004 return(res);
15005 }
15006 memberType = memberType->baseType;
15007 }
15008 member = member->next;
15009 }
15010 return(0);
15011 }
15012
15013 static int
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15014 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15015 xmlSchemaTypePtr type)
15016 {
15017 if (! WXS_IS_UNION(type))
15018 return(0);
15019 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15020 type->memberTypes));
15021 }
15022
15023 /**
15024 * xmlSchemaResolveTypeReferences:
15025 * @item: the complex/simple type definition
15026 * @ctxt: the parser context
15027 * @name: the name
15028 *
15029 * Resolves type definition references
15030 */
15031 static void
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,xmlSchemaParserCtxtPtr ctxt)15032 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15033 xmlSchemaParserCtxtPtr ctxt)
15034 {
15035 if (typeDef == NULL)
15036 return;
15037
15038 /*
15039 * Resolve the base type.
15040 */
15041 if (typeDef->baseType == NULL) {
15042 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15043 typeDef->base, typeDef->baseNs);
15044 if (typeDef->baseType == NULL) {
15045 xmlSchemaPResCompAttrErr(ctxt,
15046 XML_SCHEMAP_SRC_RESOLVE,
15047 WXS_BASIC_CAST typeDef, typeDef->node,
15048 "base", typeDef->base, typeDef->baseNs,
15049 XML_SCHEMA_TYPE_SIMPLE, NULL);
15050 return;
15051 }
15052 }
15053 if (WXS_IS_SIMPLE(typeDef)) {
15054 if (WXS_IS_UNION(typeDef)) {
15055 /*
15056 * Resolve the memberTypes.
15057 */
15058 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15059 return;
15060 } else if (WXS_IS_LIST(typeDef)) {
15061 /*
15062 * Resolve the itemType.
15063 */
15064 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15065
15066 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15067 typeDef->base, typeDef->baseNs);
15068
15069 if ((typeDef->subtypes == NULL) ||
15070 (! WXS_IS_SIMPLE(typeDef->subtypes)))
15071 {
15072 typeDef->subtypes = NULL;
15073 xmlSchemaPResCompAttrErr(ctxt,
15074 XML_SCHEMAP_SRC_RESOLVE,
15075 WXS_BASIC_CAST typeDef, typeDef->node,
15076 "itemType", typeDef->base, typeDef->baseNs,
15077 XML_SCHEMA_TYPE_SIMPLE, NULL);
15078 }
15079 }
15080 return;
15081 }
15082 }
15083 /*
15084 * The ball of letters below means, that if we have a particle
15085 * which has a QName-helper component as its {term}, we want
15086 * to resolve it...
15087 */
15088 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15089 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15090 XML_SCHEMA_TYPE_PARTICLE) &&
15091 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15092 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15093 XML_SCHEMA_EXTRA_QNAMEREF))
15094 {
15095 xmlSchemaQNameRefPtr ref =
15096 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15097 xmlSchemaModelGroupDefPtr groupDef;
15098
15099 /*
15100 * URGENT TODO: Test this.
15101 */
15102 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15103 /*
15104 * Resolve the MG definition reference.
15105 */
15106 groupDef =
15107 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15108 ref->itemType, ref->name, ref->targetNamespace);
15109 if (groupDef == NULL) {
15110 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15111 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15112 "ref", ref->name, ref->targetNamespace, ref->itemType,
15113 NULL);
15114 /* Remove the particle. */
15115 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15116 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15117 /* Remove the particle. */
15118 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15119 else {
15120 /*
15121 * Assign the MG definition's {model group} to the
15122 * particle's {term}.
15123 */
15124 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15125
15126 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15127 /*
15128 * SPEC cos-all-limited (1.2)
15129 * "1.2 the {term} property of a particle with
15130 * {max occurs}=1 which is part of a pair which constitutes
15131 * the {content type} of a complex type definition."
15132 */
15133 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15134 xmlSchemaCustomErr(ACTXT_CAST ctxt,
15135 /* TODO: error code */
15136 XML_SCHEMAP_COS_ALL_LIMITED,
15137 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15138 "The particle's {max occurs} must be 1, since the "
15139 "reference resolves to an 'all' model group",
15140 NULL, NULL);
15141 }
15142 }
15143 }
15144 }
15145 }
15146
15147
15148
15149 /**
15150 * xmlSchemaCheckSTPropsCorrect:
15151 * @ctxt: the schema parser context
15152 * @type: the simple type definition
15153 *
15154 * Checks st-props-correct.
15155 *
15156 * Returns 0 if the properties are correct,
15157 * if not, a positive error code and -1 on internal
15158 * errors.
15159 */
15160 static int
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)15161 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15162 xmlSchemaTypePtr type)
15163 {
15164 xmlSchemaTypePtr baseType = type->baseType;
15165 xmlChar *str = NULL;
15166
15167 /* STATE: error funcs converted. */
15168 /*
15169 * Schema Component Constraint: Simple Type Definition Properties Correct
15170 *
15171 * NOTE: This is somehow redundant, since we actually built a simple type
15172 * to have all the needed information; this acts as an self test.
15173 */
15174 /* Base type: If the datatype has been `derived` by `restriction`
15175 * then the Simple Type Definition component from which it is `derived`,
15176 * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15177 */
15178 if (baseType == NULL) {
15179 /*
15180 * TODO: Think about: "modulo the impact of Missing
15181 * Sub-components ($5.3)."
15182 */
15183 xmlSchemaPCustomErr(ctxt,
15184 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15185 WXS_BASIC_CAST type, NULL,
15186 "No base type existent", NULL);
15187 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15188
15189 }
15190 if (! WXS_IS_SIMPLE(baseType)) {
15191 xmlSchemaPCustomErr(ctxt,
15192 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15193 WXS_BASIC_CAST type, NULL,
15194 "The base type '%s' is not a simple type",
15195 xmlSchemaGetComponentQName(&str, baseType));
15196 FREE_AND_NULL(str)
15197 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15198 }
15199 if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15200 (WXS_IS_RESTRICTION(type) == 0) &&
15201 ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15202 (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15203 xmlSchemaPCustomErr(ctxt,
15204 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15205 WXS_BASIC_CAST type, NULL,
15206 "A type, derived by list or union, must have "
15207 "the simple ur-type definition as base type, not '%s'",
15208 xmlSchemaGetComponentQName(&str, baseType));
15209 FREE_AND_NULL(str)
15210 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15211 }
15212 /*
15213 * Variety: One of {atomic, list, union}.
15214 */
15215 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15216 (! WXS_IS_LIST(type))) {
15217 xmlSchemaPCustomErr(ctxt,
15218 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15219 WXS_BASIC_CAST type, NULL,
15220 "The variety is absent", NULL);
15221 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15222 }
15223 /* TODO: Finish this. Hmm, is this finished? */
15224
15225 /*
15226 * 3 The {final} of the {base type definition} must not contain restriction.
15227 */
15228 if (xmlSchemaTypeFinalContains(baseType,
15229 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15230 xmlSchemaPCustomErr(ctxt,
15231 XML_SCHEMAP_ST_PROPS_CORRECT_3,
15232 WXS_BASIC_CAST type, NULL,
15233 "The 'final' of its base type '%s' must not contain "
15234 "'restriction'",
15235 xmlSchemaGetComponentQName(&str, baseType));
15236 FREE_AND_NULL(str)
15237 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15238 }
15239
15240 /*
15241 * 2 All simple type definitions must be derived ultimately from the `simple
15242 * ur-type definition` (so circular definitions are disallowed). That is, it
15243 * must be possible to reach a built-in primitive datatype or the `simple
15244 * ur-type definition` by repeatedly following the {base type definition}.
15245 *
15246 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15247 */
15248 return (0);
15249 }
15250
15251 /**
15252 * xmlSchemaCheckCOSSTRestricts:
15253 * @ctxt: the schema parser context
15254 * @type: the simple type definition
15255 *
15256 * Schema Component Constraint:
15257 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15258
15259 * Checks if the given @type (simpleType) is derived validly by restriction.
15260 * STATUS:
15261 *
15262 * Returns -1 on internal errors, 0 if the type is validly derived,
15263 * a positive error code otherwise.
15264 */
15265 static int
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15266 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15267 xmlSchemaTypePtr type)
15268 {
15269 xmlChar *str = NULL;
15270
15271 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15272 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15273 "given type is not a user-derived simpleType");
15274 return (-1);
15275 }
15276
15277 if (WXS_IS_ATOMIC(type)) {
15278 xmlSchemaTypePtr primitive;
15279 /*
15280 * 1.1 The {base type definition} must be an atomic simple
15281 * type definition or a built-in primitive datatype.
15282 */
15283 if (! WXS_IS_ATOMIC(type->baseType)) {
15284 xmlSchemaPCustomErr(pctxt,
15285 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15286 WXS_BASIC_CAST type, NULL,
15287 "The base type '%s' is not an atomic simple type",
15288 xmlSchemaGetComponentQName(&str, type->baseType));
15289 FREE_AND_NULL(str)
15290 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15291 }
15292 /* 1.2 The {final} of the {base type definition} must not contain
15293 * restriction.
15294 */
15295 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15296 if (xmlSchemaTypeFinalContains(type->baseType,
15297 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15298 xmlSchemaPCustomErr(pctxt,
15299 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15300 WXS_BASIC_CAST type, NULL,
15301 "The final of its base type '%s' must not contain 'restriction'",
15302 xmlSchemaGetComponentQName(&str, type->baseType));
15303 FREE_AND_NULL(str)
15304 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15305 }
15306
15307 /*
15308 * 1.3.1 DF must be an allowed constraining facet for the {primitive
15309 * type definition}, as specified in the appropriate subsection of 3.2
15310 * Primitive datatypes.
15311 */
15312 if (type->facets != NULL) {
15313 xmlSchemaFacetPtr facet;
15314 int ok = 1;
15315
15316 primitive = xmlSchemaGetPrimitiveType(type);
15317 if (primitive == NULL) {
15318 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15319 "failed to get primitive type");
15320 return (-1);
15321 }
15322 facet = type->facets;
15323 do {
15324 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15325 ok = 0;
15326 xmlSchemaPIllegalFacetAtomicErr(pctxt,
15327 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15328 type, primitive, facet);
15329 }
15330 facet = facet->next;
15331 } while (facet != NULL);
15332 if (ok == 0)
15333 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15334 }
15335 /*
15336 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15337 * of the {base type definition} (call this BF),then the DF's {value}
15338 * must be a valid restriction of BF's {value} as defined in
15339 * [XML Schemas: Datatypes]."
15340 *
15341 * NOTE (1.3.2) Facet derivation constraints are currently handled in
15342 * xmlSchemaDeriveAndValidateFacets()
15343 */
15344 } else if (WXS_IS_LIST(type)) {
15345 xmlSchemaTypePtr itemType = NULL;
15346
15347 itemType = type->subtypes;
15348 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15349 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15350 "failed to evaluate the item type");
15351 return (-1);
15352 }
15353 if (WXS_IS_TYPE_NOT_FIXED(itemType))
15354 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15355 /*
15356 * 2.1 The {item type definition} must have a {variety} of atomic or
15357 * union (in which case all the {member type definitions}
15358 * must be atomic).
15359 */
15360 if ((! WXS_IS_ATOMIC(itemType)) &&
15361 (! WXS_IS_UNION(itemType))) {
15362 xmlSchemaPCustomErr(pctxt,
15363 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15364 WXS_BASIC_CAST type, NULL,
15365 "The item type '%s' does not have a variety of atomic or union",
15366 xmlSchemaGetComponentQName(&str, itemType));
15367 FREE_AND_NULL(str)
15368 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15369 } else if (WXS_IS_UNION(itemType)) {
15370 xmlSchemaTypeLinkPtr member;
15371
15372 member = itemType->memberTypes;
15373 while (member != NULL) {
15374 if (! WXS_IS_ATOMIC(member->type)) {
15375 xmlSchemaPCustomErr(pctxt,
15376 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15377 WXS_BASIC_CAST type, NULL,
15378 "The item type is a union type, but the "
15379 "member type '%s' of this item type is not atomic",
15380 xmlSchemaGetComponentQName(&str, member->type));
15381 FREE_AND_NULL(str)
15382 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15383 }
15384 member = member->next;
15385 }
15386 }
15387
15388 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15389 xmlSchemaFacetPtr facet;
15390 /*
15391 * This is the case if we have: <simpleType><list ..
15392 */
15393 /*
15394 * 2.3.1
15395 * 2.3.1.1 The {final} of the {item type definition} must not
15396 * contain list.
15397 */
15398 if (xmlSchemaTypeFinalContains(itemType,
15399 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15400 xmlSchemaPCustomErr(pctxt,
15401 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15402 WXS_BASIC_CAST type, NULL,
15403 "The final of its item type '%s' must not contain 'list'",
15404 xmlSchemaGetComponentQName(&str, itemType));
15405 FREE_AND_NULL(str)
15406 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15407 }
15408 /*
15409 * 2.3.1.2 The {facets} must only contain the whiteSpace
15410 * facet component.
15411 * OPTIMIZE TODO: the S4S already disallows any facet
15412 * to be specified.
15413 */
15414 if (type->facets != NULL) {
15415 facet = type->facets;
15416 do {
15417 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15418 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15419 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15420 type, facet);
15421 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15422 }
15423 facet = facet->next;
15424 } while (facet != NULL);
15425 }
15426 /*
15427 * MAYBE TODO: (Hmm, not really) Datatypes states:
15428 * A `list` datatype can be `derived` from an `atomic` datatype
15429 * whose `lexical space` allows space (such as string or anyURI)or
15430 * a `union` datatype any of whose {member type definitions}'s
15431 * `lexical space` allows space.
15432 */
15433 } else {
15434 /*
15435 * This is the case if we have: <simpleType><restriction ...
15436 * I.e. the variety of "list" is inherited.
15437 */
15438 /*
15439 * 2.3.2
15440 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15441 */
15442 if (! WXS_IS_LIST(type->baseType)) {
15443 xmlSchemaPCustomErr(pctxt,
15444 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15445 WXS_BASIC_CAST type, NULL,
15446 "The base type '%s' must be a list type",
15447 xmlSchemaGetComponentQName(&str, type->baseType));
15448 FREE_AND_NULL(str)
15449 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15450 }
15451 /*
15452 * 2.3.2.2 The {final} of the {base type definition} must not
15453 * contain restriction.
15454 */
15455 if (xmlSchemaTypeFinalContains(type->baseType,
15456 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15457 xmlSchemaPCustomErr(pctxt,
15458 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15459 WXS_BASIC_CAST type, NULL,
15460 "The 'final' of the base type '%s' must not contain 'restriction'",
15461 xmlSchemaGetComponentQName(&str, type->baseType));
15462 FREE_AND_NULL(str)
15463 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15464 }
15465 /*
15466 * 2.3.2.3 The {item type definition} must be validly derived
15467 * from the {base type definition}'s {item type definition} given
15468 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15469 */
15470 {
15471 xmlSchemaTypePtr baseItemType;
15472
15473 baseItemType = type->baseType->subtypes;
15474 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15475 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15476 "failed to eval the item type of a base type");
15477 return (-1);
15478 }
15479 if ((itemType != baseItemType) &&
15480 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15481 baseItemType, 0) != 0)) {
15482 xmlChar *strBIT = NULL, *strBT = NULL;
15483 xmlSchemaPCustomErrExt(pctxt,
15484 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15485 WXS_BASIC_CAST type, NULL,
15486 "The item type '%s' is not validly derived from "
15487 "the item type '%s' of the base type '%s'",
15488 xmlSchemaGetComponentQName(&str, itemType),
15489 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15490 xmlSchemaGetComponentQName(&strBT, type->baseType));
15491
15492 FREE_AND_NULL(str)
15493 FREE_AND_NULL(strBIT)
15494 FREE_AND_NULL(strBT)
15495 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15496 }
15497 }
15498
15499 if (type->facets != NULL) {
15500 xmlSchemaFacetPtr facet;
15501 int ok = 1;
15502 /*
15503 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15504 * and enumeration facet components are allowed among the {facets}.
15505 */
15506 facet = type->facets;
15507 do {
15508 switch (facet->type) {
15509 case XML_SCHEMA_FACET_LENGTH:
15510 case XML_SCHEMA_FACET_MINLENGTH:
15511 case XML_SCHEMA_FACET_MAXLENGTH:
15512 case XML_SCHEMA_FACET_WHITESPACE:
15513 /*
15514 * TODO: 2.5.1.2 List datatypes
15515 * The value of `whiteSpace` is fixed to the value collapse.
15516 */
15517 case XML_SCHEMA_FACET_PATTERN:
15518 case XML_SCHEMA_FACET_ENUMERATION:
15519 break;
15520 default: {
15521 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15522 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15523 type, facet);
15524 /*
15525 * We could return, but it's nicer to report all
15526 * invalid facets.
15527 */
15528 ok = 0;
15529 }
15530 }
15531 facet = facet->next;
15532 } while (facet != NULL);
15533 if (ok == 0)
15534 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15535 /*
15536 * SPEC (2.3.2.5) (same as 1.3.2)
15537 *
15538 * NOTE (2.3.2.5) This is currently done in
15539 * xmlSchemaDeriveAndValidateFacets()
15540 */
15541 }
15542 }
15543 } else if (WXS_IS_UNION(type)) {
15544 /*
15545 * 3.1 The {member type definitions} must all have {variety} of
15546 * atomic or list.
15547 */
15548 xmlSchemaTypeLinkPtr member;
15549
15550 member = type->memberTypes;
15551 while (member != NULL) {
15552 if (WXS_IS_TYPE_NOT_FIXED(member->type))
15553 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15554
15555 if ((! WXS_IS_ATOMIC(member->type)) &&
15556 (! WXS_IS_LIST(member->type))) {
15557 xmlSchemaPCustomErr(pctxt,
15558 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15559 WXS_BASIC_CAST type, NULL,
15560 "The member type '%s' is neither an atomic, nor a list type",
15561 xmlSchemaGetComponentQName(&str, member->type));
15562 FREE_AND_NULL(str)
15563 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15564 }
15565 member = member->next;
15566 }
15567 /*
15568 * 3.3.1 If the {base type definition} is the `simple ur-type
15569 * definition`
15570 */
15571 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15572 /*
15573 * 3.3.1.1 All of the {member type definitions} must have a
15574 * {final} which does not contain union.
15575 */
15576 member = type->memberTypes;
15577 while (member != NULL) {
15578 if (xmlSchemaTypeFinalContains(member->type,
15579 XML_SCHEMAS_TYPE_FINAL_UNION)) {
15580 xmlSchemaPCustomErr(pctxt,
15581 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15582 WXS_BASIC_CAST type, NULL,
15583 "The 'final' of member type '%s' contains 'union'",
15584 xmlSchemaGetComponentQName(&str, member->type));
15585 FREE_AND_NULL(str)
15586 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15587 }
15588 member = member->next;
15589 }
15590 /*
15591 * 3.3.1.2 The {facets} must be empty.
15592 */
15593 if (type->facetSet != NULL) {
15594 xmlSchemaPCustomErr(pctxt,
15595 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15596 WXS_BASIC_CAST type, NULL,
15597 "No facets allowed", NULL);
15598 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15599 }
15600 } else {
15601 /*
15602 * 3.3.2.1 The {base type definition} must have a {variety} of union.
15603 * I.e. the variety of "list" is inherited.
15604 */
15605 if (! WXS_IS_UNION(type->baseType)) {
15606 xmlSchemaPCustomErr(pctxt,
15607 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15608 WXS_BASIC_CAST type, NULL,
15609 "The base type '%s' is not a union type",
15610 xmlSchemaGetComponentQName(&str, type->baseType));
15611 FREE_AND_NULL(str)
15612 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15613 }
15614 /*
15615 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15616 */
15617 if (xmlSchemaTypeFinalContains(type->baseType,
15618 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15619 xmlSchemaPCustomErr(pctxt,
15620 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15621 WXS_BASIC_CAST type, NULL,
15622 "The 'final' of its base type '%s' must not contain 'restriction'",
15623 xmlSchemaGetComponentQName(&str, type->baseType));
15624 FREE_AND_NULL(str)
15625 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15626 }
15627 /*
15628 * 3.3.2.3 The {member type definitions}, in order, must be validly
15629 * derived from the corresponding type definitions in the {base
15630 * type definition}'s {member type definitions} given the empty set,
15631 * as defined in Type Derivation OK (Simple) ($3.14.6).
15632 */
15633 {
15634 xmlSchemaTypeLinkPtr baseMember;
15635
15636 /*
15637 * OPTIMIZE: if the type is restricting, it has no local defined
15638 * member types and inherits the member types of the base type;
15639 * thus a check for equality can be skipped.
15640 */
15641 /*
15642 * Even worse: I cannot see a scenario where a restricting
15643 * union simple type can have other member types as the member
15644 * types of it's base type. This check seems not necessary with
15645 * respect to the derivation process in libxml2.
15646 * But necessary if constructing types with an API.
15647 */
15648 if (type->memberTypes != NULL) {
15649 member = type->memberTypes;
15650 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15651 if ((member == NULL) && (baseMember != NULL)) {
15652 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15653 "different number of member types in base");
15654 }
15655 while (member != NULL) {
15656 if (baseMember == NULL) {
15657 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15658 "different number of member types in base");
15659 } else if ((member->type != baseMember->type) &&
15660 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15661 member->type, baseMember->type, 0) != 0)) {
15662 xmlChar *strBMT = NULL, *strBT = NULL;
15663
15664 xmlSchemaPCustomErrExt(pctxt,
15665 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15666 WXS_BASIC_CAST type, NULL,
15667 "The member type %s is not validly "
15668 "derived from its corresponding member "
15669 "type %s of the base type %s",
15670 xmlSchemaGetComponentQName(&str, member->type),
15671 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15672 xmlSchemaGetComponentQName(&strBT, type->baseType));
15673 FREE_AND_NULL(str)
15674 FREE_AND_NULL(strBMT)
15675 FREE_AND_NULL(strBT)
15676 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15677 }
15678 member = member->next;
15679 if (baseMember != NULL)
15680 baseMember = baseMember->next;
15681 }
15682 }
15683 }
15684 /*
15685 * 3.3.2.4 Only pattern and enumeration facet components are
15686 * allowed among the {facets}.
15687 */
15688 if (type->facets != NULL) {
15689 xmlSchemaFacetPtr facet;
15690 int ok = 1;
15691
15692 facet = type->facets;
15693 do {
15694 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15695 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15696 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15697 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15698 type, facet);
15699 ok = 0;
15700 }
15701 facet = facet->next;
15702 } while (facet != NULL);
15703 if (ok == 0)
15704 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15705
15706 }
15707 /*
15708 * SPEC (3.3.2.5) (same as 1.3.2)
15709 *
15710 * NOTE (3.3.2.5) This is currently done in
15711 * xmlSchemaDeriveAndValidateFacets()
15712 */
15713 }
15714 }
15715
15716 return (0);
15717 }
15718
15719 /**
15720 * xmlSchemaCheckSRCSimpleType:
15721 * @ctxt: the schema parser context
15722 * @type: the simple type definition
15723 *
15724 * Checks crc-simple-type constraints.
15725 *
15726 * Returns 0 if the constraints are satisfied,
15727 * if not a positive error code and -1 on internal
15728 * errors.
15729 */
15730 #if 0
15731 static int
15732 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15733 xmlSchemaTypePtr type)
15734 {
15735 /*
15736 * src-simple-type.1 The corresponding simple type definition, if any,
15737 * must satisfy the conditions set out in Constraints on Simple Type
15738 * Definition Schema Components ($3.14.6).
15739 */
15740 if (WXS_IS_RESTRICTION(type)) {
15741 /*
15742 * src-simple-type.2 "If the <restriction> alternative is chosen,
15743 * either it must have a base [attribute] or a <simpleType> among its
15744 * [children], but not both."
15745 * NOTE: This is checked in the parse function of <restriction>.
15746 */
15747 /*
15748 *
15749 */
15750 } else if (WXS_IS_LIST(type)) {
15751 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15752 * an itemType [attribute] or a <simpleType> among its [children],
15753 * but not both."
15754 *
15755 * NOTE: This is checked in the parse function of <list>.
15756 */
15757 } else if (WXS_IS_UNION(type)) {
15758 /*
15759 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15760 */
15761 }
15762 return (0);
15763 }
15764 #endif
15765
15766 static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)15767 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15768 {
15769 if (ctxt->vctxt == NULL) {
15770 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15771 if (ctxt->vctxt == NULL) {
15772 xmlSchemaPErr(ctxt, NULL,
15773 XML_SCHEMAP_INTERNAL,
15774 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15775 "failed to create a temp. validation context.\n",
15776 NULL, NULL);
15777 return (-1);
15778 }
15779 /* TODO: Pass user data. */
15780 xmlSchemaSetValidErrors(ctxt->vctxt,
15781 ctxt->error, ctxt->warning, ctxt->errCtxt);
15782 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15783 ctxt->serror, ctxt->errCtxt);
15784 }
15785 return (0);
15786 }
15787
15788 static int
15789 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15790 xmlNodePtr node,
15791 xmlSchemaTypePtr type,
15792 const xmlChar *value,
15793 xmlSchemaValPtr *retVal,
15794 int fireErrors,
15795 int normalize,
15796 int isNormalized);
15797
15798 /**
15799 * xmlSchemaParseCheckCOSValidDefault:
15800 * @pctxt: the schema parser context
15801 * @type: the simple type definition
15802 * @value: the default value
15803 * @node: an optional node (the holder of the value)
15804 *
15805 * Schema Component Constraint: Element Default Valid (Immediate)
15806 * (cos-valid-default)
15807 * This will be used by the parser only. For the validator there's
15808 * an other version.
15809 *
15810 * Returns 0 if the constraints are satisfied,
15811 * if not, a positive error code and -1 on internal
15812 * errors.
15813 */
15814 static int
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)15815 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15816 xmlNodePtr node,
15817 xmlSchemaTypePtr type,
15818 const xmlChar *value,
15819 xmlSchemaValPtr *val)
15820 {
15821 int ret = 0;
15822
15823 /*
15824 * cos-valid-default:
15825 * Schema Component Constraint: Element Default Valid (Immediate)
15826 * For a string to be a valid default with respect to a type
15827 * definition the appropriate case among the following must be true:
15828 */
15829 if WXS_IS_COMPLEX(type) {
15830 /*
15831 * Complex type.
15832 *
15833 * SPEC (2.1) "its {content type} must be a simple type definition
15834 * or mixed."
15835 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15836 * type}'s particle must be `emptiable` as defined by
15837 * Particle Emptiable ($3.9.6)."
15838 */
15839 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15840 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15841 /* NOTE that this covers (2.2.2) as well. */
15842 xmlSchemaPCustomErr(pctxt,
15843 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15844 WXS_BASIC_CAST type, type->node,
15845 "For a string to be a valid default, the type definition "
15846 "must be a simple type or a complex type with mixed content "
15847 "and a particle emptiable", NULL);
15848 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15849 }
15850 }
15851 /*
15852 * 1 If the type definition is a simple type definition, then the string
15853 * must be `valid` with respect to that definition as defined by String
15854 * Valid ($3.14.4).
15855 *
15856 * AND
15857 *
15858 * 2.2.1 If the {content type} is a simple type definition, then the
15859 * string must be `valid` with respect to that simple type definition
15860 * as defined by String Valid ($3.14.4).
15861 */
15862 if (WXS_IS_SIMPLE(type))
15863 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15864 type, value, val, 1, 1, 0);
15865 else if (WXS_HAS_SIMPLE_CONTENT(type))
15866 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15867 type->contentTypeDef, value, val, 1, 1, 0);
15868 else
15869 return (ret);
15870
15871 if (ret < 0) {
15872 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15873 "calling xmlSchemaVCheckCVCSimpleType()");
15874 }
15875
15876 return (ret);
15877 }
15878
15879 /**
15880 * xmlSchemaCheckCTPropsCorrect:
15881 * @ctxt: the schema parser context
15882 * @type: the complex type definition
15883 *
15884 *.(4.6) Constraints on Complex Type Definition Schema Components
15885 * Schema Component Constraint:
15886 * Complex Type Definition Properties Correct (ct-props-correct)
15887 * STATUS: (seems) complete
15888 *
15889 * Returns 0 if the constraints are satisfied, a positive
15890 * error code if not and -1 if an internal error occurred.
15891 */
15892 static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15893 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15894 xmlSchemaTypePtr type)
15895 {
15896 /*
15897 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15898 *
15899 * SPEC (1) "The values of the properties of a complex type definition must
15900 * be as described in the property tableau in The Complex Type Definition
15901 * Schema Component ($3.4.1), modulo the impact of Missing
15902 * Sub-components ($5.3)."
15903 */
15904 if ((type->baseType != NULL) &&
15905 (WXS_IS_SIMPLE(type->baseType)) &&
15906 (WXS_IS_EXTENSION(type) == 0)) {
15907 /*
15908 * SPEC (2) "If the {base type definition} is a simple type definition,
15909 * the {derivation method} must be extension."
15910 */
15911 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15912 XML_SCHEMAP_SRC_CT_1,
15913 NULL, WXS_BASIC_CAST type,
15914 "If the base type is a simple type, the derivation method must be "
15915 "'extension'", NULL, NULL);
15916 return (XML_SCHEMAP_SRC_CT_1);
15917 }
15918 /*
15919 * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15920 * definition`. That is, it must be possible to reach the `ur-type
15921 * definition` by repeatedly following the {base type definition}."
15922 *
15923 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15924 */
15925 /*
15926 * NOTE that (4) and (5) need the following:
15927 * - attribute uses need to be already inherited (apply attr. prohibitions)
15928 * - attribute group references need to be expanded already
15929 * - simple types need to be typefixed already
15930 */
15931 if (type->attrUses &&
15932 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15933 {
15934 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15935 xmlSchemaAttributeUsePtr use, tmp;
15936 int i, j, hasId = 0;
15937
15938 for (i = uses->nbItems -1; i >= 0; i--) {
15939 use = uses->items[i];
15940
15941 /*
15942 * SPEC ct-props-correct
15943 * (4) "Two distinct attribute declarations in the
15944 * {attribute uses} must not have identical {name}s and
15945 * {target namespace}s."
15946 */
15947 if (i > 0) {
15948 for (j = i -1; j >= 0; j--) {
15949 tmp = uses->items[j];
15950 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15951 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15952 (WXS_ATTRUSE_DECL_TNS(use) ==
15953 WXS_ATTRUSE_DECL_TNS(tmp)))
15954 {
15955 xmlChar *str = NULL;
15956
15957 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15958 XML_SCHEMAP_AG_PROPS_CORRECT,
15959 NULL, WXS_BASIC_CAST type,
15960 "Duplicate %s",
15961 xmlSchemaGetComponentDesignation(&str, use),
15962 NULL);
15963 FREE_AND_NULL(str);
15964 /*
15965 * Remove the duplicate.
15966 */
15967 if (xmlSchemaItemListRemove(uses, i) == -1)
15968 goto exit_failure;
15969 goto next_use;
15970 }
15971 }
15972 }
15973 /*
15974 * SPEC ct-props-correct
15975 * (5) "Two distinct attribute declarations in the
15976 * {attribute uses} must not have {type definition}s which
15977 * are or are derived from ID."
15978 */
15979 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15980 if (xmlSchemaIsDerivedFromBuiltInType(
15981 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15982 {
15983 if (hasId) {
15984 xmlChar *str = NULL;
15985
15986 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15987 XML_SCHEMAP_AG_PROPS_CORRECT,
15988 NULL, WXS_BASIC_CAST type,
15989 "There must not exist more than one attribute "
15990 "declaration of type 'xs:ID' "
15991 "(or derived from 'xs:ID'). The %s violates this "
15992 "constraint",
15993 xmlSchemaGetComponentDesignation(&str, use),
15994 NULL);
15995 FREE_AND_NULL(str);
15996 if (xmlSchemaItemListRemove(uses, i) == -1)
15997 goto exit_failure;
15998 }
15999
16000 hasId = 1;
16001 }
16002 }
16003 next_use: {}
16004 }
16005 }
16006 return (0);
16007 exit_failure:
16008 return(-1);
16009 }
16010
16011 static int
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,xmlSchemaTypePtr typeB)16012 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16013 xmlSchemaTypePtr typeB)
16014 {
16015 /*
16016 * TODO: This should implement component-identity
16017 * in the future.
16018 */
16019 if ((typeA == NULL) || (typeB == NULL))
16020 return (0);
16021 return (typeA == typeB);
16022 }
16023
16024 /**
16025 * xmlSchemaCheckCOSCTDerivedOK:
16026 * @ctxt: the schema parser context
16027 * @type: the to-be derived complex type definition
16028 * @baseType: the base complex type definition
16029 * @set: the given set
16030 *
16031 * Schema Component Constraint:
16032 * Type Derivation OK (Complex) (cos-ct-derived-ok)
16033 *
16034 * STATUS: completed
16035 *
16036 * Returns 0 if the constraints are satisfied, or 1
16037 * if not.
16038 */
16039 static int
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16040 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16041 xmlSchemaTypePtr type,
16042 xmlSchemaTypePtr baseType,
16043 int set)
16044 {
16045 int equal = xmlSchemaAreEqualTypes(type, baseType);
16046 /* TODO: Error codes. */
16047 /*
16048 * SPEC "For a complex type definition (call it D, for derived)
16049 * to be validly derived from a type definition (call this
16050 * B, for base) given a subset of {extension, restriction}
16051 * all of the following must be true:"
16052 */
16053 if (! equal) {
16054 /*
16055 * SPEC (1) "If B and D are not the same type definition, then the
16056 * {derivation method} of D must not be in the subset."
16057 */
16058 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16059 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16060 return (1);
16061 } else {
16062 /*
16063 * SPEC (2.1) "B and D must be the same type definition."
16064 */
16065 return (0);
16066 }
16067 /*
16068 * SPEC (2.2) "B must be D's {base type definition}."
16069 */
16070 if (type->baseType == baseType)
16071 return (0);
16072 /*
16073 * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16074 * definition`."
16075 */
16076 if (WXS_IS_ANYTYPE(type->baseType))
16077 return (1);
16078
16079 if (WXS_IS_COMPLEX(type->baseType)) {
16080 /*
16081 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16082 * must be validly derived from B given the subset as defined by this
16083 * constraint."
16084 */
16085 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16086 baseType, set));
16087 } else {
16088 /*
16089 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16090 * must be validly derived from B given the subset as defined in Type
16091 * Derivation OK (Simple) ($3.14.6).
16092 */
16093 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16094 baseType, set));
16095 }
16096 }
16097
16098 /**
16099 * xmlSchemaCheckCOSDerivedOK:
16100 * @type: the derived simple type definition
16101 * @baseType: the base type definition
16102 *
16103 * Calls:
16104 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16105 *
16106 * Checks whether @type can be validly derived from @baseType.
16107 *
16108 * Returns 0 on success, an positive error code otherwise.
16109 */
16110 static int
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16111 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16112 xmlSchemaTypePtr type,
16113 xmlSchemaTypePtr baseType,
16114 int set)
16115 {
16116 if (WXS_IS_SIMPLE(type))
16117 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16118 else
16119 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16120 }
16121
16122 /**
16123 * xmlSchemaCheckCOSCTExtends:
16124 * @ctxt: the schema parser context
16125 * @type: the complex type definition
16126 *
16127 * (3.4.6) Constraints on Complex Type Definition Schema Components
16128 * Schema Component Constraint:
16129 * Derivation Valid (Extension) (cos-ct-extends)
16130 *
16131 * STATUS:
16132 * missing:
16133 * (1.5)
16134 * (1.4.3.2.2.2) "Particle Valid (Extension)"
16135 *
16136 * Returns 0 if the constraints are satisfied, a positive
16137 * error code if not and -1 if an internal error occurred.
16138 */
16139 static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16140 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16141 xmlSchemaTypePtr type)
16142 {
16143 xmlSchemaTypePtr base = type->baseType;
16144 /*
16145 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16146 * temporarily only.
16147 */
16148 /*
16149 * SPEC (1) "If the {base type definition} is a complex type definition,
16150 * then all of the following must be true:"
16151 */
16152 if (WXS_IS_COMPLEX(base)) {
16153 /*
16154 * SPEC (1.1) "The {final} of the {base type definition} must not
16155 * contain extension."
16156 */
16157 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16158 xmlSchemaPCustomErr(ctxt,
16159 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16160 WXS_BASIC_CAST type, NULL,
16161 "The 'final' of the base type definition "
16162 "contains 'extension'", NULL);
16163 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16164 }
16165
16166 /*
16167 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16168 * since they are automatically satisfied through the
16169 * inheriting mechanism.
16170 * Note that even if redefining components, the inheriting mechanism
16171 * is used.
16172 */
16173 #if 0
16174 /*
16175 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16176 * uses}
16177 * of the complex type definition itself, that is, for every attribute
16178 * use in the {attribute uses} of the {base type definition}, there
16179 * must be an attribute use in the {attribute uses} of the complex
16180 * type definition itself whose {attribute declaration} has the same
16181 * {name}, {target namespace} and {type definition} as its attribute
16182 * declaration"
16183 */
16184 if (base->attrUses != NULL) {
16185 int i, j, found;
16186 xmlSchemaAttributeUsePtr use, buse;
16187
16188 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16189 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16190 found = 0;
16191 if (type->attrUses != NULL) {
16192 use = (WXS_LIST_CAST type->attrUses)->items[j];
16193 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16194 {
16195 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16196 WXS_ATTRUSE_DECL_NAME(buse)) &&
16197 (WXS_ATTRUSE_DECL_TNS(use) ==
16198 WXS_ATTRUSE_DECL_TNS(buse)) &&
16199 (WXS_ATTRUSE_TYPEDEF(use) ==
16200 WXS_ATTRUSE_TYPEDEF(buse))
16201 {
16202 found = 1;
16203 break;
16204 }
16205 }
16206 }
16207 if (! found) {
16208 xmlChar *str = NULL;
16209
16210 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16211 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16212 NULL, WXS_BASIC_CAST type,
16213 /*
16214 * TODO: The report does not indicate that also the
16215 * type needs to be the same.
16216 */
16217 "This type is missing a matching correspondent "
16218 "for its {base type}'s %s in its {attribute uses}",
16219 xmlSchemaGetComponentDesignation(&str,
16220 buse->children),
16221 NULL);
16222 FREE_AND_NULL(str)
16223 }
16224 }
16225 }
16226 /*
16227 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16228 * definition must also have one, and the base type definition's
16229 * {attribute wildcard}'s {namespace constraint} must be a subset
16230 * of the complex type definition's {attribute wildcard}'s {namespace
16231 * constraint}, as defined by Wildcard Subset ($3.10.6)."
16232 */
16233
16234 /*
16235 * MAYBE TODO: Enable if ever needed. But this will be needed only
16236 * if created the type via a schema construction API.
16237 */
16238 if (base->attributeWildcard != NULL) {
16239 if (type->attributeWildcard == NULL) {
16240 xmlChar *str = NULL;
16241
16242 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16243 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16244 NULL, type,
16245 "The base %s has an attribute wildcard, "
16246 "but this type is missing an attribute wildcard",
16247 xmlSchemaGetComponentDesignation(&str, base));
16248 FREE_AND_NULL(str)
16249
16250 } else if (xmlSchemaCheckCOSNSSubset(
16251 base->attributeWildcard, type->attributeWildcard))
16252 {
16253 xmlChar *str = NULL;
16254
16255 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16256 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16257 NULL, type,
16258 "The attribute wildcard is not a valid "
16259 "superset of the one in the base %s",
16260 xmlSchemaGetComponentDesignation(&str, base));
16261 FREE_AND_NULL(str)
16262 }
16263 }
16264 #endif
16265 /*
16266 * SPEC (1.4) "One of the following must be true:"
16267 */
16268 if ((type->contentTypeDef != NULL) &&
16269 (type->contentTypeDef == base->contentTypeDef)) {
16270 /*
16271 * SPEC (1.4.1) "The {content type} of the {base type definition}
16272 * and the {content type} of the complex type definition itself
16273 * must be the same simple type definition"
16274 * PASS
16275 */
16276 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16277 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16278 /*
16279 * SPEC (1.4.2) "The {content type} of both the {base type
16280 * definition} and the complex type definition itself must
16281 * be empty."
16282 * PASS
16283 */
16284 } else {
16285 /*
16286 * SPEC (1.4.3) "All of the following must be true:"
16287 */
16288 if (type->subtypes == NULL) {
16289 /*
16290 * SPEC 1.4.3.1 The {content type} of the complex type
16291 * definition itself must specify a particle.
16292 */
16293 xmlSchemaPCustomErr(ctxt,
16294 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16295 WXS_BASIC_CAST type, NULL,
16296 "The content type must specify a particle", NULL);
16297 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16298 }
16299 /*
16300 * SPEC (1.4.3.2) "One of the following must be true:"
16301 */
16302 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16303 /*
16304 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16305 * definition} must be empty.
16306 * PASS
16307 */
16308 } else {
16309 /*
16310 * SPEC (1.4.3.2.2) "All of the following must be true:"
16311 */
16312 if ((type->contentType != base->contentType) ||
16313 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16314 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16315 /*
16316 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16317 * or both must be element-only."
16318 */
16319 xmlSchemaPCustomErr(ctxt,
16320 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16321 WXS_BASIC_CAST type, NULL,
16322 "The content type of both, the type and its base "
16323 "type, must either 'mixed' or 'element-only'", NULL);
16324 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16325 }
16326 /*
16327 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16328 * complex type definition must be a `valid extension`
16329 * of the {base type definition}'s particle, as defined
16330 * in Particle Valid (Extension) ($3.9.6)."
16331 *
16332 * NOTE that we won't check "Particle Valid (Extension)",
16333 * since it is ensured by the derivation process in
16334 * xmlSchemaTypeFixup(). We need to implement this when heading
16335 * for a construction API
16336 * TODO: !! This is needed to be checked if redefining a type !!
16337 */
16338 }
16339 /*
16340 * URGENT TODO (1.5)
16341 */
16342 }
16343 } else {
16344 /*
16345 * SPEC (2) "If the {base type definition} is a simple type definition,
16346 * then all of the following must be true:"
16347 */
16348 if (type->contentTypeDef != base) {
16349 /*
16350 * SPEC (2.1) "The {content type} must be the same simple type
16351 * definition."
16352 */
16353 xmlSchemaPCustomErr(ctxt,
16354 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16355 WXS_BASIC_CAST type, NULL,
16356 "The content type must be the simple base type", NULL);
16357 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16358 }
16359 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16360 /*
16361 * SPEC (2.2) "The {final} of the {base type definition} must not
16362 * contain extension"
16363 * NOTE that this is the same as (1.1).
16364 */
16365 xmlSchemaPCustomErr(ctxt,
16366 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16367 WXS_BASIC_CAST type, NULL,
16368 "The 'final' of the base type definition "
16369 "contains 'extension'", NULL);
16370 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16371 }
16372 }
16373 return (0);
16374 }
16375
16376 /**
16377 * xmlSchemaCheckDerivationOKRestriction:
16378 * @ctxt: the schema parser context
16379 * @type: the complex type definition
16380 *
16381 * (3.4.6) Constraints on Complex Type Definition Schema Components
16382 * Schema Component Constraint:
16383 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16384 *
16385 * STATUS:
16386 * missing:
16387 * (5.4.2) ???
16388 *
16389 * ATTENTION:
16390 * In XML Schema 1.1 this will be:
16391 * Validation Rule: Checking complex type subsumption
16392 *
16393 * Returns 0 if the constraints are satisfied, a positive
16394 * error code if not and -1 if an internal error occurred.
16395 */
16396 static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16397 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16398 xmlSchemaTypePtr type)
16399 {
16400 xmlSchemaTypePtr base;
16401
16402 /*
16403 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16404 * temporarily only.
16405 */
16406 base = type->baseType;
16407 if (! WXS_IS_COMPLEX(base)) {
16408 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16409 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16410 type->node, WXS_BASIC_CAST type,
16411 "The base type must be a complex type", NULL, NULL);
16412 return(ctxt->err);
16413 }
16414 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16415 /*
16416 * SPEC (1) "The {base type definition} must be a complex type
16417 * definition whose {final} does not contain restriction."
16418 */
16419 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16420 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16421 type->node, WXS_BASIC_CAST type,
16422 "The 'final' of the base type definition "
16423 "contains 'restriction'", NULL, NULL);
16424 return (ctxt->err);
16425 }
16426 /*
16427 * SPEC (2), (3) and (4)
16428 * Those are handled in a separate function, since the
16429 * same constraints are needed for redefinition of
16430 * attribute groups as well.
16431 */
16432 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16433 XML_SCHEMA_ACTION_DERIVE,
16434 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16435 type->attrUses, base->attrUses,
16436 type->attributeWildcard,
16437 base->attributeWildcard) == -1)
16438 {
16439 return(-1);
16440 }
16441 /*
16442 * SPEC (5) "One of the following must be true:"
16443 */
16444 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16445 /*
16446 * SPEC (5.1) "The {base type definition} must be the
16447 * `ur-type definition`."
16448 * PASS
16449 */
16450 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16451 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16452 /*
16453 * SPEC (5.2.1) "The {content type} of the complex type definition
16454 * must be a simple type definition"
16455 *
16456 * SPEC (5.2.2) "One of the following must be true:"
16457 */
16458 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16459 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16460 {
16461 int err;
16462 /*
16463 * SPEC (5.2.2.1) "The {content type} of the {base type
16464 * definition} must be a simple type definition from which
16465 * the {content type} is validly derived given the empty
16466 * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16467 *
16468 * ATTENTION TODO: This seems not needed if the type implicitly
16469 * derived from the base type.
16470 *
16471 */
16472 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16473 type->contentTypeDef, base->contentTypeDef, 0);
16474 if (err != 0) {
16475 xmlChar *strA = NULL, *strB = NULL;
16476
16477 if (err == -1)
16478 return(-1);
16479 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16480 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16481 NULL, WXS_BASIC_CAST type,
16482 "The {content type} %s is not validly derived from the "
16483 "base type's {content type} %s",
16484 xmlSchemaGetComponentDesignation(&strA,
16485 type->contentTypeDef),
16486 xmlSchemaGetComponentDesignation(&strB,
16487 base->contentTypeDef));
16488 FREE_AND_NULL(strA);
16489 FREE_AND_NULL(strB);
16490 return(ctxt->err);
16491 }
16492 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16493 (xmlSchemaIsParticleEmptiable(
16494 (xmlSchemaParticlePtr) base->subtypes))) {
16495 /*
16496 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16497 * and have a particle which is `emptiable` as defined in
16498 * Particle Emptiable ($3.9.6)."
16499 * PASS
16500 */
16501 } else {
16502 xmlSchemaPCustomErr(ctxt,
16503 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16504 WXS_BASIC_CAST type, NULL,
16505 "The content type of the base type must be either "
16506 "a simple type or 'mixed' and an emptiable particle", NULL);
16507 return (ctxt->err);
16508 }
16509 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16510 /*
16511 * SPEC (5.3.1) "The {content type} of the complex type itself must
16512 * be empty"
16513 */
16514 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16515 /*
16516 * SPEC (5.3.2.1) "The {content type} of the {base type
16517 * definition} must also be empty."
16518 * PASS
16519 */
16520 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16521 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16522 xmlSchemaIsParticleEmptiable(
16523 (xmlSchemaParticlePtr) base->subtypes)) {
16524 /*
16525 * SPEC (5.3.2.2) "The {content type} of the {base type
16526 * definition} must be elementOnly or mixed and have a particle
16527 * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16528 * PASS
16529 */
16530 } else {
16531 xmlSchemaPCustomErr(ctxt,
16532 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16533 WXS_BASIC_CAST type, NULL,
16534 "The content type of the base type must be either "
16535 "empty or 'mixed' (or 'elements-only') and an emptiable "
16536 "particle", NULL);
16537 return (ctxt->err);
16538 }
16539 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16540 WXS_HAS_MIXED_CONTENT(type)) {
16541 /*
16542 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16543 * itself must be element-only"
16544 */
16545 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16546 /*
16547 * SPEC (5.4.1.2) "The {content type} of the complex type
16548 * definition itself and of the {base type definition} must be
16549 * mixed"
16550 */
16551 xmlSchemaPCustomErr(ctxt,
16552 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16553 WXS_BASIC_CAST type, NULL,
16554 "If the content type is 'mixed', then the content type of the "
16555 "base type must also be 'mixed'", NULL);
16556 return (ctxt->err);
16557 }
16558 /*
16559 * SPEC (5.4.2) "The particle of the complex type definition itself
16560 * must be a `valid restriction` of the particle of the {content
16561 * type} of the {base type definition} as defined in Particle Valid
16562 * (Restriction) ($3.9.6).
16563 *
16564 * URGENT TODO: (5.4.2)
16565 */
16566 } else {
16567 xmlSchemaPCustomErr(ctxt,
16568 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16569 WXS_BASIC_CAST type, NULL,
16570 "The type is not a valid restriction of its base type", NULL);
16571 return (ctxt->err);
16572 }
16573 return (0);
16574 }
16575
16576 /**
16577 * xmlSchemaCheckCTComponent:
16578 * @ctxt: the schema parser context
16579 * @type: the complex type definition
16580 *
16581 * (3.4.6) Constraints on Complex Type Definition Schema Components
16582 *
16583 * Returns 0 if the constraints are satisfied, a positive
16584 * error code if not and -1 if an internal error occurred.
16585 */
16586 static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16587 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16588 xmlSchemaTypePtr type)
16589 {
16590 int ret;
16591 /*
16592 * Complex Type Definition Properties Correct
16593 */
16594 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16595 if (ret != 0)
16596 return (ret);
16597 if (WXS_IS_EXTENSION(type))
16598 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16599 else
16600 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16601 return (ret);
16602 }
16603
16604 /**
16605 * xmlSchemaCheckSRCCT:
16606 * @ctxt: the schema parser context
16607 * @type: the complex type definition
16608 *
16609 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16610 * Schema Representation Constraint:
16611 * Complex Type Definition Representation OK (src-ct)
16612 *
16613 * Returns 0 if the constraints are satisfied, a positive
16614 * error code if not and -1 if an internal error occurred.
16615 */
16616 static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16617 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16618 xmlSchemaTypePtr type)
16619 {
16620 xmlSchemaTypePtr base;
16621 int ret = 0;
16622
16623 /*
16624 * TODO: Adjust the error codes here, as I used
16625 * XML_SCHEMAP_SRC_CT_1 only yet.
16626 */
16627 base = type->baseType;
16628 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16629 /*
16630 * 1 If the <complexContent> alternative is chosen, the type definition
16631 * `resolved` to by the `actual value` of the base [attribute]
16632 * must be a complex type definition;
16633 */
16634 if (! WXS_IS_COMPLEX(base)) {
16635 xmlChar *str = NULL;
16636 xmlSchemaPCustomErr(ctxt,
16637 XML_SCHEMAP_SRC_CT_1,
16638 WXS_BASIC_CAST type, type->node,
16639 "If using <complexContent>, the base type is expected to be "
16640 "a complex type. The base type '%s' is a simple type",
16641 xmlSchemaFormatQName(&str, base->targetNamespace,
16642 base->name));
16643 FREE_AND_NULL(str)
16644 return (XML_SCHEMAP_SRC_CT_1);
16645 }
16646 } else {
16647 /*
16648 * SPEC
16649 * 2 If the <simpleContent> alternative is chosen, all of the
16650 * following must be true:
16651 * 2.1 The type definition `resolved` to by the `actual value` of the
16652 * base [attribute] must be one of the following:
16653 */
16654 if (WXS_IS_SIMPLE(base)) {
16655 if (WXS_IS_EXTENSION(type) == 0) {
16656 xmlChar *str = NULL;
16657 /*
16658 * 2.1.3 only if the <extension> alternative is also
16659 * chosen, a simple type definition.
16660 */
16661 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16662 xmlSchemaPCustomErr(ctxt,
16663 XML_SCHEMAP_SRC_CT_1,
16664 WXS_BASIC_CAST type, NULL,
16665 "If using <simpleContent> and <restriction>, the base "
16666 "type must be a complex type. The base type '%s' is "
16667 "a simple type",
16668 xmlSchemaFormatQName(&str, base->targetNamespace,
16669 base->name));
16670 FREE_AND_NULL(str)
16671 return (XML_SCHEMAP_SRC_CT_1);
16672 }
16673 } else {
16674 /* Base type is a complex type. */
16675 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16676 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16677 /*
16678 * 2.1.1 a complex type definition whose {content type} is a
16679 * simple type definition;
16680 * PASS
16681 */
16682 if (base->contentTypeDef == NULL) {
16683 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16684 WXS_BASIC_CAST type, NULL,
16685 "Internal error: xmlSchemaCheckSRCCT, "
16686 "'%s', base type has no content type",
16687 type->name);
16688 return (-1);
16689 }
16690 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16691 (WXS_IS_RESTRICTION(type))) {
16692
16693 /*
16694 * 2.1.2 only if the <restriction> alternative is also
16695 * chosen, a complex type definition whose {content type}
16696 * is mixed and a particle emptiable.
16697 */
16698 if (! xmlSchemaIsParticleEmptiable(
16699 (xmlSchemaParticlePtr) base->subtypes)) {
16700 ret = XML_SCHEMAP_SRC_CT_1;
16701 } else
16702 /*
16703 * Attention: at this point the <simpleType> child is in
16704 * ->contentTypeDef (put there during parsing).
16705 */
16706 if (type->contentTypeDef == NULL) {
16707 xmlChar *str = NULL;
16708 /*
16709 * 2.2 If clause 2.1.2 above is satisfied, then there
16710 * must be a <simpleType> among the [children] of
16711 * <restriction>.
16712 */
16713 /* TODO: Change error code to ..._SRC_CT_2_2. */
16714 xmlSchemaPCustomErr(ctxt,
16715 XML_SCHEMAP_SRC_CT_1,
16716 WXS_BASIC_CAST type, NULL,
16717 "A <simpleType> is expected among the children "
16718 "of <restriction>, if <simpleContent> is used and "
16719 "the base type '%s' is a complex type",
16720 xmlSchemaFormatQName(&str, base->targetNamespace,
16721 base->name));
16722 FREE_AND_NULL(str)
16723 return (XML_SCHEMAP_SRC_CT_1);
16724 }
16725 } else {
16726 ret = XML_SCHEMAP_SRC_CT_1;
16727 }
16728 }
16729 if (ret > 0) {
16730 xmlChar *str = NULL;
16731 if (WXS_IS_RESTRICTION(type)) {
16732 xmlSchemaPCustomErr(ctxt,
16733 XML_SCHEMAP_SRC_CT_1,
16734 WXS_BASIC_CAST type, NULL,
16735 "If <simpleContent> and <restriction> is used, the "
16736 "base type must be a simple type or a complex type with "
16737 "mixed content and particle emptiable. The base type "
16738 "'%s' is none of those",
16739 xmlSchemaFormatQName(&str, base->targetNamespace,
16740 base->name));
16741 } else {
16742 xmlSchemaPCustomErr(ctxt,
16743 XML_SCHEMAP_SRC_CT_1,
16744 WXS_BASIC_CAST type, NULL,
16745 "If <simpleContent> and <extension> is used, the "
16746 "base type must be a simple type. The base type '%s' "
16747 "is a complex type",
16748 xmlSchemaFormatQName(&str, base->targetNamespace,
16749 base->name));
16750 }
16751 FREE_AND_NULL(str)
16752 }
16753 }
16754 /*
16755 * SPEC (3) "The corresponding complex type definition component must
16756 * satisfy the conditions set out in Constraints on Complex Type
16757 * Definition Schema Components ($3.4.6);"
16758 * NOTE (3) will be done in xmlSchemaTypeFixup().
16759 */
16760 /*
16761 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16762 * above for {attribute wildcard} is satisfied, the intensional
16763 * intersection must be expressible, as defined in Attribute Wildcard
16764 * Intersection ($3.10.6).
16765 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16766 */
16767 return (ret);
16768 }
16769
16770 #ifdef ENABLE_PARTICLE_RESTRICTION
16771 /**
16772 * xmlSchemaCheckParticleRangeOK:
16773 * @ctxt: the schema parser context
16774 * @type: the complex type definition
16775 *
16776 * (3.9.6) Constraints on Particle Schema Components
16777 * Schema Component Constraint:
16778 * Occurrence Range OK (range-ok)
16779 *
16780 * STATUS: complete
16781 *
16782 * Returns 0 if the constraints are satisfied, a positive
16783 * error code if not and -1 if an internal error occurred.
16784 */
16785 static int
xmlSchemaCheckParticleRangeOK(int rmin,int rmax,int bmin,int bmax)16786 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16787 int bmin, int bmax)
16788 {
16789 if (rmin < bmin)
16790 return (1);
16791 if ((bmax != UNBOUNDED) &&
16792 (rmax > bmax))
16793 return (1);
16794 return (0);
16795 }
16796
16797 /**
16798 * xmlSchemaCheckRCaseNameAndTypeOK:
16799 * @ctxt: the schema parser context
16800 * @r: the restricting element declaration particle
16801 * @b: the base element declaration particle
16802 *
16803 * (3.9.6) Constraints on Particle Schema Components
16804 * Schema Component Constraint:
16805 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16806 * (rcase-NameAndTypeOK)
16807 *
16808 * STATUS:
16809 * MISSING (3.2.3)
16810 * CLARIFY: (3.2.2)
16811 *
16812 * Returns 0 if the constraints are satisfied, a positive
16813 * error code if not and -1 if an internal error occurred.
16814 */
16815 static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16816 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16817 xmlSchemaParticlePtr r,
16818 xmlSchemaParticlePtr b)
16819 {
16820 xmlSchemaElementPtr elemR, elemB;
16821
16822 /* TODO: Error codes (rcase-NameAndTypeOK). */
16823 elemR = (xmlSchemaElementPtr) r->children;
16824 elemB = (xmlSchemaElementPtr) b->children;
16825 /*
16826 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16827 * the same."
16828 */
16829 if ((elemR != elemB) &&
16830 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16831 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16832 return (1);
16833 /*
16834 * SPEC (2) "R's occurrence range is a valid restriction of B's
16835 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16836 */
16837 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16838 b->minOccurs, b->maxOccurs) != 0)
16839 return (1);
16840 /*
16841 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16842 * {scope} are global."
16843 */
16844 if (elemR == elemB)
16845 return (0);
16846 /*
16847 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16848 */
16849 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16850 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16851 return (1);
16852 /*
16853 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16854 * or is not fixed, or R's declaration's {value constraint} is fixed
16855 * with the same value."
16856 */
16857 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16858 ((elemR->value == NULL) ||
16859 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16860 /* TODO: Equality of the initial value or normalized or canonical? */
16861 (! xmlStrEqual(elemR->value, elemB->value))))
16862 return (1);
16863 /*
16864 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16865 * definitions} is a subset of B's declaration's {identity-constraint
16866 * definitions}, if any."
16867 */
16868 if (elemB->idcs != NULL) {
16869 /* TODO */
16870 }
16871 /*
16872 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16873 * superset of B's declaration's {disallowed substitutions}."
16874 */
16875 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16876 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16877 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16878 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16879 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16880 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16881 return (1);
16882 /*
16883 * SPEC (3.2.5) "R's {type definition} is validly derived given
16884 * {extension, list, union} from B's {type definition}"
16885 *
16886 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16887 * set, if the corresponding constraints handle "restriction" and
16888 * "extension" only?
16889 *
16890 */
16891 {
16892 int set = 0;
16893
16894 set |= SUBSET_EXTENSION;
16895 set |= SUBSET_LIST;
16896 set |= SUBSET_UNION;
16897 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16898 elemB->subtypes, set) != 0)
16899 return (1);
16900 }
16901 return (0);
16902 }
16903
16904 /**
16905 * xmlSchemaCheckRCaseNSCompat:
16906 * @ctxt: the schema parser context
16907 * @r: the restricting element declaration particle
16908 * @b: the base wildcard particle
16909 *
16910 * (3.9.6) Constraints on Particle Schema Components
16911 * Schema Component Constraint:
16912 * Particle Derivation OK (Elt:Any -- NSCompat)
16913 * (rcase-NSCompat)
16914 *
16915 * STATUS: complete
16916 *
16917 * Returns 0 if the constraints are satisfied, a positive
16918 * error code if not and -1 if an internal error occurred.
16919 */
16920 static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16921 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16922 xmlSchemaParticlePtr r,
16923 xmlSchemaParticlePtr b)
16924 {
16925 /* TODO:Error codes (rcase-NSCompat). */
16926 /*
16927 * SPEC "For an element declaration particle to be a `valid restriction`
16928 * of a wildcard particle all of the following must be true:"
16929 *
16930 * SPEC (1) "The element declaration's {target namespace} is `valid`
16931 * with respect to the wildcard's {namespace constraint} as defined by
16932 * Wildcard allows Namespace Name ($3.10.4)."
16933 */
16934 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16935 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16936 return (1);
16937 /*
16938 * SPEC (2) "R's occurrence range is a valid restriction of B's
16939 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16940 */
16941 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16942 b->minOccurs, b->maxOccurs) != 0)
16943 return (1);
16944
16945 return (0);
16946 }
16947
16948 /**
16949 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16950 * @ctxt: the schema parser context
16951 * @r: the restricting element declaration particle
16952 * @b: the base model group particle
16953 *
16954 * (3.9.6) Constraints on Particle Schema Components
16955 * Schema Component Constraint:
16956 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16957 * (rcase-RecurseAsIfGroup)
16958 *
16959 * STATUS: TODO
16960 *
16961 * Returns 0 if the constraints are satisfied, a positive
16962 * error code if not and -1 if an internal error occurred.
16963 */
16964 static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16965 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16966 xmlSchemaParticlePtr r,
16967 xmlSchemaParticlePtr b)
16968 {
16969 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16970 TODO
16971 return (0);
16972 }
16973
16974 /**
16975 * xmlSchemaCheckRCaseNSSubset:
16976 * @ctxt: the schema parser context
16977 * @r: the restricting wildcard particle
16978 * @b: the base wildcard particle
16979 *
16980 * (3.9.6) Constraints on Particle Schema Components
16981 * Schema Component Constraint:
16982 * Particle Derivation OK (Any:Any -- NSSubset)
16983 * (rcase-NSSubset)
16984 *
16985 * STATUS: complete
16986 *
16987 * Returns 0 if the constraints are satisfied, a positive
16988 * error code if not and -1 if an internal error occurred.
16989 */
16990 static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b,int isAnyTypeBase)16991 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16992 xmlSchemaParticlePtr r,
16993 xmlSchemaParticlePtr b,
16994 int isAnyTypeBase)
16995 {
16996 /* TODO: Error codes (rcase-NSSubset). */
16997 /*
16998 * SPEC (1) "R's occurrence range is a valid restriction of B's
16999 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17000 */
17001 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17002 b->minOccurs, b->maxOccurs))
17003 return (1);
17004 /*
17005 * SPEC (2) "R's {namespace constraint} must be an intensional subset
17006 * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17007 */
17008 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17009 (xmlSchemaWildcardPtr) b->children))
17010 return (1);
17011 /*
17012 * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17013 * definition`, R's {process contents} must be identical to or stronger
17014 * than B's {process contents}, where strict is stronger than lax is
17015 * stronger than skip."
17016 */
17017 if (! isAnyTypeBase) {
17018 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17019 ((xmlSchemaWildcardPtr) b->children)->processContents)
17020 return (1);
17021 }
17022
17023 return (0);
17024 }
17025
17026 /**
17027 * xmlSchemaCheckCOSParticleRestrict:
17028 * @ctxt: the schema parser context
17029 * @type: the complex type definition
17030 *
17031 * (3.9.6) Constraints on Particle Schema Components
17032 * Schema Component Constraint:
17033 * Particle Valid (Restriction) (cos-particle-restrict)
17034 *
17035 * STATUS: TODO
17036 *
17037 * Returns 0 if the constraints are satisfied, a positive
17038 * error code if not and -1 if an internal error occurred.
17039 */
17040 static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17041 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17042 xmlSchemaParticlePtr r,
17043 xmlSchemaParticlePtr b)
17044 {
17045 int ret = 0;
17046
17047 /*part = WXS_TYPE_PARTICLE(type);
17048 basePart = WXS_TYPE_PARTICLE(base);
17049 */
17050
17051 TODO
17052
17053 /*
17054 * SPEC (1) "They are the same particle."
17055 */
17056 if (r == b)
17057 return (0);
17058
17059
17060 return (0);
17061 }
17062
17063 #if 0
17064 /**
17065 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17066 * @ctxt: the schema parser context
17067 * @r: the model group particle
17068 * @b: the base wildcard particle
17069 *
17070 * (3.9.6) Constraints on Particle Schema Components
17071 * Schema Component Constraint:
17072 * Particle Derivation OK (All/Choice/Sequence:Any --
17073 * NSRecurseCheckCardinality)
17074 * (rcase-NSRecurseCheckCardinality)
17075 *
17076 * STATUS: TODO: subst-groups
17077 *
17078 * Returns 0 if the constraints are satisfied, a positive
17079 * error code if not and -1 if an internal error occurred.
17080 */
17081 static int
17082 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17083 xmlSchemaParticlePtr r,
17084 xmlSchemaParticlePtr b)
17085 {
17086 xmlSchemaParticlePtr part;
17087 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17088 if ((r->children == NULL) || (r->children->children == NULL))
17089 return (-1);
17090 /*
17091 * SPEC "For a group particle to be a `valid restriction` of a
17092 * wildcard particle..."
17093 *
17094 * SPEC (1) "Every member of the {particles} of the group is a `valid
17095 * restriction` of the wildcard as defined by
17096 * Particle Valid (Restriction) ($3.9.6)."
17097 */
17098 part = (xmlSchemaParticlePtr) r->children->children;
17099 do {
17100 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17101 return (1);
17102 part = (xmlSchemaParticlePtr) part->next;
17103 } while (part != NULL);
17104 /*
17105 * SPEC (2) "The effective total range of the group [...] is a
17106 * valid restriction of B's occurrence range as defined by
17107 * Occurrence Range OK ($3.9.6)."
17108 */
17109 if (xmlSchemaCheckParticleRangeOK(
17110 xmlSchemaGetParticleTotalRangeMin(r),
17111 xmlSchemaGetParticleTotalRangeMax(r),
17112 b->minOccurs, b->maxOccurs) != 0)
17113 return (1);
17114 return (0);
17115 }
17116 #endif
17117
17118 /**
17119 * xmlSchemaCheckRCaseRecurse:
17120 * @ctxt: the schema parser context
17121 * @r: the <all> or <sequence> model group particle
17122 * @b: the base <all> or <sequence> model group particle
17123 *
17124 * (3.9.6) Constraints on Particle Schema Components
17125 * Schema Component Constraint:
17126 * Particle Derivation OK (All:All,Sequence:Sequence --
17127 Recurse)
17128 * (rcase-Recurse)
17129 *
17130 * STATUS: ?
17131 * TODO: subst-groups
17132 *
17133 * Returns 0 if the constraints are satisfied, a positive
17134 * error code if not and -1 if an internal error occurred.
17135 */
17136 static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17137 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17138 xmlSchemaParticlePtr r,
17139 xmlSchemaParticlePtr b)
17140 {
17141 /* xmlSchemaParticlePtr part; */
17142 /* TODO: Error codes (rcase-Recurse). */
17143 if ((r->children == NULL) || (b->children == NULL) ||
17144 (r->children->type != b->children->type))
17145 return (-1);
17146 /*
17147 * SPEC "For an all or sequence group particle to be a `valid
17148 * restriction` of another group particle with the same {compositor}..."
17149 *
17150 * SPEC (1) "R's occurrence range is a valid restriction of B's
17151 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17152 */
17153 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17154 b->minOccurs, b->maxOccurs))
17155 return (1);
17156
17157
17158 return (0);
17159 }
17160
17161 #endif
17162
17163 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17164 xmlSchemaPCustomErrExt(pctxt, \
17165 XML_SCHEMAP_INVALID_FACET_VALUE, \
17166 WXS_BASIC_CAST fac1, fac1->node, \
17167 "It is an error for both '%s' and '%s' to be specified on the "\
17168 "same type definition", \
17169 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17170 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17171
17172 #define FACET_RESTR_ERR(fac1, msg) \
17173 xmlSchemaPCustomErr(pctxt, \
17174 XML_SCHEMAP_INVALID_FACET_VALUE, \
17175 WXS_BASIC_CAST fac1, fac1->node, \
17176 msg, NULL);
17177
17178 #define FACET_RESTR_FIXED_ERR(fac) \
17179 xmlSchemaPCustomErr(pctxt, \
17180 XML_SCHEMAP_INVALID_FACET_VALUE, \
17181 WXS_BASIC_CAST fac, fac->node, \
17182 "The base type's facet is 'fixed', thus the value must not " \
17183 "differ", NULL);
17184
17185 static void
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,xmlSchemaFacetPtr facet1,xmlSchemaFacetPtr facet2,int lessGreater,int orEqual,int ofBase)17186 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17187 xmlSchemaFacetPtr facet1,
17188 xmlSchemaFacetPtr facet2,
17189 int lessGreater,
17190 int orEqual,
17191 int ofBase)
17192 {
17193 xmlChar *msg = NULL;
17194
17195 msg = xmlStrdup(BAD_CAST "'");
17196 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17197 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17198 if (lessGreater == 0)
17199 msg = xmlStrcat(msg, BAD_CAST " equal to");
17200 if (lessGreater == 1)
17201 msg = xmlStrcat(msg, BAD_CAST " greater than");
17202 else
17203 msg = xmlStrcat(msg, BAD_CAST " less than");
17204
17205 if (orEqual)
17206 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17207 msg = xmlStrcat(msg, BAD_CAST " '");
17208 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17209 if (ofBase)
17210 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17211 else
17212 msg = xmlStrcat(msg, BAD_CAST "'");
17213
17214 xmlSchemaPCustomErr(pctxt,
17215 XML_SCHEMAP_INVALID_FACET_VALUE,
17216 WXS_BASIC_CAST facet1, NULL,
17217 (const char *) msg, NULL);
17218
17219 if (msg != NULL)
17220 xmlFree(msg);
17221 }
17222
17223 /*
17224 * xmlSchemaDeriveAndValidateFacets:
17225 *
17226 * Schema Component Constraint: Simple Type Restriction (Facets)
17227 * (st-restrict-facets)
17228 */
17229 static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17230 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17231 xmlSchemaTypePtr type)
17232 {
17233 xmlSchemaTypePtr base = type->baseType;
17234 xmlSchemaFacetLinkPtr link, cur, last = NULL;
17235 xmlSchemaFacetPtr facet, bfacet,
17236 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17237 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17238 fmininc = NULL, fmaxinc = NULL,
17239 fminexc = NULL, fmaxexc = NULL,
17240 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17241 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17242 bfmininc = NULL, bfmaxinc = NULL,
17243 bfminexc = NULL, bfmaxexc = NULL;
17244 int res; /* err = 0, fixedErr; */
17245
17246 /*
17247 * SPEC st-restrict-facets 1:
17248 * "The {variety} of R is the same as that of B."
17249 */
17250 /*
17251 * SPEC st-restrict-facets 2:
17252 * "If {variety} is atomic, the {primitive type definition}
17253 * of R is the same as that of B."
17254 *
17255 * NOTE: we leave 1 & 2 out for now, since this will be
17256 * satisfied by the derivation process.
17257 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17258 */
17259 /*
17260 * SPEC st-restrict-facets 3:
17261 * "The {facets} of R are the union of S and the {facets}
17262 * of B, eliminating duplicates. To eliminate duplicates,
17263 * when a facet of the same kind occurs in both S and the
17264 * {facets} of B, the one in the {facets} of B is not
17265 * included, with the exception of enumeration and pattern
17266 * facets, for which multiple occurrences with distinct values
17267 * are allowed."
17268 */
17269
17270 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17271 return (0);
17272
17273 last = type->facetSet;
17274 if (last != NULL)
17275 while (last->next != NULL)
17276 last = last->next;
17277
17278 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17279 facet = cur->facet;
17280 switch (facet->type) {
17281 case XML_SCHEMA_FACET_LENGTH:
17282 flength = facet; break;
17283 case XML_SCHEMA_FACET_MINLENGTH:
17284 fminlen = facet; break;
17285 case XML_SCHEMA_FACET_MININCLUSIVE:
17286 fmininc = facet; break;
17287 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17288 fminexc = facet; break;
17289 case XML_SCHEMA_FACET_MAXLENGTH:
17290 fmaxlen = facet; break;
17291 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17292 fmaxinc = facet; break;
17293 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17294 fmaxexc = facet; break;
17295 case XML_SCHEMA_FACET_TOTALDIGITS:
17296 ftotdig = facet; break;
17297 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17298 ffracdig = facet; break;
17299 default:
17300 break;
17301 }
17302 }
17303 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17304 facet = cur->facet;
17305 switch (facet->type) {
17306 case XML_SCHEMA_FACET_LENGTH:
17307 bflength = facet; break;
17308 case XML_SCHEMA_FACET_MINLENGTH:
17309 bfminlen = facet; break;
17310 case XML_SCHEMA_FACET_MININCLUSIVE:
17311 bfmininc = facet; break;
17312 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17313 bfminexc = facet; break;
17314 case XML_SCHEMA_FACET_MAXLENGTH:
17315 bfmaxlen = facet; break;
17316 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17317 bfmaxinc = facet; break;
17318 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17319 bfmaxexc = facet; break;
17320 case XML_SCHEMA_FACET_TOTALDIGITS:
17321 bftotdig = facet; break;
17322 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17323 bffracdig = facet; break;
17324 default:
17325 break;
17326 }
17327 }
17328 /*
17329 * length and minLength or maxLength (2.2) + (3.2)
17330 */
17331 if (flength && (fminlen || fmaxlen)) {
17332 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17333 "either of 'minLength' or 'maxLength' to be specified on "
17334 "the same type definition")
17335 }
17336 /*
17337 * Mutual exclusions in the same derivation step.
17338 */
17339 if ((fmaxinc) && (fmaxexc)) {
17340 /*
17341 * SCC "maxInclusive and maxExclusive"
17342 */
17343 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17344 }
17345 if ((fmininc) && (fminexc)) {
17346 /*
17347 * SCC "minInclusive and minExclusive"
17348 */
17349 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17350 }
17351
17352 if (flength && bflength) {
17353 /*
17354 * SCC "length valid restriction"
17355 * The values have to be equal.
17356 */
17357 res = xmlSchemaCompareValues(flength->val, bflength->val);
17358 if (res == -2)
17359 goto internal_error;
17360 if (res != 0)
17361 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17362 if ((res != 0) && (bflength->fixed)) {
17363 FACET_RESTR_FIXED_ERR(flength)
17364 }
17365
17366 }
17367 if (fminlen && bfminlen) {
17368 /*
17369 * SCC "minLength valid restriction"
17370 * minLength >= BASE minLength
17371 */
17372 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17373 if (res == -2)
17374 goto internal_error;
17375 if (res == -1)
17376 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17377 if ((res != 0) && (bfminlen->fixed)) {
17378 FACET_RESTR_FIXED_ERR(fminlen)
17379 }
17380 }
17381 if (fmaxlen && bfmaxlen) {
17382 /*
17383 * SCC "maxLength valid restriction"
17384 * maxLength <= BASE minLength
17385 */
17386 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17387 if (res == -2)
17388 goto internal_error;
17389 if (res == 1)
17390 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17391 if ((res != 0) && (bfmaxlen->fixed)) {
17392 FACET_RESTR_FIXED_ERR(fmaxlen)
17393 }
17394 }
17395 /*
17396 * SCC "length and minLength or maxLength"
17397 */
17398 if (! flength)
17399 flength = bflength;
17400 if (flength) {
17401 if (! fminlen)
17402 fminlen = bfminlen;
17403 if (fminlen) {
17404 /* (1.1) length >= minLength */
17405 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17406 if (res == -2)
17407 goto internal_error;
17408 if (res == -1)
17409 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17410 }
17411 if (! fmaxlen)
17412 fmaxlen = bfmaxlen;
17413 if (fmaxlen) {
17414 /* (2.1) length <= maxLength */
17415 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17416 if (res == -2)
17417 goto internal_error;
17418 if (res == 1)
17419 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17420 }
17421 }
17422 if (fmaxinc) {
17423 /*
17424 * "maxInclusive"
17425 */
17426 if (fmininc) {
17427 /* SCC "maxInclusive >= minInclusive" */
17428 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17429 if (res == -2)
17430 goto internal_error;
17431 if (res == -1) {
17432 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17433 }
17434 }
17435 /*
17436 * SCC "maxInclusive valid restriction"
17437 */
17438 if (bfmaxinc) {
17439 /* maxInclusive <= BASE maxInclusive */
17440 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17441 if (res == -2)
17442 goto internal_error;
17443 if (res == 1)
17444 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17445 if ((res != 0) && (bfmaxinc->fixed)) {
17446 FACET_RESTR_FIXED_ERR(fmaxinc)
17447 }
17448 }
17449 if (bfmaxexc) {
17450 /* maxInclusive < BASE maxExclusive */
17451 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17452 if (res == -2)
17453 goto internal_error;
17454 if (res != -1) {
17455 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17456 }
17457 }
17458 if (bfmininc) {
17459 /* maxInclusive >= BASE minInclusive */
17460 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17461 if (res == -2)
17462 goto internal_error;
17463 if (res == -1) {
17464 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17465 }
17466 }
17467 if (bfminexc) {
17468 /* maxInclusive > BASE minExclusive */
17469 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17470 if (res == -2)
17471 goto internal_error;
17472 if (res != 1) {
17473 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17474 }
17475 }
17476 }
17477 if (fmaxexc) {
17478 /*
17479 * "maxExclusive >= minExclusive"
17480 */
17481 if (fminexc) {
17482 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17483 if (res == -2)
17484 goto internal_error;
17485 if (res == -1) {
17486 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17487 }
17488 }
17489 /*
17490 * "maxExclusive valid restriction"
17491 */
17492 if (bfmaxexc) {
17493 /* maxExclusive <= BASE maxExclusive */
17494 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17495 if (res == -2)
17496 goto internal_error;
17497 if (res == 1) {
17498 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17499 }
17500 if ((res != 0) && (bfmaxexc->fixed)) {
17501 FACET_RESTR_FIXED_ERR(fmaxexc)
17502 }
17503 }
17504 if (bfmaxinc) {
17505 /* maxExclusive <= BASE maxInclusive */
17506 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17507 if (res == -2)
17508 goto internal_error;
17509 if (res == 1) {
17510 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17511 }
17512 }
17513 if (bfmininc) {
17514 /* maxExclusive > BASE minInclusive */
17515 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17516 if (res == -2)
17517 goto internal_error;
17518 if (res != 1) {
17519 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17520 }
17521 }
17522 if (bfminexc) {
17523 /* maxExclusive > BASE minExclusive */
17524 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17525 if (res == -2)
17526 goto internal_error;
17527 if (res != 1) {
17528 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17529 }
17530 }
17531 }
17532 if (fminexc) {
17533 /*
17534 * "minExclusive < maxInclusive"
17535 */
17536 if (fmaxinc) {
17537 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17538 if (res == -2)
17539 goto internal_error;
17540 if (res != -1) {
17541 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17542 }
17543 }
17544 /*
17545 * "minExclusive valid restriction"
17546 */
17547 if (bfminexc) {
17548 /* minExclusive >= BASE minExclusive */
17549 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17550 if (res == -2)
17551 goto internal_error;
17552 if (res == -1) {
17553 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17554 }
17555 if ((res != 0) && (bfminexc->fixed)) {
17556 FACET_RESTR_FIXED_ERR(fminexc)
17557 }
17558 }
17559 if (bfmaxinc) {
17560 /* minExclusive <= BASE maxInclusive */
17561 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17562 if (res == -2)
17563 goto internal_error;
17564 if (res == 1) {
17565 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17566 }
17567 }
17568 if (bfmininc) {
17569 /* minExclusive >= BASE minInclusive */
17570 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17571 if (res == -2)
17572 goto internal_error;
17573 if (res == -1) {
17574 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17575 }
17576 }
17577 if (bfmaxexc) {
17578 /* minExclusive < BASE maxExclusive */
17579 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17580 if (res == -2)
17581 goto internal_error;
17582 if (res != -1) {
17583 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17584 }
17585 }
17586 }
17587 if (fmininc) {
17588 /*
17589 * "minInclusive < maxExclusive"
17590 */
17591 if (fmaxexc) {
17592 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17593 if (res == -2)
17594 goto internal_error;
17595 if (res != -1) {
17596 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17597 }
17598 }
17599 /*
17600 * "minExclusive valid restriction"
17601 */
17602 if (bfmininc) {
17603 /* minInclusive >= BASE minInclusive */
17604 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17605 if (res == -2)
17606 goto internal_error;
17607 if (res == -1) {
17608 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17609 }
17610 if ((res != 0) && (bfmininc->fixed)) {
17611 FACET_RESTR_FIXED_ERR(fmininc)
17612 }
17613 }
17614 if (bfmaxinc) {
17615 /* minInclusive <= BASE maxInclusive */
17616 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17617 if (res == -2)
17618 goto internal_error;
17619 if (res == 1) {
17620 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17621 }
17622 }
17623 if (bfminexc) {
17624 /* minInclusive > BASE minExclusive */
17625 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17626 if (res == -2)
17627 goto internal_error;
17628 if (res != 1)
17629 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17630 }
17631 if (bfmaxexc) {
17632 /* minInclusive < BASE maxExclusive */
17633 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17634 if (res == -2)
17635 goto internal_error;
17636 if (res != -1)
17637 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17638 }
17639 }
17640 if (ftotdig && bftotdig) {
17641 /*
17642 * SCC " totalDigits valid restriction"
17643 * totalDigits <= BASE totalDigits
17644 */
17645 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17646 if (res == -2)
17647 goto internal_error;
17648 if (res == 1)
17649 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17650 -1, 1, 1);
17651 if ((res != 0) && (bftotdig->fixed)) {
17652 FACET_RESTR_FIXED_ERR(ftotdig)
17653 }
17654 }
17655 if (ffracdig && bffracdig) {
17656 /*
17657 * SCC "fractionDigits valid restriction"
17658 * fractionDigits <= BASE fractionDigits
17659 */
17660 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17661 if (res == -2)
17662 goto internal_error;
17663 if (res == 1)
17664 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17665 -1, 1, 1);
17666 if ((res != 0) && (bffracdig->fixed)) {
17667 FACET_RESTR_FIXED_ERR(ffracdig)
17668 }
17669 }
17670 /*
17671 * SCC "fractionDigits less than or equal to totalDigits"
17672 */
17673 if (! ftotdig)
17674 ftotdig = bftotdig;
17675 if (! ffracdig)
17676 ffracdig = bffracdig;
17677 if (ftotdig && ffracdig) {
17678 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17679 if (res == -2)
17680 goto internal_error;
17681 if (res == 1)
17682 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17683 -1, 1, 0);
17684 }
17685 /*
17686 * *Enumerations* won' be added here, since only the first set
17687 * of enumerations in the ancestor-or-self axis is used
17688 * for validation, plus we need to use the base type of those
17689 * enumerations for whitespace.
17690 *
17691 * *Patterns*: won't be add here, since they are ORed at
17692 * type level and ANDed at ancestor level. This will
17693 * happen during validation by walking the base axis
17694 * of the type.
17695 */
17696 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17697 bfacet = cur->facet;
17698 /*
17699 * Special handling of enumerations and patterns.
17700 * TODO: hmm, they should not appear in the set, so remove this.
17701 */
17702 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17703 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17704 continue;
17705 /*
17706 * Search for a duplicate facet in the current type.
17707 */
17708 link = type->facetSet;
17709 /* err = 0; */
17710 /* fixedErr = 0; */
17711 while (link != NULL) {
17712 facet = link->facet;
17713 if (facet->type == bfacet->type) {
17714 switch (facet->type) {
17715 case XML_SCHEMA_FACET_WHITESPACE:
17716 /*
17717 * The whitespace must be stronger.
17718 */
17719 if (facet->whitespace < bfacet->whitespace) {
17720 FACET_RESTR_ERR(facet,
17721 "The 'whitespace' value has to be equal to "
17722 "or stronger than the 'whitespace' value of "
17723 "the base type")
17724 }
17725 if ((bfacet->fixed) &&
17726 (facet->whitespace != bfacet->whitespace)) {
17727 FACET_RESTR_FIXED_ERR(facet)
17728 }
17729 break;
17730 default:
17731 break;
17732 }
17733 /* Duplicate found. */
17734 break;
17735 }
17736 link = link->next;
17737 }
17738 /*
17739 * If no duplicate was found: add the base types's facet
17740 * to the set.
17741 */
17742 if (link == NULL) {
17743 link = (xmlSchemaFacetLinkPtr)
17744 xmlMalloc(sizeof(xmlSchemaFacetLink));
17745 if (link == NULL) {
17746 xmlSchemaPErrMemory(pctxt);
17747 return (-1);
17748 }
17749 link->facet = cur->facet;
17750 link->next = NULL;
17751 if (last == NULL)
17752 type->facetSet = link;
17753 else
17754 last->next = link;
17755 last = link;
17756 }
17757
17758 }
17759
17760 return (0);
17761 internal_error:
17762 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17763 "an error occurred");
17764 return (-1);
17765 }
17766
17767 static int
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17768 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17769 xmlSchemaTypePtr type)
17770 {
17771 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17772 /*
17773 * The actual value is then formed by replacing any union type
17774 * definition in the `explicit members` with the members of their
17775 * {member type definitions}, in order.
17776 *
17777 * TODO: There's a bug entry at
17778 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17779 * which indicates that we'll keep the union types the future.
17780 */
17781 link = type->memberTypes;
17782 while (link != NULL) {
17783
17784 if (WXS_IS_TYPE_NOT_FIXED(link->type))
17785 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17786
17787 if (WXS_IS_UNION(link->type)) {
17788 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17789 if (subLink != NULL) {
17790 link->type = subLink->type;
17791 if (subLink->next != NULL) {
17792 lastLink = link->next;
17793 subLink = subLink->next;
17794 prevLink = link;
17795 while (subLink != NULL) {
17796 newLink = (xmlSchemaTypeLinkPtr)
17797 xmlMalloc(sizeof(xmlSchemaTypeLink));
17798 if (newLink == NULL) {
17799 xmlSchemaPErrMemory(pctxt);
17800 return (-1);
17801 }
17802 newLink->type = subLink->type;
17803 prevLink->next = newLink;
17804 prevLink = newLink;
17805 newLink->next = lastLink;
17806
17807 subLink = subLink->next;
17808 }
17809 }
17810 }
17811 }
17812 link = link->next;
17813 }
17814 return (0);
17815 }
17816
17817 static void
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)17818 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17819 {
17820 int has = 0, needVal = 0, normVal = 0;
17821
17822 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17823 if (has) {
17824 needVal = (type->baseType->flags &
17825 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17826 normVal = (type->baseType->flags &
17827 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17828 }
17829 if (type->facets != NULL) {
17830 xmlSchemaFacetPtr fac;
17831
17832 for (fac = type->facets; fac != NULL; fac = fac->next) {
17833 switch (fac->type) {
17834 case XML_SCHEMA_FACET_WHITESPACE:
17835 break;
17836 case XML_SCHEMA_FACET_PATTERN:
17837 normVal = 1;
17838 has = 1;
17839 break;
17840 case XML_SCHEMA_FACET_ENUMERATION:
17841 needVal = 1;
17842 normVal = 1;
17843 has = 1;
17844 break;
17845 default:
17846 has = 1;
17847 break;
17848 }
17849 }
17850 }
17851 if (normVal)
17852 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17853 if (needVal)
17854 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17855 if (has)
17856 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17857
17858 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17859 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17860 /*
17861 * OPTIMIZE VAL TODO: Some facets need a computed value.
17862 */
17863 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17864 (prim->builtInType != XML_SCHEMAS_STRING)) {
17865 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17866 }
17867 }
17868 }
17869
17870 static int
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)17871 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17872 {
17873
17874
17875 /*
17876 * Evaluate the whitespace-facet value.
17877 */
17878 if (WXS_IS_LIST(type)) {
17879 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17880 return (0);
17881 } else if (WXS_IS_UNION(type))
17882 return (0);
17883
17884 if (type->facetSet != NULL) {
17885 xmlSchemaFacetLinkPtr lin;
17886
17887 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17888 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17889 switch (lin->facet->whitespace) {
17890 case XML_SCHEMAS_FACET_PRESERVE:
17891 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17892 break;
17893 case XML_SCHEMAS_FACET_REPLACE:
17894 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17895 break;
17896 case XML_SCHEMAS_FACET_COLLAPSE:
17897 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17898 break;
17899 default:
17900 return (-1);
17901 }
17902 return (0);
17903 }
17904 }
17905 }
17906 /*
17907 * For all `atomic` datatypes other than string (and types `derived`
17908 * by `restriction` from it) the value of whiteSpace is fixed to
17909 * collapse
17910 */
17911 {
17912 xmlSchemaTypePtr anc;
17913
17914 for (anc = type->baseType; anc != NULL &&
17915 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17916 anc = anc->baseType) {
17917
17918 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17919 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17920 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17921
17922 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17923 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17924 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17925
17926 } else
17927 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17928 break;
17929 }
17930 }
17931 }
17932 return (0);
17933 }
17934
17935 static int
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17936 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17937 xmlSchemaTypePtr type)
17938 {
17939 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17940 return(0);
17941 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17942 return(0);
17943 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17944
17945 if (WXS_IS_LIST(type)) {
17946 /*
17947 * Corresponds to <simpleType><list>...
17948 */
17949 if (type->subtypes == NULL) {
17950 /*
17951 * This one is really needed, so get out.
17952 */
17953 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17954 "list type has no item-type assigned");
17955 return(-1);
17956 }
17957 } else if (WXS_IS_UNION(type)) {
17958 /*
17959 * Corresponds to <simpleType><union>...
17960 */
17961 if (type->memberTypes == NULL) {
17962 /*
17963 * This one is really needed, so get out.
17964 */
17965 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17966 "union type has no member-types assigned");
17967 return(-1);
17968 }
17969 } else {
17970 /*
17971 * Corresponds to <simpleType><restriction>...
17972 */
17973 if (type->baseType == NULL) {
17974 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17975 "type has no base-type assigned");
17976 return(-1);
17977 }
17978 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17979 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17980 return(-1);
17981 /*
17982 * Variety
17983 * If the <restriction> alternative is chosen, then the
17984 * {variety} of the {base type definition}.
17985 */
17986 if (WXS_IS_ATOMIC(type->baseType))
17987 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17988 else if (WXS_IS_LIST(type->baseType)) {
17989 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17990 /*
17991 * Inherit the itemType.
17992 */
17993 type->subtypes = type->baseType->subtypes;
17994 } else if (WXS_IS_UNION(type->baseType)) {
17995 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17996 /*
17997 * NOTE that we won't assign the memberTypes of the base,
17998 * since this will make trouble when freeing them; we will
17999 * use a lookup function to access them instead.
18000 */
18001 }
18002 }
18003 return(0);
18004 }
18005
18006 /*
18007 * 3.14.6 Constraints on Simple Type Definition Schema Components
18008 */
18009 static int
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18010 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18011 xmlSchemaTypePtr type)
18012 {
18013 int res, olderrs = pctxt->nberrors;
18014
18015 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18016 return(-1);
18017
18018 if (! WXS_IS_TYPE_NOT_FIXED(type))
18019 return(0);
18020
18021 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18022 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18023
18024 if (type->baseType == NULL) {
18025 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18026 "missing baseType");
18027 goto exit_failure;
18028 }
18029 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18030 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18031 /*
18032 * If a member type of a union is a union itself, we need to substitute
18033 * that member type for its member types.
18034 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18035 * types in WXS 1.1.
18036 */
18037 if ((type->memberTypes != NULL) &&
18038 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18039 return(-1);
18040 /*
18041 * SPEC src-simple-type 1
18042 * "The corresponding simple type definition, if any, must satisfy
18043 * the conditions set out in Constraints on Simple Type Definition
18044 * Schema Components ($3.14.6)."
18045 */
18046 /*
18047 * Schema Component Constraint: Simple Type Definition Properties Correct
18048 * (st-props-correct)
18049 */
18050 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18051 HFAILURE HERROR
18052 /*
18053 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18054 * (cos-st-restricts)
18055 */
18056 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18057 HFAILURE HERROR
18058 /*
18059 * TODO: Removed the error report, since it got annoying to get an
18060 * extra error report, if anything failed until now.
18061 * Enable this if needed.
18062 *
18063 * xmlSchemaPErr(ctxt, type->node,
18064 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18065 * "Simple type '%s' does not satisfy the constraints "
18066 * "on simple type definitions.\n",
18067 * type->name, NULL);
18068 */
18069 /*
18070 * Schema Component Constraint: Simple Type Restriction (Facets)
18071 * (st-restrict-facets)
18072 */
18073 res = xmlSchemaCheckFacetValues(type, pctxt);
18074 HFAILURE HERROR
18075 if ((type->facetSet != NULL) ||
18076 (type->baseType->facetSet != NULL)) {
18077 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18078 HFAILURE HERROR
18079 }
18080 /*
18081 * Whitespace value.
18082 */
18083 res = xmlSchemaTypeFixupWhitespace(type);
18084 HFAILURE HERROR
18085 xmlSchemaTypeFixupOptimFacets(type);
18086
18087 exit_error:
18088 if (olderrs != pctxt->nberrors)
18089 return(pctxt->err);
18090 return(0);
18091
18092 exit_failure:
18093 return(-1);
18094 }
18095
18096 static int
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18097 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18098 xmlSchemaTypePtr type)
18099 {
18100 int res = 0, olderrs = pctxt->nberrors;
18101 xmlSchemaTypePtr baseType = type->baseType;
18102
18103 if (! WXS_IS_TYPE_NOT_FIXED(type))
18104 return(0);
18105 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18106 if (baseType == NULL) {
18107 PERROR_INT("xmlSchemaFixupComplexType",
18108 "missing baseType");
18109 goto exit_failure;
18110 }
18111 /*
18112 * Fixup the base type.
18113 */
18114 if (WXS_IS_TYPE_NOT_FIXED(baseType))
18115 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18116 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18117 /*
18118 * Skip fixup if the base type is invalid.
18119 * TODO: Generate a warning!
18120 */
18121 return(0);
18122 }
18123 /*
18124 * This basically checks if the base type can be derived.
18125 */
18126 res = xmlSchemaCheckSRCCT(pctxt, type);
18127 HFAILURE HERROR
18128 /*
18129 * Fixup the content type.
18130 */
18131 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18132 /*
18133 * Corresponds to <complexType><simpleContent>...
18134 */
18135 if ((WXS_IS_COMPLEX(baseType)) &&
18136 (baseType->contentTypeDef != NULL) &&
18137 (WXS_IS_RESTRICTION(type))) {
18138 xmlSchemaTypePtr contentBase, content;
18139 #ifdef ENABLE_NAMED_LOCALS
18140 char buf[30];
18141 const xmlChar *tmpname;
18142 #endif
18143 /*
18144 * SPEC (1) If <restriction> + base type is <complexType>,
18145 * "whose own {content type} is a simple type..."
18146 */
18147 if (type->contentTypeDef != NULL) {
18148 /*
18149 * SPEC (1.1) "the simple type definition corresponding to the
18150 * <simpleType> among the [children] of <restriction> if there
18151 * is one;"
18152 * Note that this "<simpleType> among the [children]" was put
18153 * into ->contentTypeDef during parsing.
18154 */
18155 contentBase = type->contentTypeDef;
18156 type->contentTypeDef = NULL;
18157 } else {
18158 /*
18159 * (1.2) "...otherwise (<restriction> has no <simpleType>
18160 * among its [children]), the simple type definition which
18161 * is the {content type} of the ... base type."
18162 */
18163 contentBase = baseType->contentTypeDef;
18164 }
18165 /*
18166 * SPEC
18167 * "... a simple type definition which restricts the simple
18168 * type definition identified in clause 1.1 or clause 1.2
18169 * with a set of facet components"
18170 *
18171 * Create the anonymous simple type, which will be the content
18172 * type of the complex type.
18173 */
18174 #ifdef ENABLE_NAMED_LOCALS
18175 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18176 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18177 content = xmlSchemaAddType(pctxt, pctxt->schema,
18178 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18179 type->node, 0);
18180 #else
18181 content = xmlSchemaAddType(pctxt, pctxt->schema,
18182 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18183 type->node, 0);
18184 #endif
18185 if (content == NULL)
18186 goto exit_failure;
18187 /*
18188 * We will use the same node as for the <complexType>
18189 * to have it somehow anchored in the schema doc.
18190 */
18191 content->type = XML_SCHEMA_TYPE_SIMPLE;
18192 content->baseType = contentBase;
18193 /*
18194 * Move the facets, previously anchored on the
18195 * complexType during parsing.
18196 */
18197 content->facets = type->facets;
18198 type->facets = NULL;
18199 content->facetSet = type->facetSet;
18200 type->facetSet = NULL;
18201
18202 type->contentTypeDef = content;
18203 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18204 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18205 /*
18206 * Fixup the newly created type. We don't need to check
18207 * for circularity here.
18208 */
18209 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18210 HFAILURE HERROR
18211 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18212 HFAILURE HERROR
18213
18214 } else if ((WXS_IS_COMPLEX(baseType)) &&
18215 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18216 (WXS_IS_RESTRICTION(type))) {
18217 /*
18218 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18219 * an emptiable particle, then a simple type definition which
18220 * restricts the <restriction>'s <simpleType> child.
18221 */
18222 if ((type->contentTypeDef == NULL) ||
18223 (type->contentTypeDef->baseType == NULL)) {
18224 /*
18225 * TODO: Check if this ever happens.
18226 */
18227 xmlSchemaPCustomErr(pctxt,
18228 XML_SCHEMAP_INTERNAL,
18229 WXS_BASIC_CAST type, NULL,
18230 "Internal error: xmlSchemaTypeFixup, "
18231 "complex type '%s': the <simpleContent><restriction> "
18232 "is missing a <simpleType> child, but was not caught "
18233 "by xmlSchemaCheckSRCCT()", type->name);
18234 goto exit_failure;
18235 }
18236 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18237 /*
18238 * SPEC (3) If <extension> + base is <complexType> with
18239 * <simpleType> content, "...then the {content type} of that
18240 * complex type definition"
18241 */
18242 if (baseType->contentTypeDef == NULL) {
18243 /*
18244 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18245 * should have caught this already.
18246 */
18247 xmlSchemaPCustomErr(pctxt,
18248 XML_SCHEMAP_INTERNAL,
18249 WXS_BASIC_CAST type, NULL,
18250 "Internal error: xmlSchemaTypeFixup, "
18251 "complex type '%s': the <extension>ed base type is "
18252 "a complex type with no simple content type",
18253 type->name);
18254 goto exit_failure;
18255 }
18256 type->contentTypeDef = baseType->contentTypeDef;
18257 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18258 /*
18259 * SPEC (4) <extension> + base is <simpleType>
18260 * "... then that simple type definition"
18261 */
18262 type->contentTypeDef = baseType;
18263 } else {
18264 /*
18265 * TODO: Check if this ever happens.
18266 */
18267 xmlSchemaPCustomErr(pctxt,
18268 XML_SCHEMAP_INTERNAL,
18269 WXS_BASIC_CAST type, NULL,
18270 "Internal error: xmlSchemaTypeFixup, "
18271 "complex type '%s' with <simpleContent>: unhandled "
18272 "derivation case", type->name);
18273 goto exit_failure;
18274 }
18275 } else {
18276 int dummySequence = 0;
18277 xmlSchemaParticlePtr particle =
18278 (xmlSchemaParticlePtr) type->subtypes;
18279 /*
18280 * Corresponds to <complexType><complexContent>...
18281 *
18282 * NOTE that the effective mixed was already set during parsing of
18283 * <complexType> and <complexContent>; its flag value is
18284 * XML_SCHEMAS_TYPE_MIXED.
18285 *
18286 * Compute the "effective content":
18287 * (2.1.1) + (2.1.2) + (2.1.3)
18288 */
18289 if ((particle == NULL) ||
18290 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18291 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18292 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18293 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18294 (particle->minOccurs == 0))) &&
18295 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18296 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18297 /*
18298 * SPEC (2.1.4) "If the `effective mixed` is true, then
18299 * a particle whose properties are as follows:..."
18300 *
18301 * Empty sequence model group with
18302 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18303 * NOTE that we sill assign it the <complexType> node to
18304 * somehow anchor it in the doc.
18305 */
18306 if ((particle == NULL) ||
18307 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18308 /*
18309 * Create the particle.
18310 */
18311 particle = xmlSchemaAddParticle(pctxt,
18312 type->node, 1, 1);
18313 if (particle == NULL)
18314 goto exit_failure;
18315 /*
18316 * Create the model group.
18317 */ /* URGENT TODO: avoid adding to pending items. */
18318 particle->children = (xmlSchemaTreeItemPtr)
18319 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18320 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18321 if (particle->children == NULL)
18322 goto exit_failure;
18323
18324 type->subtypes = (xmlSchemaTypePtr) particle;
18325 }
18326 dummySequence = 1;
18327 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18328 } else {
18329 /*
18330 * SPEC (2.1.5) "otherwise empty"
18331 */
18332 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18333 }
18334 } else {
18335 /*
18336 * SPEC (2.2) "otherwise the particle corresponding to the
18337 * <all>, <choice>, <group> or <sequence> among the
18338 * [children]."
18339 */
18340 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18341 }
18342 /*
18343 * Compute the "content type".
18344 */
18345 if (WXS_IS_RESTRICTION(type)) {
18346 /*
18347 * SPEC (3.1) "If <restriction>..."
18348 * (3.1.1) + (3.1.2) */
18349 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18350 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18351 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18352 }
18353 } else {
18354 /*
18355 * SPEC (3.2) "If <extension>..."
18356 */
18357 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18358 /*
18359 * SPEC (3.2.1)
18360 * "If the `effective content` is empty, then the
18361 * {content type} of the [...] base ..."
18362 */
18363 type->contentType = baseType->contentType;
18364 type->subtypes = baseType->subtypes;
18365 /*
18366 * Fixes bug #347316:
18367 * This is the case when the base type has a simple
18368 * type definition as content.
18369 */
18370 type->contentTypeDef = baseType->contentTypeDef;
18371 /*
18372 * NOTE that the effective mixed is ignored here.
18373 */
18374 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18375 /*
18376 * SPEC (3.2.2)
18377 */
18378 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18379 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18380 } else {
18381 /*
18382 * SPEC (3.2.3)
18383 */
18384 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18385 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18386 /*
18387 * "A model group whose {compositor} is sequence and whose
18388 * {particles} are..."
18389 */
18390 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18391 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18392 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18393 XML_SCHEMA_TYPE_ALL))
18394 {
18395 /*
18396 * SPEC cos-all-limited (1)
18397 */
18398 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18399 /* TODO: error code */
18400 XML_SCHEMAP_COS_ALL_LIMITED,
18401 WXS_ITEM_NODE(type), NULL,
18402 "The type has an 'all' model group in its "
18403 "{content type} and thus cannot be derived from "
18404 "a non-empty type, since this would produce a "
18405 "'sequence' model group containing the 'all' "
18406 "model group; 'all' model groups are not "
18407 "allowed to appear inside other model groups",
18408 NULL, NULL);
18409
18410 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18411 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18412 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18413 XML_SCHEMA_TYPE_ALL))
18414 {
18415 /*
18416 * SPEC cos-all-limited (1)
18417 */
18418 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18419 /* TODO: error code */
18420 XML_SCHEMAP_COS_ALL_LIMITED,
18421 WXS_ITEM_NODE(type), NULL,
18422 "A type cannot be derived by extension from a type "
18423 "which has an 'all' model group in its "
18424 "{content type}, since this would produce a "
18425 "'sequence' model group containing the 'all' "
18426 "model group; 'all' model groups are not "
18427 "allowed to appear inside other model groups",
18428 NULL, NULL);
18429
18430 } else if ((!dummySequence) && (baseType->subtypes != NULL)) {
18431 xmlSchemaTreeItemPtr effectiveContent =
18432 (xmlSchemaTreeItemPtr) type->subtypes;
18433 /*
18434 * Create the particle.
18435 */
18436 particle = xmlSchemaAddParticle(pctxt,
18437 type->node, 1, 1);
18438 if (particle == NULL)
18439 goto exit_failure;
18440 /*
18441 * Create the "sequence" model group.
18442 */
18443 particle->children = (xmlSchemaTreeItemPtr)
18444 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18445 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18446 if (particle->children == NULL)
18447 goto exit_failure;
18448 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18449 /*
18450 * SPEC "the particle of the {content type} of
18451 * the ... base ..."
18452 * Create a duplicate of the base type's particle
18453 * and assign its "term" to it.
18454 */
18455 particle->children->children =
18456 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18457 type->node,
18458 ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18459 ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18460 if (particle->children->children == NULL)
18461 goto exit_failure;
18462 particle = (xmlSchemaParticlePtr)
18463 particle->children->children;
18464 particle->children =
18465 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18466 /*
18467 * SPEC "followed by the `effective content`."
18468 */
18469 particle->next = effectiveContent;
18470 /*
18471 * This all will result in:
18472 * new-particle
18473 * --> new-sequence(
18474 * new-particle
18475 * --> base-model,
18476 * this-particle
18477 * --> this-model
18478 * )
18479 */
18480 } else {
18481 /*
18482 * This is the case when there is already an empty
18483 * <sequence> with minOccurs==maxOccurs==1.
18484 * Just add the base types's content type.
18485 * NOTE that, although we miss to add an intermediate
18486 * <sequence>, this should produce no difference to
18487 * neither the regex compilation of the content model,
18488 * nor to the complex type constraints.
18489 */
18490 particle->children->children =
18491 (xmlSchemaTreeItemPtr) baseType->subtypes;
18492 }
18493 }
18494 }
18495 }
18496 /*
18497 * Now fixup attribute uses:
18498 * - expand attr. group references
18499 * - intersect attribute wildcards
18500 * - inherit attribute uses of the base type
18501 * - inherit or union attr. wildcards if extending
18502 * - apply attr. use prohibitions if restricting
18503 */
18504 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18505 HFAILURE HERROR
18506 /*
18507 * Apply the complex type component constraints; this will not
18508 * check attributes, since this is done in
18509 * xmlSchemaFixupTypeAttributeUses().
18510 */
18511 res = xmlSchemaCheckCTComponent(pctxt, type);
18512 HFAILURE HERROR
18513
18514 if (olderrs != pctxt->nberrors)
18515 return(pctxt->err);
18516 else
18517 return(0);
18518
18519 exit_error:
18520 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18521 return(pctxt->err);
18522
18523 exit_failure:
18524 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18525 return(-1);
18526 }
18527
18528
18529 /**
18530 * xmlSchemaTypeFixup:
18531 * @typeDecl: the schema type definition
18532 * @ctxt: the schema parser context
18533 *
18534 * Fixes the content model of the type.
18535 * URGENT TODO: We need an int result!
18536 */
18537 static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,xmlSchemaAbstractCtxtPtr actxt)18538 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18539 xmlSchemaAbstractCtxtPtr actxt)
18540 {
18541 if (type == NULL)
18542 return(0);
18543 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18544 AERROR_INT("xmlSchemaTypeFixup",
18545 "this function needs a parser context");
18546 return(-1);
18547 }
18548 if (! WXS_IS_TYPE_NOT_FIXED(type))
18549 return(0);
18550 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18551 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18552 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18553 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18554 return(0);
18555 }
18556
18557 /**
18558 * xmlSchemaCheckFacet:
18559 * @facet: the facet
18560 * @typeDecl: the schema type definition
18561 * @pctxt: the schema parser context or NULL
18562 * @name: the optional name of the type
18563 *
18564 * Checks and computes the values of facets.
18565 *
18566 * Returns 0 if valid, a positive error code if not valid and
18567 * -1 in case of an internal or API error.
18568 */
18569 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt,const xmlChar * name ATTRIBUTE_UNUSED)18570 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18571 xmlSchemaTypePtr typeDecl,
18572 xmlSchemaParserCtxtPtr pctxt,
18573 const xmlChar * name ATTRIBUTE_UNUSED)
18574 {
18575 int ret = 0, ctxtGiven;
18576
18577 if ((facet == NULL) || (typeDecl == NULL))
18578 return(-1);
18579 /*
18580 * TODO: will the parser context be given if used from
18581 * the relaxNG module?
18582 */
18583 if (pctxt == NULL)
18584 ctxtGiven = 0;
18585 else
18586 ctxtGiven = 1;
18587
18588 switch (facet->type) {
18589 case XML_SCHEMA_FACET_MININCLUSIVE:
18590 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18591 case XML_SCHEMA_FACET_MAXINCLUSIVE:
18592 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18593 case XML_SCHEMA_FACET_ENUMERATION: {
18594 /*
18595 * Okay we need to validate the value
18596 * at that point.
18597 */
18598 xmlSchemaTypePtr base;
18599
18600 /* 4.3.5.5 Constraints on enumeration Schema Components
18601 * Schema Component Constraint: enumeration valid restriction
18602 * It is an `error` if any member of {value} is not in the
18603 * `value space` of {base type definition}.
18604 *
18605 * minInclusive, maxInclusive, minExclusive, maxExclusive:
18606 * The value `must` be in the
18607 * `value space` of the `base type`.
18608 */
18609 /*
18610 * This function is intended to deliver a compiled value
18611 * on the facet. In this implementation of XML Schemata the
18612 * type holding a facet, won't be a built-in type.
18613 * Thus to ensure that other API
18614 * calls (relaxng) do work, if the given type is a built-in
18615 * type, we will assume that the given built-in type *is
18616 * already* the base type.
18617 */
18618 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18619 base = typeDecl->baseType;
18620 if (base == NULL) {
18621 PERROR_INT("xmlSchemaCheckFacet",
18622 "a type user derived type has no base type");
18623 return (-1);
18624 }
18625 } else
18626 base = typeDecl;
18627
18628 if (! ctxtGiven) {
18629 /*
18630 * A context is needed if called from RelaxNG.
18631 */
18632 pctxt = xmlSchemaNewParserCtxt("*");
18633 if (pctxt == NULL)
18634 return (-1);
18635 }
18636 /*
18637 * NOTE: This call does not check the content nodes,
18638 * since they are not available:
18639 * facet->node is just the node holding the facet
18640 * definition, *not* the attribute holding the *value*
18641 * of the facet.
18642 */
18643 ret = xmlSchemaVCheckCVCSimpleType(
18644 ACTXT_CAST pctxt, facet->node, base,
18645 facet->value, &(facet->val), 1, 1, 0);
18646 if (ret != 0) {
18647 if (ret < 0) {
18648 /* No error message for RelaxNG. */
18649 if (ctxtGiven) {
18650 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18651 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18652 "Internal error: xmlSchemaCheckFacet, "
18653 "failed to validate the value '%s' of the "
18654 "facet '%s' against the base type",
18655 facet->value, xmlSchemaFacetTypeToString(facet->type));
18656 }
18657 goto internal_error;
18658 }
18659 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18660 /* No error message for RelaxNG. */
18661 if (ctxtGiven) {
18662 xmlChar *str = NULL;
18663
18664 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18665 ret, facet->node, WXS_BASIC_CAST facet,
18666 "The value '%s' of the facet does not validate "
18667 "against the base type '%s'",
18668 facet->value,
18669 xmlSchemaFormatQName(&str,
18670 base->targetNamespace, base->name));
18671 FREE_AND_NULL(str);
18672 }
18673 goto exit;
18674 } else if (facet->val == NULL) {
18675 if (ctxtGiven) {
18676 PERROR_INT("xmlSchemaCheckFacet",
18677 "value was not computed");
18678 }
18679 /* TODO */
18680 }
18681 break;
18682 }
18683 case XML_SCHEMA_FACET_PATTERN:
18684 facet->regexp = xmlRegexpCompile(facet->value);
18685 if (facet->regexp == NULL) {
18686 ret = XML_SCHEMAP_REGEXP_INVALID;
18687 /* No error message for RelaxNG. */
18688 if (ctxtGiven) {
18689 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18690 ret, facet->node, WXS_BASIC_CAST typeDecl,
18691 "The value '%s' of the facet 'pattern' is not a "
18692 "valid regular expression",
18693 facet->value, NULL);
18694 }
18695 }
18696 break;
18697 case XML_SCHEMA_FACET_TOTALDIGITS:
18698 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18699 case XML_SCHEMA_FACET_LENGTH:
18700 case XML_SCHEMA_FACET_MAXLENGTH:
18701 case XML_SCHEMA_FACET_MINLENGTH:
18702
18703 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18704 ret = xmlSchemaValidatePredefinedType(
18705 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18706 facet->value, &(facet->val));
18707 } else {
18708 ret = xmlSchemaValidatePredefinedType(
18709 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18710 facet->value, &(facet->val));
18711 }
18712 if (ret != 0) {
18713 if (ret < 0) {
18714 /* No error message for RelaxNG. */
18715 if (ctxtGiven) {
18716 PERROR_INT("xmlSchemaCheckFacet",
18717 "validating facet value");
18718 }
18719 goto internal_error;
18720 }
18721 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18722 /* No error message for RelaxNG. */
18723 if (ctxtGiven) {
18724 /* error code */
18725 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18726 ret, facet->node, WXS_BASIC_CAST typeDecl,
18727 "The value '%s' of the facet '%s' is not a valid '%s'",
18728 facet->value,
18729 xmlSchemaFacetTypeToString(facet->type),
18730 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18731 BAD_CAST "nonNegativeInteger" :
18732 BAD_CAST "positiveInteger",
18733 NULL);
18734 }
18735 }
18736 break;
18737
18738 case XML_SCHEMA_FACET_WHITESPACE:{
18739 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18740 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18741 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18742 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18743 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18744 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18745 } else {
18746 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18747 /* No error message for RelaxNG. */
18748 if (ctxtGiven) {
18749 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18750 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18751 ret, facet->node, WXS_BASIC_CAST typeDecl,
18752 "The value '%s' of the facet 'whitespace' is not "
18753 "valid", facet->value, NULL);
18754 }
18755 }
18756 }
18757 default:
18758 break;
18759 }
18760 exit:
18761 if ((! ctxtGiven) && (pctxt != NULL))
18762 xmlSchemaFreeParserCtxt(pctxt);
18763 return (ret);
18764 internal_error:
18765 if ((! ctxtGiven) && (pctxt != NULL))
18766 xmlSchemaFreeParserCtxt(pctxt);
18767 return (-1);
18768 }
18769
18770 /**
18771 * xmlSchemaCheckFacetValues:
18772 * @typeDecl: the schema type definition
18773 * @ctxt: the schema parser context
18774 *
18775 * Checks the default values types, especially for facets
18776 */
18777 static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt)18778 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18779 xmlSchemaParserCtxtPtr pctxt)
18780 {
18781 int res, olderrs = pctxt->nberrors;
18782 const xmlChar *name = typeDecl->name;
18783 /*
18784 * NOTE: It is intended to use the facets list, instead
18785 * of facetSet.
18786 */
18787 if (typeDecl->facets != NULL) {
18788 xmlSchemaFacetPtr facet = typeDecl->facets;
18789
18790 /*
18791 * Temporarily assign the "schema" to the validation context
18792 * of the parser context. This is needed for NOTATION validation.
18793 */
18794 if (pctxt->vctxt == NULL) {
18795 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18796 return(-1);
18797 }
18798 pctxt->vctxt->schema = pctxt->schema;
18799 while (facet != NULL) {
18800 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18801 HFAILURE
18802 facet = facet->next;
18803 }
18804 pctxt->vctxt->schema = NULL;
18805 }
18806 if (olderrs != pctxt->nberrors)
18807 return(pctxt->err);
18808 return(0);
18809 exit_failure:
18810 return(-1);
18811 }
18812
18813 /**
18814 * xmlSchemaGetCircModelGrDefRef:
18815 * @ctxtMGroup: the searched model group
18816 * @selfMGroup: the second searched model group
18817 * @particle: the first particle
18818 *
18819 * This one is intended to be used by
18820 * xmlSchemaCheckGroupDefCircular only.
18821 *
18822 * Returns the particle with the circular model group definition reference,
18823 * otherwise NULL.
18824 */
18825 static xmlSchemaTreeItemPtr
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,xmlSchemaTreeItemPtr particle)18826 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18827 xmlSchemaTreeItemPtr particle)
18828 {
18829 xmlSchemaTreeItemPtr circ = NULL;
18830 xmlSchemaTreeItemPtr term;
18831 xmlSchemaModelGroupDefPtr gdef;
18832
18833 for (; particle != NULL; particle = particle->next) {
18834 term = particle->children;
18835 if (term == NULL)
18836 continue;
18837 switch (term->type) {
18838 case XML_SCHEMA_TYPE_GROUP:
18839 gdef = (xmlSchemaModelGroupDefPtr) term;
18840 if (gdef == groupDef)
18841 return (particle);
18842 /*
18843 * Mark this model group definition to avoid infinite
18844 * recursion on circular references not yet examined.
18845 */
18846 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18847 continue;
18848 if (gdef->children != NULL) {
18849 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18850 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18851 gdef->children->children);
18852 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18853 if (circ != NULL)
18854 return (circ);
18855 }
18856 break;
18857 case XML_SCHEMA_TYPE_SEQUENCE:
18858 case XML_SCHEMA_TYPE_CHOICE:
18859 case XML_SCHEMA_TYPE_ALL:
18860 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18861 if (circ != NULL)
18862 return (circ);
18863 break;
18864 default:
18865 break;
18866 }
18867 }
18868 return (NULL);
18869 }
18870
18871 /**
18872 * xmlSchemaCheckGroupDefCircular:
18873 * @item: the model group definition
18874 * @ctxt: the parser context
18875 * @name: the name
18876 *
18877 * Checks for circular references to model group definitions.
18878 */
18879 static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,xmlSchemaParserCtxtPtr ctxt)18880 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18881 xmlSchemaParserCtxtPtr ctxt)
18882 {
18883 /*
18884 * Schema Component Constraint: Model Group Correct
18885 * 2 Circular groups are disallowed. That is, within the {particles}
18886 * of a group there must not be at any depth a particle whose {term}
18887 * is the group itself.
18888 */
18889 if ((item == NULL) ||
18890 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18891 (item->children == NULL))
18892 return;
18893 {
18894 xmlSchemaTreeItemPtr circ;
18895
18896 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18897 if (circ != NULL) {
18898 xmlChar *str = NULL;
18899 /*
18900 * TODO: The error report is not adequate: this constraint
18901 * is defined for model groups but not definitions, but since
18902 * there cannot be any circular model groups without a model group
18903 * definition (if not using a construction API), we check those
18904 * definitions only.
18905 */
18906 xmlSchemaPCustomErr(ctxt,
18907 XML_SCHEMAP_MG_PROPS_CORRECT_2,
18908 NULL, WXS_ITEM_NODE(circ),
18909 "Circular reference to the model group definition '%s' "
18910 "defined", xmlSchemaFormatQName(&str,
18911 item->targetNamespace, item->name));
18912 FREE_AND_NULL(str)
18913 /*
18914 * NOTE: We will cut the reference to avoid further
18915 * confusion of the processor. This is a fatal error.
18916 */
18917 circ->children = NULL;
18918 }
18919 }
18920 }
18921
18922 /**
18923 * xmlSchemaModelGroupToModelGroupDefFixup:
18924 * @ctxt: the parser context
18925 * @mg: the model group
18926 *
18927 * Assigns the model group of model group definitions to the "term"
18928 * of the referencing particle.
18929 * In xmlSchemaResolveModelGroupParticleReferences the model group
18930 * definitions were assigned to the "term", since needed for the
18931 * circularity check.
18932 *
18933 * Schema Component Constraint:
18934 * All Group Limited (cos-all-limited) (1.2)
18935 */
18936 static void
xmlSchemaModelGroupToModelGroupDefFixup(xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaModelGroupPtr mg)18937 xmlSchemaModelGroupToModelGroupDefFixup(
18938 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18939 xmlSchemaModelGroupPtr mg)
18940 {
18941 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18942
18943 while (particle != NULL) {
18944 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18945 ((WXS_PARTICLE_TERM(particle))->type !=
18946 XML_SCHEMA_TYPE_GROUP))
18947 {
18948 particle = WXS_PTC_CAST particle->next;
18949 continue;
18950 }
18951 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18952 /*
18953 * TODO: Remove the particle.
18954 */
18955 WXS_PARTICLE_TERM(particle) = NULL;
18956 particle = WXS_PTC_CAST particle->next;
18957 continue;
18958 }
18959 /*
18960 * Assign the model group to the {term} of the particle.
18961 */
18962 WXS_PARTICLE_TERM(particle) =
18963 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18964
18965 particle = WXS_PTC_CAST particle->next;
18966 }
18967 }
18968
18969 /**
18970 * xmlSchemaCheckAttrGroupCircularRecur:
18971 * @ctxtGr: the searched attribute group
18972 * @attr: the current attribute list to be processed
18973 *
18974 * This one is intended to be used by
18975 * xmlSchemaCheckAttrGroupCircular only.
18976 *
18977 * Returns the circular attribute group reference, otherwise NULL.
18978 */
18979 static xmlSchemaQNameRefPtr
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,xmlSchemaItemListPtr list)18980 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18981 xmlSchemaItemListPtr list)
18982 {
18983 xmlSchemaAttributeGroupPtr gr;
18984 xmlSchemaQNameRefPtr ref, circ;
18985 int i;
18986 /*
18987 * We will search for an attribute group reference which
18988 * references the context attribute group.
18989 */
18990 for (i = 0; i < list->nbItems; i++) {
18991 ref = list->items[i];
18992 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18993 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18994 (ref->item != NULL))
18995 {
18996 gr = WXS_ATTR_GROUP_CAST ref->item;
18997 if (gr == ctxtGr)
18998 return(ref);
18999 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19000 continue;
19001 /*
19002 * Mark as visited to avoid infinite recursion on
19003 * circular references not yet examined.
19004 */
19005 if ((gr->attrUses) &&
19006 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19007 {
19008 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19009 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19010 (xmlSchemaItemListPtr) gr->attrUses);
19011 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19012 if (circ != NULL)
19013 return (circ);
19014 }
19015
19016 }
19017 }
19018 return (NULL);
19019 }
19020
19021 /**
19022 * xmlSchemaCheckAttrGroupCircular:
19023 * attrGr: the attribute group definition
19024 * @ctxt: the parser context
19025 * @name: the name
19026 *
19027 * Checks for circular references of attribute groups.
19028 */
19029 static int
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,xmlSchemaParserCtxtPtr ctxt)19030 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19031 xmlSchemaParserCtxtPtr ctxt)
19032 {
19033 /*
19034 * Schema Representation Constraint:
19035 * Attribute Group Definition Representation OK
19036 * 3 Circular group reference is disallowed outside <redefine>.
19037 * That is, unless this element information item's parent is
19038 * <redefine>, then among the [children], if any, there must
19039 * not be an <attributeGroup> with ref [attribute] which resolves
19040 * to the component corresponding to this <attributeGroup>. Indirect
19041 * circularity is also ruled out. That is, when QName resolution
19042 * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19043 * any <attributeGroup>s with a ref [attribute] among the [children],
19044 * it must not be the case that a `QName` is encountered at any depth
19045 * which resolves to the component corresponding to this <attributeGroup>.
19046 */
19047 if (attrGr->attrUses == NULL)
19048 return(0);
19049 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19050 return(0);
19051 else {
19052 xmlSchemaQNameRefPtr circ;
19053
19054 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19055 (xmlSchemaItemListPtr) attrGr->attrUses);
19056 if (circ != NULL) {
19057 xmlChar *str = NULL;
19058 /*
19059 * TODO: Report the referenced attr group as QName.
19060 */
19061 xmlSchemaPCustomErr(ctxt,
19062 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19063 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19064 "Circular reference to the attribute group '%s' "
19065 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19066 FREE_AND_NULL(str);
19067 /*
19068 * NOTE: We will cut the reference to avoid further
19069 * confusion of the processor.
19070 * BADSPEC TODO: The spec should define how to process in this case.
19071 */
19072 circ->item = NULL;
19073 return(ctxt->err);
19074 }
19075 }
19076 return(0);
19077 }
19078
19079 static int
19080 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19081 xmlSchemaAttributeGroupPtr attrGr);
19082
19083 /**
19084 * xmlSchemaExpandAttributeGroupRefs:
19085 * @pctxt: the parser context
19086 * @node: the node of the component holding the attribute uses
19087 * @completeWild: the intersected wildcard to be returned
19088 * @list: the attribute uses
19089 *
19090 * Substitutes contained attribute group references
19091 * for their attribute uses. Wildcards are intersected.
19092 * Attribute use prohibitions are removed from the list
19093 * and returned via the @prohibs list.
19094 * Pointlessness of attr. prohibs, if a matching attr. decl
19095 * is existent a well, are checked.
19096 */
19097 static int
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr item,xmlSchemaWildcardPtr * completeWild,xmlSchemaItemListPtr list,xmlSchemaItemListPtr prohibs)19098 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19099 xmlSchemaBasicItemPtr item,
19100 xmlSchemaWildcardPtr *completeWild,
19101 xmlSchemaItemListPtr list,
19102 xmlSchemaItemListPtr prohibs)
19103 {
19104 xmlSchemaAttributeGroupPtr gr;
19105 xmlSchemaAttributeUsePtr use;
19106 xmlSchemaItemListPtr sublist;
19107 int i, j;
19108 int created = (*completeWild == NULL) ? 0 : 1;
19109
19110 if (prohibs)
19111 prohibs->nbItems = 0;
19112
19113 for (i = 0; i < list->nbItems; i++) {
19114 use = list->items[i];
19115
19116 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19117 if (prohibs == NULL) {
19118 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19119 "unexpected attr prohibition found");
19120 return(-1);
19121 }
19122 /*
19123 * Remove from attribute uses.
19124 */
19125 if (xmlSchemaItemListRemove(list, i) == -1)
19126 return(-1);
19127 i--;
19128 /*
19129 * Note that duplicate prohibitions were already
19130 * handled at parsing time.
19131 */
19132 /*
19133 * Add to list of prohibitions.
19134 */
19135 xmlSchemaItemListAddSize(prohibs, 2, use);
19136 continue;
19137 }
19138 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19139 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19140 {
19141 if ((WXS_QNAME_CAST use)->item == NULL)
19142 return(-1);
19143 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19144 /*
19145 * Expand the referenced attr. group.
19146 * TODO: remove this, this is done in a previous step, so
19147 * already done here.
19148 */
19149 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19150 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19151 return(-1);
19152 }
19153 /*
19154 * Build the 'complete' wildcard; i.e. intersect multiple
19155 * wildcards.
19156 */
19157 if (gr->attributeWildcard != NULL) {
19158 if (*completeWild == NULL) {
19159 *completeWild = gr->attributeWildcard;
19160 } else {
19161 if (! created) {
19162 xmlSchemaWildcardPtr tmpWild;
19163
19164 /*
19165 * Copy the first encountered wildcard as context,
19166 * except for the annotation.
19167 *
19168 * Although the complete wildcard might not correspond
19169 * to any node in the schema, we will anchor it on
19170 * the node of the owner component.
19171 */
19172 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19173 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19174 WXS_ITEM_NODE(item));
19175 if (tmpWild == NULL)
19176 return(-1);
19177 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19178 tmpWild, *completeWild) == -1)
19179 return (-1);
19180 tmpWild->processContents = (*completeWild)->processContents;
19181 *completeWild = tmpWild;
19182 created = 1;
19183 }
19184
19185 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19186 gr->attributeWildcard) == -1)
19187 return(-1);
19188 }
19189 }
19190 /*
19191 * Just remove the reference if the referenced group does not
19192 * contain any attribute uses.
19193 */
19194 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19195 if ((sublist == NULL) || sublist->nbItems == 0) {
19196 if (xmlSchemaItemListRemove(list, i) == -1)
19197 return(-1);
19198 i--;
19199 continue;
19200 }
19201 /*
19202 * Add the attribute uses.
19203 */
19204 list->items[i] = sublist->items[0];
19205 if (sublist->nbItems != 1) {
19206 for (j = 1; j < sublist->nbItems; j++) {
19207 i++;
19208 if (xmlSchemaItemListInsert(list,
19209 sublist->items[j], i) == -1)
19210 return(-1);
19211 }
19212 }
19213 }
19214
19215 }
19216 /*
19217 * Handle pointless prohibitions of declared attributes.
19218 */
19219 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19220 xmlSchemaAttributeUseProhibPtr prohib;
19221
19222 for (i = prohibs->nbItems -1; i >= 0; i--) {
19223 prohib = prohibs->items[i];
19224 for (j = 0; j < list->nbItems; j++) {
19225 use = list->items[j];
19226
19227 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19228 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19229 {
19230 xmlChar *str = NULL;
19231
19232 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19233 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19234 prohib->node, NULL,
19235 "Skipping pointless attribute use prohibition "
19236 "'%s', since a corresponding attribute use "
19237 "exists already in the type definition",
19238 xmlSchemaFormatQName(&str,
19239 prohib->targetNamespace, prohib->name),
19240 NULL, NULL);
19241 FREE_AND_NULL(str);
19242 /*
19243 * Remove the prohibition.
19244 */
19245 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19246 return(-1);
19247 break;
19248 }
19249 }
19250 }
19251 }
19252 return(0);
19253 }
19254
19255 /**
19256 * xmlSchemaAttributeGroupExpandRefs:
19257 * @pctxt: the parser context
19258 * @attrGr: the attribute group definition
19259 *
19260 * Computation of:
19261 * {attribute uses} property
19262 * {attribute wildcard} property
19263 *
19264 * Substitutes contained attribute group references
19265 * for their attribute uses. Wildcards are intersected.
19266 */
19267 static int
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19268 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19269 xmlSchemaAttributeGroupPtr attrGr)
19270 {
19271 if ((attrGr->attrUses == NULL) ||
19272 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19273 return(0);
19274
19275 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19276 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19277 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19278 return(-1);
19279 return(0);
19280 }
19281
19282 /**
19283 * xmlSchemaAttributeGroupExpandRefs:
19284 * @pctxt: the parser context
19285 * @attrGr: the attribute group definition
19286 *
19287 * Substitutes contained attribute group references
19288 * for their attribute uses. Wildcards are intersected.
19289 *
19290 * Schema Component Constraint:
19291 * Attribute Group Definition Properties Correct (ag-props-correct)
19292 */
19293 static int
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19294 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19295 xmlSchemaAttributeGroupPtr attrGr)
19296 {
19297 /*
19298 * SPEC ag-props-correct
19299 * (1) "The values of the properties of an attribute group definition
19300 * must be as described in the property tableau in The Attribute
19301 * Group Definition Schema Component ($3.6.1), modulo the impact of
19302 * Missing Sub-components ($5.3);"
19303 */
19304
19305 if ((attrGr->attrUses != NULL) &&
19306 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19307 {
19308 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19309 xmlSchemaAttributeUsePtr use, tmp;
19310 int i, j, hasId = 0;
19311
19312 for (i = uses->nbItems -1; i >= 0; i--) {
19313 use = uses->items[i];
19314 /*
19315 * SPEC ag-props-correct
19316 * (2) "Two distinct members of the {attribute uses} must not have
19317 * {attribute declaration}s both of whose {name}s match and whose
19318 * {target namespace}s are identical."
19319 */
19320 if (i > 0) {
19321 for (j = i -1; j >= 0; j--) {
19322 tmp = uses->items[j];
19323 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19324 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19325 (WXS_ATTRUSE_DECL_TNS(use) ==
19326 WXS_ATTRUSE_DECL_TNS(tmp)))
19327 {
19328 xmlChar *str = NULL;
19329
19330 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19331 XML_SCHEMAP_AG_PROPS_CORRECT,
19332 attrGr->node, WXS_BASIC_CAST attrGr,
19333 "Duplicate %s",
19334 xmlSchemaGetComponentDesignation(&str, use),
19335 NULL);
19336 FREE_AND_NULL(str);
19337 /*
19338 * Remove the duplicate.
19339 */
19340 if (xmlSchemaItemListRemove(uses, i) == -1)
19341 return(-1);
19342 goto next_use;
19343 }
19344 }
19345 }
19346 /*
19347 * SPEC ag-props-correct
19348 * (3) "Two distinct members of the {attribute uses} must not have
19349 * {attribute declaration}s both of whose {type definition}s are or
19350 * are derived from ID."
19351 * TODO: Does 'derived' include member-types of unions?
19352 */
19353 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19354 if (xmlSchemaIsDerivedFromBuiltInType(
19355 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19356 {
19357 if (hasId) {
19358 xmlChar *str = NULL;
19359
19360 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19361 XML_SCHEMAP_AG_PROPS_CORRECT,
19362 attrGr->node, WXS_BASIC_CAST attrGr,
19363 "There must not exist more than one attribute "
19364 "declaration of type 'xs:ID' "
19365 "(or derived from 'xs:ID'). The %s violates this "
19366 "constraint",
19367 xmlSchemaGetComponentDesignation(&str, use),
19368 NULL);
19369 FREE_AND_NULL(str);
19370 if (xmlSchemaItemListRemove(uses, i) == -1)
19371 return(-1);
19372 }
19373 hasId = 1;
19374 }
19375 }
19376 next_use: {}
19377 }
19378 }
19379 return(0);
19380 }
19381
19382 /**
19383 * xmlSchemaResolveAttrGroupReferences:
19384 * @attrgrpDecl: the schema attribute definition
19385 * @ctxt: the schema parser context
19386 * @name: the attribute name
19387 *
19388 * Resolves references to attribute group definitions.
19389 */
19390 static int
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,xmlSchemaParserCtxtPtr ctxt)19391 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19392 xmlSchemaParserCtxtPtr ctxt)
19393 {
19394 xmlSchemaAttributeGroupPtr group;
19395
19396 if (ref->item != NULL)
19397 return(0);
19398 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19399 ref->name,
19400 ref->targetNamespace);
19401 if (group == NULL) {
19402 xmlSchemaPResCompAttrErr(ctxt,
19403 XML_SCHEMAP_SRC_RESOLVE,
19404 NULL, ref->node,
19405 "ref", ref->name, ref->targetNamespace,
19406 ref->itemType, NULL);
19407 return(ctxt->err);
19408 }
19409 ref->item = WXS_BASIC_CAST group;
19410 return(0);
19411 }
19412
19413 /**
19414 * xmlSchemaCheckAttrPropsCorrect:
19415 * @item: an schema attribute declaration/use
19416 * @ctxt: a schema parser context
19417 * @name: the name of the attribute
19418 *
19419 *
19420 * Schema Component Constraint:
19421 * Attribute Declaration Properties Correct (a-props-correct)
19422 *
19423 * Validates the value constraints of an attribute declaration/use.
19424 * NOTE that this needs the simple type definitions to be already
19425 * built and checked.
19426 */
19427 static int
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributePtr attr)19428 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19429 xmlSchemaAttributePtr attr)
19430 {
19431
19432 /*
19433 * SPEC a-props-correct (1)
19434 * "The values of the properties of an attribute declaration must
19435 * be as described in the property tableau in The Attribute
19436 * Declaration Schema Component ($3.2.1), modulo the impact of
19437 * Missing Sub-components ($5.3)."
19438 */
19439
19440 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19441 return(0);
19442
19443 if (attr->defValue != NULL) {
19444 int ret;
19445
19446 /*
19447 * SPEC a-props-correct (3)
19448 * "If the {type definition} is or is derived from ID then there
19449 * must not be a {value constraint}."
19450 */
19451 if (xmlSchemaIsDerivedFromBuiltInType(
19452 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19453 {
19454 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19455 XML_SCHEMAP_A_PROPS_CORRECT_3,
19456 NULL, WXS_BASIC_CAST attr,
19457 "Value constraints are not allowed if the type definition "
19458 "is or is derived from xs:ID",
19459 NULL, NULL);
19460 return(pctxt->err);
19461 }
19462 /*
19463 * SPEC a-props-correct (2)
19464 * "if there is a {value constraint}, the canonical lexical
19465 * representation of its value must be `valid` with respect
19466 * to the {type definition} as defined in String Valid ($3.14.4)."
19467 * TODO: Don't care about the *canonical* stuff here, this requirement
19468 * will be removed in WXS 1.1 anyway.
19469 */
19470 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19471 attr->node, WXS_ATTR_TYPEDEF(attr),
19472 attr->defValue, &(attr->defVal),
19473 1, 1, 0);
19474 if (ret != 0) {
19475 if (ret < 0) {
19476 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19477 "calling xmlSchemaVCheckCVCSimpleType()");
19478 return(-1);
19479 }
19480 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19481 XML_SCHEMAP_A_PROPS_CORRECT_2,
19482 NULL, WXS_BASIC_CAST attr,
19483 "The value of the value constraint is not valid",
19484 NULL, NULL);
19485 return(pctxt->err);
19486 }
19487 }
19488
19489 return(0);
19490 }
19491
19492 static xmlSchemaElementPtr
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,xmlSchemaElementPtr ancestor)19493 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19494 xmlSchemaElementPtr ancestor)
19495 {
19496 xmlSchemaElementPtr ret;
19497
19498 if (WXS_SUBST_HEAD(ancestor) == NULL)
19499 return (NULL);
19500 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19501 return (ancestor);
19502
19503 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19504 return (NULL);
19505 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19506 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19507 WXS_SUBST_HEAD(ancestor));
19508 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19509
19510 return (ret);
19511 }
19512
19513 /**
19514 * xmlSchemaCheckElemPropsCorrect:
19515 * @ctxt: a schema parser context
19516 * @decl: the element declaration
19517 * @name: the name of the attribute
19518 *
19519 * Schema Component Constraint:
19520 * Element Declaration Properties Correct (e-props-correct)
19521 *
19522 * STATUS:
19523 * missing: (6)
19524 */
19525 static int
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr elemDecl)19526 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19527 xmlSchemaElementPtr elemDecl)
19528 {
19529 int ret = 0;
19530 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19531 /*
19532 * SPEC (1) "The values of the properties of an element declaration
19533 * must be as described in the property tableau in The Element
19534 * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19535 * Sub-components ($5.3)."
19536 */
19537 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19538 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19539
19540 xmlSchemaCheckElementDeclComponent(head, pctxt);
19541 /*
19542 * SPEC (3) "If there is a non-`absent` {substitution group
19543 * affiliation}, then {scope} must be global."
19544 */
19545 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19546 xmlSchemaPCustomErr(pctxt,
19547 XML_SCHEMAP_E_PROPS_CORRECT_3,
19548 WXS_BASIC_CAST elemDecl, NULL,
19549 "Only global element declarations can have a "
19550 "substitution group affiliation", NULL);
19551 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19552 }
19553 /*
19554 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19555 * That is, it must not be possible to return to an element declaration
19556 * by repeatedly following the {substitution group affiliation}
19557 * property."
19558 */
19559 if (head == elemDecl)
19560 circ = head;
19561 else if (WXS_SUBST_HEAD(head) != NULL)
19562 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19563 else
19564 circ = NULL;
19565 if (circ != NULL) {
19566 xmlChar *strA = NULL, *strB = NULL;
19567
19568 xmlSchemaPCustomErrExt(pctxt,
19569 XML_SCHEMAP_E_PROPS_CORRECT_6,
19570 WXS_BASIC_CAST circ, NULL,
19571 "The element declaration '%s' defines a circular "
19572 "substitution group to element declaration '%s'",
19573 xmlSchemaGetComponentQName(&strA, circ),
19574 xmlSchemaGetComponentQName(&strB, head),
19575 NULL);
19576 FREE_AND_NULL(strA)
19577 FREE_AND_NULL(strB)
19578 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19579 }
19580 /*
19581 * SPEC (4) "If there is a {substitution group affiliation},
19582 * the {type definition}
19583 * of the element declaration must be validly derived from the {type
19584 * definition} of the {substitution group affiliation}, given the value
19585 * of the {substitution group exclusions} of the {substitution group
19586 * affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19587 * (if the {type definition} is complex) or as defined in
19588 * Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19589 * simple)."
19590 *
19591 * NOTE: {substitution group exclusions} means the values of the
19592 * attribute "final".
19593 */
19594
19595 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19596 int set = 0;
19597
19598 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19599 set |= SUBSET_EXTENSION;
19600 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19601 set |= SUBSET_RESTRICTION;
19602
19603 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19604 WXS_ELEM_TYPEDEF(head), set) != 0) {
19605 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19606
19607 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19608 xmlSchemaPCustomErrExt(pctxt,
19609 XML_SCHEMAP_E_PROPS_CORRECT_4,
19610 WXS_BASIC_CAST elemDecl, NULL,
19611 "The type definition '%s' was "
19612 "either rejected by the substitution group "
19613 "affiliation '%s', or not validly derived from its type "
19614 "definition '%s'",
19615 xmlSchemaGetComponentQName(&strA, typeDef),
19616 xmlSchemaGetComponentQName(&strB, head),
19617 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19618 FREE_AND_NULL(strA)
19619 FREE_AND_NULL(strB)
19620 FREE_AND_NULL(strC)
19621 }
19622 }
19623 }
19624 /*
19625 * SPEC (5) "If the {type definition} or {type definition}'s
19626 * {content type}
19627 * is or is derived from ID then there must not be a {value constraint}.
19628 * Note: The use of ID as a type definition for elements goes beyond
19629 * XML 1.0, and should be avoided if backwards compatibility is desired"
19630 */
19631 if ((elemDecl->value != NULL) &&
19632 ((WXS_IS_SIMPLE(typeDef) &&
19633 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19634 (WXS_IS_COMPLEX(typeDef) &&
19635 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19636 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19637 XML_SCHEMAS_ID)))) {
19638
19639 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19640 xmlSchemaPCustomErr(pctxt,
19641 XML_SCHEMAP_E_PROPS_CORRECT_5,
19642 WXS_BASIC_CAST elemDecl, NULL,
19643 "The type definition (or type definition's content type) is or "
19644 "is derived from ID; value constraints are not allowed in "
19645 "conjunction with such a type definition", NULL);
19646 } else if (elemDecl->value != NULL) {
19647 int vcret;
19648 xmlNodePtr node = NULL;
19649
19650 /*
19651 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19652 * representation of its value must be `valid` with respect to the
19653 * {type definition} as defined in Element Default Valid (Immediate)
19654 * ($3.3.6)."
19655 */
19656 if (typeDef == NULL) {
19657 xmlSchemaPErr(pctxt, elemDecl->node,
19658 XML_SCHEMAP_INTERNAL,
19659 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19660 "type is missing... skipping validation of "
19661 "the value constraint", NULL, NULL);
19662 return (-1);
19663 }
19664 if (elemDecl->node != NULL) {
19665 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19666 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19667 BAD_CAST "fixed");
19668 else
19669 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19670 BAD_CAST "default");
19671 }
19672 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19673 typeDef, elemDecl->value, &(elemDecl->defVal));
19674 if (vcret != 0) {
19675 if (vcret < 0) {
19676 PERROR_INT("xmlSchemaElemCheckValConstr",
19677 "failed to validate the value constraint of an "
19678 "element declaration");
19679 return (-1);
19680 }
19681 return (vcret);
19682 }
19683 }
19684
19685 return (ret);
19686 }
19687
19688 /**
19689 * xmlSchemaCheckElemSubstGroup:
19690 * @ctxt: a schema parser context
19691 * @decl: the element declaration
19692 * @name: the name of the attribute
19693 *
19694 * Schema Component Constraint:
19695 * Substitution Group (cos-equiv-class)
19696 *
19697 * In Libxml2 the subst. groups will be precomputed, in terms of that
19698 * a list will be built for each subst. group head, holding all direct
19699 * referents to this head.
19700 * NOTE that this function needs:
19701 * 1. circular subst. groups to be checked beforehand
19702 * 2. the declaration's type to be derived from the head's type
19703 *
19704 * STATUS:
19705 *
19706 */
19707 static void
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaElementPtr elemDecl)19708 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19709 xmlSchemaElementPtr elemDecl)
19710 {
19711 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19712 /* SPEC (1) "Its {abstract} is false." */
19713 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19714 return;
19715 {
19716 xmlSchemaElementPtr head;
19717 xmlSchemaTypePtr headType, type;
19718 int set, methSet;
19719 /*
19720 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19721 * {disallowed substitutions} as the blocking constraint, as defined in
19722 * Substitution Group OK (Transitive) ($3.3.6)."
19723 */
19724 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19725 head = WXS_SUBST_HEAD(head)) {
19726 set = 0;
19727 methSet = 0;
19728 /*
19729 * The blocking constraints.
19730 */
19731 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19732 continue;
19733 headType = head->subtypes;
19734 type = elemDecl->subtypes;
19735 if (headType == type)
19736 goto add_member;
19737 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19738 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19739 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19740 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19741 /*
19742 * SPEC: Substitution Group OK (Transitive) (2.3)
19743 * "The set of all {derivation method}s involved in the
19744 * derivation of D's {type definition} from C's {type definition}
19745 * does not intersect with the union of the blocking constraint,
19746 * C's {prohibited substitutions} (if C is complex, otherwise the
19747 * empty set) and the {prohibited substitutions} (respectively the
19748 * empty set) of any intermediate {type definition}s in the
19749 * derivation of D's {type definition} from C's {type definition}."
19750 */
19751 /*
19752 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19753 * subst.head axis, the methSet does not need to be computed for
19754 * the full depth over and over.
19755 */
19756 /*
19757 * The set of all {derivation method}s involved in the derivation
19758 */
19759 while ((type != NULL) && (type != headType) &&
19760 (type != type->baseType)) {
19761 if ((WXS_IS_EXTENSION(type)) &&
19762 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19763 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19764
19765 if (WXS_IS_RESTRICTION(type) &&
19766 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19767 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19768
19769 type = type->baseType;
19770 }
19771 /*
19772 * The {prohibited substitutions} of all intermediate types +
19773 * the head's type.
19774 */
19775 type = elemDecl->subtypes->baseType;
19776 while (type != NULL) {
19777 if (WXS_IS_COMPLEX(type)) {
19778 if ((type->flags &
19779 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19780 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19781 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19782 if ((type->flags &
19783 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19784 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19785 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19786 } else
19787 break;
19788 if (type == headType)
19789 break;
19790 type = type->baseType;
19791 }
19792 if ((set != 0) &&
19793 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19794 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19795 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19796 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19797 continue;
19798 }
19799 add_member:
19800 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19801 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19802 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19803 }
19804 }
19805 }
19806
19807 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19808 /**
19809 * xmlSchemaCheckElementDeclComponent
19810 * @pctxt: the schema parser context
19811 * @ctxtComponent: the context component (an element declaration)
19812 * @ctxtParticle: the first particle of the context component
19813 * @searchParticle: the element declaration particle to be analysed
19814 *
19815 * Schema Component Constraint: Element Declarations Consistent
19816 */
19817 static int
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ctxtComponent,xmlSchemaParticlePtr ctxtParticle,xmlSchemaParticlePtr searchParticle,xmlSchemaParticlePtr curParticle,int search)19818 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19819 xmlSchemaBasicItemPtr ctxtComponent,
19820 xmlSchemaParticlePtr ctxtParticle,
19821 xmlSchemaParticlePtr searchParticle,
19822 xmlSchemaParticlePtr curParticle,
19823 int search)
19824 {
19825 return(0);
19826
19827 int ret = 0;
19828 xmlSchemaParticlePtr cur = curParticle;
19829 if (curParticle == NULL) {
19830 return(0);
19831 }
19832 if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19833 /*
19834 * Just return in this case. A missing "term" of the particle
19835 * might arise due to an invalid "term" component.
19836 */
19837 return(0);
19838 }
19839 while (cur != NULL) {
19840 switch (WXS_PARTICLE_TERM(cur)->type) {
19841 case XML_SCHEMA_TYPE_ANY:
19842 break;
19843 case XML_SCHEMA_TYPE_ELEMENT:
19844 if (search == 0) {
19845 ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19846 ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19847 if (ret != 0)
19848 return(ret);
19849 } else {
19850 xmlSchemaElementPtr elem =
19851 WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19852 /*
19853 * SPEC Element Declarations Consistent:
19854 * "If the {particles} contains, either directly,
19855 * indirectly (that is, within the {particles} of a
19856 * contained model group, recursively) or `implicitly`
19857 * two or more element declaration particles with
19858 * the same {name} and {target namespace}, then
19859 * all their type definitions must be the same
19860 * top-level definition [...]"
19861 */
19862 if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19863 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19864 xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19865 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19866 {
19867 xmlChar *strA = NULL, *strB = NULL;
19868
19869 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19870 /* TODO: error code */
19871 XML_SCHEMAP_COS_NONAMBIG,
19872 WXS_ITEM_NODE(cur), NULL,
19873 "In the content model of %s, there are multiple "
19874 "element declarations for '%s' with different "
19875 "type definitions",
19876 xmlSchemaGetComponentDesignation(&strA,
19877 ctxtComponent),
19878 xmlSchemaFormatQName(&strB,
19879 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19880 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19881 FREE_AND_NULL(strA);
19882 FREE_AND_NULL(strB);
19883 return(XML_SCHEMAP_COS_NONAMBIG);
19884 }
19885 }
19886 break;
19887 case XML_SCHEMA_TYPE_SEQUENCE: {
19888 break;
19889 }
19890 case XML_SCHEMA_TYPE_CHOICE:{
19891 /*
19892 xmlSchemaTreeItemPtr sub;
19893
19894 sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
19895 while (sub != NULL) {
19896 ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19897 ctxtParticle, ctxtElem);
19898 if (ret != 0)
19899 return(ret);
19900 sub = sub->next;
19901 }
19902 */
19903 break;
19904 }
19905 case XML_SCHEMA_TYPE_ALL:
19906 break;
19907 case XML_SCHEMA_TYPE_GROUP:
19908 break;
19909 default:
19910 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19911 "xmlSchemaCheckElementDeclConsistent",
19912 "found unexpected term of type '%s' in content model",
19913 WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19914 return(-1);
19915 }
19916 cur = (xmlSchemaParticlePtr) cur->next;
19917 }
19918
19919 exit:
19920 return(ret);
19921 }
19922 #endif
19923
19924 /**
19925 * xmlSchemaCheckElementDeclComponent
19926 * @item: an schema element declaration/particle
19927 * @ctxt: a schema parser context
19928 * @name: the name of the attribute
19929 *
19930 * Validates the value constraints of an element declaration.
19931 * Adds substitution group members.
19932 */
19933 static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)19934 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19935 xmlSchemaParserCtxtPtr ctxt)
19936 {
19937 if (elemDecl == NULL)
19938 return;
19939 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19940 return;
19941 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19942 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19943 /*
19944 * Adds substitution group members.
19945 */
19946 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19947 }
19948 }
19949
19950 /**
19951 * xmlSchemaResolveModelGroupParticleReferences:
19952 * @particle: a particle component
19953 * @ctxt: a parser context
19954 *
19955 * Resolves references of a model group's {particles} to
19956 * model group definitions and to element declarations.
19957 */
19958 static void
xmlSchemaResolveModelGroupParticleReferences(xmlSchemaParserCtxtPtr ctxt,xmlSchemaModelGroupPtr mg)19959 xmlSchemaResolveModelGroupParticleReferences(
19960 xmlSchemaParserCtxtPtr ctxt,
19961 xmlSchemaModelGroupPtr mg)
19962 {
19963 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19964 xmlSchemaQNameRefPtr ref;
19965 xmlSchemaBasicItemPtr refItem;
19966
19967 /*
19968 * URGENT TODO: Test this.
19969 */
19970 while (particle != NULL) {
19971 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19972 ((WXS_PARTICLE_TERM(particle))->type !=
19973 XML_SCHEMA_EXTRA_QNAMEREF))
19974 {
19975 goto next_particle;
19976 }
19977 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
19978 /*
19979 * Resolve the reference.
19980 * NULL the {term} by default.
19981 */
19982 particle->children = NULL;
19983
19984 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19985 ref->itemType, ref->name, ref->targetNamespace);
19986 if (refItem == NULL) {
19987 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
19988 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
19989 ref->targetNamespace, ref->itemType, NULL);
19990 /* TODO: remove the particle. */
19991 goto next_particle;
19992 }
19993 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19994 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19995 /* TODO: remove the particle. */
19996 goto next_particle;
19997 /*
19998 * NOTE that we will assign the model group definition
19999 * itself to the "term" of the particle. This will ease
20000 * the check for circular model group definitions. After
20001 * that the "term" will be assigned the model group of the
20002 * model group definition.
20003 */
20004 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20005 XML_SCHEMA_TYPE_ALL) {
20006 /*
20007 * SPEC cos-all-limited (1)
20008 * SPEC cos-all-limited (1.2)
20009 * "It appears only as the value of one or both of the
20010 * following properties:"
20011 * (1.1) "the {model group} property of a model group
20012 * definition."
20013 * (1.2) "the {term} property of a particle [... of] the "
20014 * {content type} of a complex type definition."
20015 */
20016 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20017 /* TODO: error code */
20018 XML_SCHEMAP_COS_ALL_LIMITED,
20019 WXS_ITEM_NODE(particle), NULL,
20020 "A model group definition is referenced, but "
20021 "it contains an 'all' model group, which "
20022 "cannot be contained by model groups",
20023 NULL, NULL);
20024 /* TODO: remove the particle. */
20025 goto next_particle;
20026 }
20027 particle->children = (xmlSchemaTreeItemPtr) refItem;
20028 } else {
20029 /*
20030 * TODO: Are referenced element declarations the only
20031 * other components we expect here?
20032 */
20033 particle->children = (xmlSchemaTreeItemPtr) refItem;
20034 }
20035 next_particle:
20036 particle = WXS_PTC_CAST particle->next;
20037 }
20038 }
20039
20040 static int
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,xmlSchemaValPtr y)20041 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20042 xmlSchemaValPtr y)
20043 {
20044 xmlSchemaTypePtr tx, ty, ptx, pty;
20045 int ret;
20046
20047 while (x != NULL) {
20048 /* Same types. */
20049 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20050 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20051 ptx = xmlSchemaGetPrimitiveType(tx);
20052 pty = xmlSchemaGetPrimitiveType(ty);
20053 /*
20054 * (1) if a datatype T' is `derived` by `restriction` from an
20055 * atomic datatype T then the `value space` of T' is a subset of
20056 * the `value space` of T. */
20057 /*
20058 * (2) if datatypes T' and T'' are `derived` by `restriction`
20059 * from a common atomic ancestor T then the `value space`s of T'
20060 * and T'' may overlap.
20061 */
20062 if (ptx != pty)
20063 return(0);
20064 /*
20065 * We assume computed values to be normalized, so do a fast
20066 * string comparison for string based types.
20067 */
20068 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20069 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20070 if (! xmlStrEqual(
20071 xmlSchemaValueGetAsString(x),
20072 xmlSchemaValueGetAsString(y)))
20073 return (0);
20074 } else {
20075 ret = xmlSchemaCompareValuesWhtsp(
20076 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20077 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20078 if (ret == -2)
20079 return(-1);
20080 if (ret != 0)
20081 return(0);
20082 }
20083 /*
20084 * Lists.
20085 */
20086 x = xmlSchemaValueGetNext(x);
20087 if (x != NULL) {
20088 y = xmlSchemaValueGetNext(y);
20089 if (y == NULL)
20090 return (0);
20091 } else if (xmlSchemaValueGetNext(y) != NULL)
20092 return (0);
20093 else
20094 return (1);
20095 }
20096 return (0);
20097 }
20098
20099 /**
20100 * xmlSchemaResolveAttrUseReferences:
20101 * @item: an attribute use
20102 * @ctxt: a parser context
20103 *
20104 * Resolves the referenced attribute declaration.
20105 */
20106 static int
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,xmlSchemaParserCtxtPtr ctxt)20107 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20108 xmlSchemaParserCtxtPtr ctxt)
20109 {
20110 if ((ctxt == NULL) || (ause == NULL))
20111 return(-1);
20112 if ((ause->attrDecl == NULL) ||
20113 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20114 return(0);
20115
20116 {
20117 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20118
20119 /*
20120 * TODO: Evaluate, what errors could occur if the declaration is not
20121 * found.
20122 */
20123 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20124 ref->name, ref->targetNamespace);
20125 if (ause->attrDecl == NULL) {
20126 xmlSchemaPResCompAttrErr(ctxt,
20127 XML_SCHEMAP_SRC_RESOLVE,
20128 WXS_BASIC_CAST ause, ause->node,
20129 "ref", ref->name, ref->targetNamespace,
20130 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20131 return(ctxt->err);;
20132 }
20133 }
20134 return(0);
20135 }
20136
20137 /**
20138 * xmlSchemaCheckAttrUsePropsCorrect:
20139 * @ctxt: a parser context
20140 * @use: an attribute use
20141 *
20142 * Schema Component Constraint:
20143 * Attribute Use Correct (au-props-correct)
20144 *
20145 */
20146 static int
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaAttributeUsePtr use)20147 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20148 xmlSchemaAttributeUsePtr use)
20149 {
20150 if ((ctxt == NULL) || (use == NULL))
20151 return(-1);
20152 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20153 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20154 return(0);
20155
20156 /*
20157 * SPEC au-props-correct (1)
20158 * "The values of the properties of an attribute use must be as
20159 * described in the property tableau in The Attribute Use Schema
20160 * Component ($3.5.1), modulo the impact of Missing
20161 * Sub-components ($5.3)."
20162 */
20163
20164 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20165 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20166 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20167 {
20168 xmlSchemaPCustomErr(ctxt,
20169 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20170 WXS_BASIC_CAST use, NULL,
20171 "The attribute declaration has a 'fixed' value constraint "
20172 ", thus the attribute use must also have a 'fixed' value "
20173 "constraint",
20174 NULL);
20175 return(ctxt->err);
20176 }
20177 /*
20178 * Compute and check the value constraint's value.
20179 */
20180 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20181 int ret;
20182 /*
20183 * TODO: The spec seems to be missing a check of the
20184 * value constraint of the attribute use. We will do it here.
20185 */
20186 /*
20187 * SPEC a-props-correct (3)
20188 */
20189 if (xmlSchemaIsDerivedFromBuiltInType(
20190 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20191 {
20192 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20193 XML_SCHEMAP_AU_PROPS_CORRECT,
20194 NULL, WXS_BASIC_CAST use,
20195 "Value constraints are not allowed if the type definition "
20196 "is or is derived from xs:ID",
20197 NULL, NULL);
20198 return(ctxt->err);
20199 }
20200
20201 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20202 use->node, WXS_ATTRUSE_TYPEDEF(use),
20203 use->defValue, &(use->defVal),
20204 1, 1, 0);
20205 if (ret != 0) {
20206 if (ret < 0) {
20207 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20208 "calling xmlSchemaVCheckCVCSimpleType()");
20209 return(-1);
20210 }
20211 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20212 XML_SCHEMAP_AU_PROPS_CORRECT,
20213 NULL, WXS_BASIC_CAST use,
20214 "The value of the value constraint is not valid",
20215 NULL, NULL);
20216 return(ctxt->err);
20217 }
20218 }
20219 /*
20220 * SPEC au-props-correct (2)
20221 * "If the {attribute declaration} has a fixed
20222 * {value constraint}, then if the attribute use itself has a
20223 * {value constraint}, it must also be fixed and its value must match
20224 * that of the {attribute declaration}'s {value constraint}."
20225 */
20226 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20227 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20228 {
20229 if (! xmlSchemaAreValuesEqual(use->defVal,
20230 (WXS_ATTRUSE_DECL(use))->defVal))
20231 {
20232 xmlSchemaPCustomErr(ctxt,
20233 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20234 WXS_BASIC_CAST use, NULL,
20235 "The 'fixed' value constraint of the attribute use "
20236 "must match the attribute declaration's value "
20237 "constraint '%s'",
20238 (WXS_ATTRUSE_DECL(use))->defValue);
20239 }
20240 return(ctxt->err);
20241 }
20242 return(0);
20243 }
20244
20245
20246
20247
20248 /**
20249 * xmlSchemaResolveAttrTypeReferences:
20250 * @item: an attribute declaration
20251 * @ctxt: a parser context
20252 *
20253 * Resolves the referenced type definition component.
20254 */
20255 static int
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,xmlSchemaParserCtxtPtr ctxt)20256 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20257 xmlSchemaParserCtxtPtr ctxt)
20258 {
20259 /*
20260 * The simple type definition corresponding to the <simpleType> element
20261 * information item in the [children], if present, otherwise the simple
20262 * type definition `resolved` to by the `actual value` of the type
20263 * [attribute], if present, otherwise the `simple ur-type definition`.
20264 */
20265 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20266 return(0);
20267 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20268 if (item->subtypes != NULL)
20269 return(0);
20270 if (item->typeName != NULL) {
20271 xmlSchemaTypePtr type;
20272
20273 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20274 item->typeNs);
20275 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20276 xmlSchemaPResCompAttrErr(ctxt,
20277 XML_SCHEMAP_SRC_RESOLVE,
20278 WXS_BASIC_CAST item, item->node,
20279 "type", item->typeName, item->typeNs,
20280 XML_SCHEMA_TYPE_SIMPLE, NULL);
20281 return(ctxt->err);
20282 } else
20283 item->subtypes = type;
20284
20285 } else {
20286 /*
20287 * The type defaults to the xs:anySimpleType.
20288 */
20289 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20290 }
20291 return(0);
20292 }
20293
20294 /**
20295 * xmlSchemaResolveIDCKeyReferences:
20296 * @idc: the identity-constraint definition
20297 * @ctxt: the schema parser context
20298 * @name: the attribute name
20299 *
20300 * Resolve keyRef references to key/unique IDCs.
20301 * Schema Component Constraint:
20302 * Identity-constraint Definition Properties Correct (c-props-correct)
20303 */
20304 static int
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,xmlSchemaParserCtxtPtr pctxt)20305 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20306 xmlSchemaParserCtxtPtr pctxt)
20307 {
20308 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20309 return(0);
20310 if (idc->ref->name != NULL) {
20311 idc->ref->item = (xmlSchemaBasicItemPtr)
20312 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20313 idc->ref->targetNamespace);
20314 if (idc->ref->item == NULL) {
20315 /*
20316 * TODO: It is actually not an error to fail to resolve
20317 * at this stage. BUT we need to be that strict!
20318 */
20319 xmlSchemaPResCompAttrErr(pctxt,
20320 XML_SCHEMAP_SRC_RESOLVE,
20321 WXS_BASIC_CAST idc, idc->node,
20322 "refer", idc->ref->name,
20323 idc->ref->targetNamespace,
20324 XML_SCHEMA_TYPE_IDC_KEY, NULL);
20325 return(pctxt->err);
20326 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20327 /*
20328 * SPEC c-props-correct (1)
20329 */
20330 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20331 XML_SCHEMAP_C_PROPS_CORRECT,
20332 NULL, WXS_BASIC_CAST idc,
20333 "The keyref references a keyref",
20334 NULL, NULL);
20335 idc->ref->item = NULL;
20336 return(pctxt->err);
20337 } else {
20338 if (idc->nbFields !=
20339 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20340 xmlChar *str = NULL;
20341 xmlSchemaIDCPtr refer;
20342
20343 refer = (xmlSchemaIDCPtr) idc->ref->item;
20344 /*
20345 * SPEC c-props-correct(2)
20346 * "If the {identity-constraint category} is keyref,
20347 * the cardinality of the {fields} must equal that of
20348 * the {fields} of the {referenced key}.
20349 */
20350 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20351 XML_SCHEMAP_C_PROPS_CORRECT,
20352 NULL, WXS_BASIC_CAST idc,
20353 "The cardinality of the keyref differs from the "
20354 "cardinality of the referenced key/unique '%s'",
20355 xmlSchemaFormatQName(&str, refer->targetNamespace,
20356 refer->name),
20357 NULL);
20358 FREE_AND_NULL(str)
20359 return(pctxt->err);
20360 }
20361 }
20362 }
20363 return(0);
20364 }
20365
20366 static int
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,xmlSchemaParserCtxtPtr pctxt)20367 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20368 xmlSchemaParserCtxtPtr pctxt)
20369 {
20370 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20371 prohib->targetNamespace) == NULL) {
20372
20373 xmlSchemaPResCompAttrErr(pctxt,
20374 XML_SCHEMAP_SRC_RESOLVE,
20375 NULL, prohib->node,
20376 "ref", prohib->name, prohib->targetNamespace,
20377 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20378 return(XML_SCHEMAP_SRC_RESOLVE);
20379 }
20380 return(0);
20381 }
20382
20383 #define WXS_REDEFINED_TYPE(c) \
20384 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20385
20386 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20387 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20388
20389 #define WXS_REDEFINED_ATTR_GROUP(c) \
20390 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20391
20392 static int
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)20393 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20394 {
20395 int err = 0;
20396 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20397 xmlSchemaBasicItemPtr prev, item;
20398 int wasRedefined;
20399
20400 if (redef == NULL)
20401 return(0);
20402
20403 do {
20404 item = redef->item;
20405 /*
20406 * First try to locate the redefined component in the
20407 * schema graph starting with the redefined schema.
20408 * NOTE: According to this schema bug entry:
20409 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20410 * it's not clear if the referenced component needs to originate
20411 * from the <redefine>d schema _document_ or the schema; the latter
20412 * would include all imported and included sub-schemas of the
20413 * <redefine>d schema. Currently the latter approach is used.
20414 * SUPPLEMENT: It seems that the WG moves towards the latter
20415 * approach, so we are doing it right.
20416 *
20417 */
20418 prev = xmlSchemaFindRedefCompInGraph(
20419 redef->targetBucket, item->type,
20420 redef->refName, redef->refTargetNs);
20421 if (prev == NULL) {
20422 xmlChar *str = NULL;
20423 xmlNodePtr node;
20424
20425 /*
20426 * SPEC src-redefine:
20427 * (6.2.1) "The `actual value` of its own name attribute plus
20428 * target namespace must successfully `resolve` to a model
20429 * group definition in I."
20430 * (7.2.1) "The `actual value` of its own name attribute plus
20431 * target namespace must successfully `resolve` to an attribute
20432 * group definition in I."
20433
20434 *
20435 * Note that, if we are redefining with the use of references
20436 * to components, the spec assumes the src-resolve to be used;
20437 * but this won't assure that we search only *inside* the
20438 * redefined schema.
20439 */
20440 if (redef->reference)
20441 node = WXS_ITEM_NODE(redef->reference);
20442 else
20443 node = WXS_ITEM_NODE(item);
20444 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20445 /*
20446 * TODO: error code.
20447 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20448 * reference kind.
20449 */
20450 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20451 "The %s '%s' to be redefined could not be found in "
20452 "the redefined schema",
20453 WXS_ITEM_TYPE_NAME(item),
20454 xmlSchemaFormatQName(&str, redef->refTargetNs,
20455 redef->refName));
20456 FREE_AND_NULL(str);
20457 err = pctxt->err;
20458 redef = redef->next;
20459 continue;
20460 }
20461 /*
20462 * TODO: Obtaining and setting the redefinition state is really
20463 * clumsy.
20464 */
20465 wasRedefined = 0;
20466 switch (item->type) {
20467 case XML_SCHEMA_TYPE_COMPLEX:
20468 case XML_SCHEMA_TYPE_SIMPLE:
20469 if ((WXS_TYPE_CAST prev)->flags &
20470 XML_SCHEMAS_TYPE_REDEFINED)
20471 {
20472 wasRedefined = 1;
20473 break;
20474 }
20475 /* Mark it as redefined. */
20476 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20477 /*
20478 * Assign the redefined type to the
20479 * base type of the redefining type.
20480 * TODO: How
20481 */
20482 ((xmlSchemaTypePtr) item)->baseType =
20483 (xmlSchemaTypePtr) prev;
20484 break;
20485 case XML_SCHEMA_TYPE_GROUP:
20486 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20487 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20488 {
20489 wasRedefined = 1;
20490 break;
20491 }
20492 /* Mark it as redefined. */
20493 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20494 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20495 if (redef->reference != NULL) {
20496 /*
20497 * Overwrite the QName-reference with the
20498 * referenced model group def.
20499 */
20500 (WXS_PTC_CAST redef->reference)->children =
20501 WXS_TREE_CAST prev;
20502 }
20503 redef->target = prev;
20504 break;
20505 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20506 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20507 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20508 {
20509 wasRedefined = 1;
20510 break;
20511 }
20512 (WXS_ATTR_GROUP_CAST prev)->flags |=
20513 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20514 if (redef->reference != NULL) {
20515 /*
20516 * Assign the redefined attribute group to the
20517 * QName-reference component.
20518 * This is the easy case, since we will just
20519 * expand the redefined group.
20520 */
20521 (WXS_QNAME_CAST redef->reference)->item = prev;
20522 redef->target = NULL;
20523 } else {
20524 /*
20525 * This is the complicated case: we need
20526 * to apply src-redefine (7.2.2) at a later
20527 * stage, i.e. when attribute group references
20528 * have been expanded and simple types have
20529 * been fixed.
20530 */
20531 redef->target = prev;
20532 }
20533 break;
20534 default:
20535 PERROR_INT("xmlSchemaResolveRedefReferences",
20536 "Unexpected redefined component type");
20537 return(-1);
20538 }
20539 if (wasRedefined) {
20540 xmlChar *str = NULL;
20541 xmlNodePtr node;
20542
20543 if (redef->reference)
20544 node = WXS_ITEM_NODE(redef->reference);
20545 else
20546 node = WXS_ITEM_NODE(redef->item);
20547
20548 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20549 /* TODO: error code. */
20550 XML_SCHEMAP_SRC_REDEFINE,
20551 node, NULL,
20552 "The referenced %s was already redefined. Multiple "
20553 "redefinition of the same component is not supported",
20554 xmlSchemaGetComponentDesignation(&str, prev),
20555 NULL);
20556 FREE_AND_NULL(str)
20557 err = pctxt->err;
20558 redef = redef->next;
20559 continue;
20560 }
20561 redef = redef->next;
20562 } while (redef != NULL);
20563
20564 return(err);
20565 }
20566
20567 static int
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)20568 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20569 {
20570 int err = 0;
20571 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20572 xmlSchemaBasicItemPtr item;
20573
20574 if (redef == NULL)
20575 return(0);
20576
20577 do {
20578 if (redef->target == NULL) {
20579 redef = redef->next;
20580 continue;
20581 }
20582 item = redef->item;
20583
20584 switch (item->type) {
20585 case XML_SCHEMA_TYPE_SIMPLE:
20586 case XML_SCHEMA_TYPE_COMPLEX:
20587 /*
20588 * Since the spec wants the {name} of the redefined
20589 * type to be 'absent', we'll NULL it.
20590 */
20591 (WXS_TYPE_CAST redef->target)->name = NULL;
20592
20593 /*
20594 * TODO: Seems like there's nothing more to do. The normal
20595 * inheritance mechanism is used. But not 100% sure.
20596 */
20597 break;
20598 case XML_SCHEMA_TYPE_GROUP:
20599 /*
20600 * URGENT TODO:
20601 * SPEC src-redefine:
20602 * (6.2.2) "The {model group} of the model group definition
20603 * which corresponds to it per XML Representation of Model
20604 * Group Definition Schema Components ($3.7.2) must be a
20605 * `valid restriction` of the {model group} of that model
20606 * group definition in I, as defined in Particle Valid
20607 * (Restriction) ($3.9.6)."
20608 */
20609 break;
20610 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20611 /*
20612 * SPEC src-redefine:
20613 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20614 * the attribute group definition which corresponds to it
20615 * per XML Representation of Attribute Group Definition Schema
20616 * Components ($3.6.2) must be `valid restrictions` of the
20617 * {attribute uses} and {attribute wildcard} of that attribute
20618 * group definition in I, as defined in clause 2, clause 3 and
20619 * clause 4 of Derivation Valid (Restriction, Complex)
20620 * ($3.4.6) (where references to the base type definition are
20621 * understood as references to the attribute group definition
20622 * in I)."
20623 */
20624 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20625 XML_SCHEMA_ACTION_REDEFINE,
20626 item, redef->target,
20627 (WXS_ATTR_GROUP_CAST item)->attrUses,
20628 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20629 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20630 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20631 if (err == -1)
20632 return(-1);
20633 break;
20634 default:
20635 break;
20636 }
20637 redef = redef->next;
20638 } while (redef != NULL);
20639 return(0);
20640 }
20641
20642
20643 static int
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr bucket)20644 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20645 xmlSchemaBucketPtr bucket)
20646 {
20647 xmlSchemaBasicItemPtr item;
20648 int err;
20649 xmlHashTablePtr *table;
20650 const xmlChar *name;
20651 int i;
20652
20653 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20654 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20655 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20656 else \
20657 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20658
20659 /*
20660 * Add global components to the schema's hash tables.
20661 * This is the place where duplicate components will be
20662 * detected.
20663 * TODO: I think normally we should support imports of the
20664 * same namespace from multiple locations. We don't do currently,
20665 * but if we do then according to:
20666 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20667 * we would need, if imported directly, to import redefined
20668 * components as well to be able to catch clashing components.
20669 * (I hope I'll still know what this means after some months :-()
20670 */
20671 if (bucket == NULL)
20672 return(-1);
20673 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20674 return(0);
20675 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20676
20677 for (i = 0; i < bucket->globals->nbItems; i++) {
20678 item = bucket->globals->items[i];
20679 table = NULL;
20680 switch (item->type) {
20681 case XML_SCHEMA_TYPE_COMPLEX:
20682 case XML_SCHEMA_TYPE_SIMPLE:
20683 if (WXS_REDEFINED_TYPE(item))
20684 continue;
20685 name = (WXS_TYPE_CAST item)->name;
20686 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20687 break;
20688 case XML_SCHEMA_TYPE_ELEMENT:
20689 name = (WXS_ELEM_CAST item)->name;
20690 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20691 break;
20692 case XML_SCHEMA_TYPE_ATTRIBUTE:
20693 name = (WXS_ATTR_CAST item)->name;
20694 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20695 break;
20696 case XML_SCHEMA_TYPE_GROUP:
20697 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20698 continue;
20699 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20700 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20701 break;
20702 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20703 if (WXS_REDEFINED_ATTR_GROUP(item))
20704 continue;
20705 name = (WXS_ATTR_GROUP_CAST item)->name;
20706 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20707 break;
20708 case XML_SCHEMA_TYPE_IDC_KEY:
20709 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20710 case XML_SCHEMA_TYPE_IDC_KEYREF:
20711 name = (WXS_IDC_CAST item)->name;
20712 WXS_GET_GLOBAL_HASH(bucket, idcDef)
20713 break;
20714 case XML_SCHEMA_TYPE_NOTATION:
20715 name = ((xmlSchemaNotationPtr) item)->name;
20716 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20717 break;
20718 default:
20719 PERROR_INT("xmlSchemaAddComponents",
20720 "Unexpected global component type");
20721 continue;
20722 }
20723 if (*table == NULL) {
20724 *table = xmlHashCreateDict(10, pctxt->dict);
20725 if (*table == NULL) {
20726 PERROR_INT("xmlSchemaAddComponents",
20727 "failed to create a component hash table");
20728 return(-1);
20729 }
20730 }
20731 err = xmlHashAddEntry(*table, name, item);
20732 if (err != 0) {
20733 xmlChar *str = NULL;
20734
20735 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20736 XML_SCHEMAP_REDEFINED_TYPE,
20737 WXS_ITEM_NODE(item),
20738 WXS_BASIC_CAST item,
20739 "A global %s '%s' does already exist",
20740 WXS_ITEM_TYPE_NAME(item),
20741 xmlSchemaGetComponentQName(&str, item));
20742 FREE_AND_NULL(str);
20743 }
20744 }
20745 /*
20746 * Process imported/included schemas.
20747 */
20748 if (bucket->relations != NULL) {
20749 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20750 do {
20751 if ((rel->bucket != NULL) &&
20752 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20753 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20754 return(-1);
20755 }
20756 rel = rel->next;
20757 } while (rel != NULL);
20758 }
20759 return(0);
20760 }
20761
20762 static int
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr rootBucket)20763 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20764 xmlSchemaBucketPtr rootBucket)
20765 {
20766 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20767 xmlSchemaTreeItemPtr item, *items;
20768 int nbItems, i, ret = 0;
20769 xmlSchemaBucketPtr oldbucket = con->bucket;
20770 xmlSchemaElementPtr elemDecl;
20771
20772 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20773
20774 if ((con->pending == NULL) ||
20775 (con->pending->nbItems == 0))
20776 return(0);
20777
20778 /*
20779 * Since xmlSchemaFixupComplexType() will create new particles
20780 * (local components), and those particle components need a bucket
20781 * on the constructor, we'll assure here that the constructor has
20782 * a bucket.
20783 * TODO: Think about storing locals _only_ on the main bucket.
20784 */
20785 if (con->bucket == NULL)
20786 con->bucket = rootBucket;
20787
20788 /* TODO:
20789 * SPEC (src-redefine):
20790 * (6.2) "If it has no such self-reference, then all of the
20791 * following must be true:"
20792
20793 * (6.2.2) The {model group} of the model group definition which
20794 * corresponds to it per XML Representation of Model Group
20795 * Definition Schema Components ($3.7.2) must be a `valid
20796 * restriction` of the {model group} of that model group definition
20797 * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20798 */
20799 xmlSchemaCheckSRCRedefineFirst(pctxt);
20800
20801 /*
20802 * Add global components to the schemata's hash tables.
20803 */
20804 xmlSchemaAddComponents(pctxt, rootBucket);
20805
20806 pctxt->ctxtType = NULL;
20807 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20808 nbItems = con->pending->nbItems;
20809 /*
20810 * Now that we have parsed *all* the schema document(s) and converted
20811 * them to schema components, we can resolve references, apply component
20812 * constraints, create the FSA from the content model, etc.
20813 */
20814 /*
20815 * Resolve references of..
20816 *
20817 * 1. element declarations:
20818 * - the type definition
20819 * - the substitution group affiliation
20820 * 2. simple/complex types:
20821 * - the base type definition
20822 * - the memberTypes of union types
20823 * - the itemType of list types
20824 * 3. attributes declarations and attribute uses:
20825 * - the type definition
20826 * - if an attribute use, then the attribute declaration
20827 * 4. attribute group references:
20828 * - the attribute group definition
20829 * 5. particles:
20830 * - the term of the particle (e.g. a model group)
20831 * 6. IDC key-references:
20832 * - the referenced IDC 'key' or 'unique' definition
20833 * 7. Attribute prohibitions which had a "ref" attribute.
20834 */
20835 for (i = 0; i < nbItems; i++) {
20836 item = items[i];
20837 switch (item->type) {
20838 case XML_SCHEMA_TYPE_ELEMENT:
20839 xmlSchemaResolveElementReferences(
20840 (xmlSchemaElementPtr) item, pctxt);
20841 FIXHFAILURE;
20842 break;
20843 case XML_SCHEMA_TYPE_COMPLEX:
20844 case XML_SCHEMA_TYPE_SIMPLE:
20845 xmlSchemaResolveTypeReferences(
20846 (xmlSchemaTypePtr) item, pctxt);
20847 FIXHFAILURE;
20848 break;
20849 case XML_SCHEMA_TYPE_ATTRIBUTE:
20850 xmlSchemaResolveAttrTypeReferences(
20851 (xmlSchemaAttributePtr) item, pctxt);
20852 FIXHFAILURE;
20853 break;
20854 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20855 xmlSchemaResolveAttrUseReferences(
20856 (xmlSchemaAttributeUsePtr) item, pctxt);
20857 FIXHFAILURE;
20858 break;
20859 case XML_SCHEMA_EXTRA_QNAMEREF:
20860 if ((WXS_QNAME_CAST item)->itemType ==
20861 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20862 {
20863 xmlSchemaResolveAttrGroupReferences(
20864 WXS_QNAME_CAST item, pctxt);
20865 }
20866 FIXHFAILURE;
20867 break;
20868 case XML_SCHEMA_TYPE_SEQUENCE:
20869 case XML_SCHEMA_TYPE_CHOICE:
20870 case XML_SCHEMA_TYPE_ALL:
20871 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20872 WXS_MODEL_GROUP_CAST item);
20873 FIXHFAILURE;
20874 break;
20875 case XML_SCHEMA_TYPE_IDC_KEY:
20876 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20877 case XML_SCHEMA_TYPE_IDC_KEYREF:
20878 xmlSchemaResolveIDCKeyReferences(
20879 (xmlSchemaIDCPtr) item, pctxt);
20880 FIXHFAILURE;
20881 break;
20882 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20883 /*
20884 * Handle attribute prohibition which had a
20885 * "ref" attribute.
20886 */
20887 xmlSchemaResolveAttrUseProhibReferences(
20888 WXS_ATTR_PROHIB_CAST item, pctxt);
20889 FIXHFAILURE;
20890 break;
20891 default:
20892 break;
20893 }
20894 }
20895 if (pctxt->nberrors != 0)
20896 goto exit_error;
20897
20898 /*
20899 * Now that all references are resolved we
20900 * can check for circularity of...
20901 * 1. the base axis of type definitions
20902 * 2. nested model group definitions
20903 * 3. nested attribute group definitions
20904 * TODO: check for circular substitution groups.
20905 */
20906 for (i = 0; i < nbItems; i++) {
20907 item = items[i];
20908 /*
20909 * Let's better stop on the first error here.
20910 */
20911 switch (item->type) {
20912 case XML_SCHEMA_TYPE_COMPLEX:
20913 case XML_SCHEMA_TYPE_SIMPLE:
20914 xmlSchemaCheckTypeDefCircular(
20915 (xmlSchemaTypePtr) item, pctxt);
20916 FIXHFAILURE;
20917 if (pctxt->nberrors != 0)
20918 goto exit_error;
20919 break;
20920 case XML_SCHEMA_TYPE_GROUP:
20921 xmlSchemaCheckGroupDefCircular(
20922 (xmlSchemaModelGroupDefPtr) item, pctxt);
20923 FIXHFAILURE;
20924 if (pctxt->nberrors != 0)
20925 goto exit_error;
20926 break;
20927 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20928 xmlSchemaCheckAttrGroupCircular(
20929 (xmlSchemaAttributeGroupPtr) item, pctxt);
20930 FIXHFAILURE;
20931 if (pctxt->nberrors != 0)
20932 goto exit_error;
20933 break;
20934 default:
20935 break;
20936 }
20937 }
20938 if (pctxt->nberrors != 0)
20939 goto exit_error;
20940 /*
20941 * Model group definition references:
20942 * Such a reference is reflected by a particle at the component
20943 * level. Until now the 'term' of such particles pointed
20944 * to the model group definition; this was done, in order to
20945 * ease circularity checks. Now we need to set the 'term' of
20946 * such particles to the model group of the model group definition.
20947 */
20948 for (i = 0; i < nbItems; i++) {
20949 item = items[i];
20950 switch (item->type) {
20951 case XML_SCHEMA_TYPE_SEQUENCE:
20952 case XML_SCHEMA_TYPE_CHOICE:
20953 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20954 WXS_MODEL_GROUP_CAST item);
20955 break;
20956 default:
20957 break;
20958 }
20959 }
20960 if (pctxt->nberrors != 0)
20961 goto exit_error;
20962 /*
20963 * Expand attribute group references of attribute group definitions.
20964 */
20965 for (i = 0; i < nbItems; i++) {
20966 item = items[i];
20967 switch (item->type) {
20968 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20969 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20970 WXS_ATTR_GROUP_HAS_REFS(item))
20971 {
20972 xmlSchemaAttributeGroupExpandRefs(pctxt,
20973 WXS_ATTR_GROUP_CAST item);
20974 FIXHFAILURE;
20975 }
20976 break;
20977 default:
20978 break;
20979 }
20980 }
20981 if (pctxt->nberrors != 0)
20982 goto exit_error;
20983 /*
20984 * First compute the variety of simple types. This is needed as
20985 * a separate step, since otherwise we won't be able to detect
20986 * circular union types in all cases.
20987 */
20988 for (i = 0; i < nbItems; i++) {
20989 item = items[i];
20990 switch (item->type) {
20991 case XML_SCHEMA_TYPE_SIMPLE:
20992 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
20993 xmlSchemaFixupSimpleTypeStageOne(pctxt,
20994 (xmlSchemaTypePtr) item);
20995 FIXHFAILURE;
20996 }
20997 break;
20998 default:
20999 break;
21000 }
21001 }
21002 if (pctxt->nberrors != 0)
21003 goto exit_error;
21004 /*
21005 * Detect circular union types. Note that this needs the variety to
21006 * be already computed.
21007 */
21008 for (i = 0; i < nbItems; i++) {
21009 item = items[i];
21010 switch (item->type) {
21011 case XML_SCHEMA_TYPE_SIMPLE:
21012 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21013 xmlSchemaCheckUnionTypeDefCircular(pctxt,
21014 (xmlSchemaTypePtr) item);
21015 FIXHFAILURE;
21016 }
21017 break;
21018 default:
21019 break;
21020 }
21021 }
21022 if (pctxt->nberrors != 0)
21023 goto exit_error;
21024
21025 /*
21026 * Do the complete type fixup for simple types.
21027 */
21028 for (i = 0; i < nbItems; i++) {
21029 item = items[i];
21030 switch (item->type) {
21031 case XML_SCHEMA_TYPE_SIMPLE:
21032 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21033 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21034 FIXHFAILURE;
21035 }
21036 break;
21037 default:
21038 break;
21039 }
21040 }
21041 if (pctxt->nberrors != 0)
21042 goto exit_error;
21043 /*
21044 * At this point we need build and check all simple types.
21045 */
21046 /*
21047 * Apply constraints for attribute declarations.
21048 */
21049 for (i = 0; i < nbItems; i++) {
21050 item = items[i];
21051 switch (item->type) {
21052 case XML_SCHEMA_TYPE_ATTRIBUTE:
21053 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21054 FIXHFAILURE;
21055 break;
21056 default:
21057 break;
21058 }
21059 }
21060 if (pctxt->nberrors != 0)
21061 goto exit_error;
21062 /*
21063 * Apply constraints for attribute uses.
21064 */
21065 for (i = 0; i < nbItems; i++) {
21066 item = items[i];
21067 switch (item->type) {
21068 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21069 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21070 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21071 WXS_ATTR_USE_CAST item);
21072 FIXHFAILURE;
21073 }
21074 break;
21075 default:
21076 break;
21077 }
21078 }
21079 if (pctxt->nberrors != 0)
21080 goto exit_error;
21081
21082 /*
21083 * Apply constraints for attribute group definitions.
21084 */
21085 for (i = 0; i < nbItems; i++) {
21086 item = items[i];
21087 switch (item->type) {
21088 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21089 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21090 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21091 {
21092 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21093 FIXHFAILURE;
21094 }
21095 break;
21096 default:
21097 break;
21098 }
21099 }
21100 if (pctxt->nberrors != 0)
21101 goto exit_error;
21102
21103 /*
21104 * Apply constraints for redefinitions.
21105 */
21106 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21107 xmlSchemaCheckSRCRedefineSecond(pctxt);
21108 if (pctxt->nberrors != 0)
21109 goto exit_error;
21110
21111 /*
21112 * Complex types are built and checked.
21113 */
21114 for (i = 0; i < nbItems; i++) {
21115 item = con->pending->items[i];
21116 switch (item->type) {
21117 case XML_SCHEMA_TYPE_COMPLEX:
21118 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21119 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21120 FIXHFAILURE;
21121 }
21122 break;
21123 default:
21124 break;
21125 }
21126 }
21127 if (pctxt->nberrors != 0)
21128 goto exit_error;
21129
21130 /*
21131 * The list could have changed, since xmlSchemaFixupComplexType()
21132 * will create particles and model groups in some cases.
21133 */
21134 items = (xmlSchemaTreeItemPtr *) con->pending->items;
21135 nbItems = con->pending->nbItems;
21136
21137 /*
21138 * Apply some constraints for element declarations.
21139 */
21140 for (i = 0; i < nbItems; i++) {
21141 item = items[i];
21142 switch (item->type) {
21143 case XML_SCHEMA_TYPE_ELEMENT:
21144 elemDecl = (xmlSchemaElementPtr) item;
21145
21146 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21147 {
21148 xmlSchemaCheckElementDeclComponent(
21149 (xmlSchemaElementPtr) elemDecl, pctxt);
21150 FIXHFAILURE;
21151 }
21152
21153 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21154 /*
21155 * Schema Component Constraint: Element Declarations Consistent
21156 * Apply this constraint to local types of element declarations.
21157 */
21158 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21159 (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21160 (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21161 {
21162 xmlSchemaCheckElementDeclConsistent(pctxt,
21163 WXS_BASIC_CAST elemDecl,
21164 WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21165 NULL, NULL, 0);
21166 }
21167 #endif
21168 break;
21169 default:
21170 break;
21171 }
21172 }
21173 if (pctxt->nberrors != 0)
21174 goto exit_error;
21175
21176 /*
21177 * Finally we can build the automaton from the content model of
21178 * complex types.
21179 */
21180
21181 for (i = 0; i < nbItems; i++) {
21182 item = items[i];
21183 switch (item->type) {
21184 case XML_SCHEMA_TYPE_COMPLEX:
21185 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21186 /* FIXHFAILURE; */
21187 break;
21188 default:
21189 break;
21190 }
21191 }
21192 if (pctxt->nberrors != 0)
21193 goto exit_error;
21194 /*
21195 * URGENT TODO: cos-element-consistent
21196 */
21197 goto exit;
21198
21199 exit_error:
21200 ret = pctxt->err;
21201 goto exit;
21202
21203 exit_failure:
21204 ret = -1;
21205
21206 exit:
21207 /*
21208 * Reset the constructor. This is needed for XSI acquisition, since
21209 * those items will be processed over and over again for every XSI
21210 * if not cleared here.
21211 */
21212 con->bucket = oldbucket;
21213 con->pending->nbItems = 0;
21214 if (con->substGroups != NULL) {
21215 xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21216 con->substGroups = NULL;
21217 }
21218 if (con->redefs != NULL) {
21219 xmlSchemaRedefListFree(con->redefs);
21220 con->redefs = NULL;
21221 }
21222 return(ret);
21223 }
21224 /**
21225 * xmlSchemaParse:
21226 * @ctxt: a schema validation context
21227 *
21228 * parse a schema definition resource and build an internal
21229 * XML Schema structure which can be used to validate instances.
21230 *
21231 * Returns the internal XML Schema structure built from the resource or
21232 * NULL in case of error
21233 */
21234 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)21235 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21236 {
21237 xmlSchemaPtr mainSchema = NULL;
21238 xmlSchemaBucketPtr bucket = NULL;
21239 int res;
21240
21241 /*
21242 * This one is used if the schema to be parsed was specified via
21243 * the API; i.e. not automatically by the validated instance document.
21244 */
21245
21246 if (xmlSchemaInitTypes() < 0)
21247 return (NULL);
21248
21249 if (ctxt == NULL)
21250 return (NULL);
21251
21252 /* TODO: Init the context. Is this all we need?*/
21253 ctxt->nberrors = 0;
21254 ctxt->err = 0;
21255 ctxt->counter = 0;
21256
21257 /* Create the *main* schema. */
21258 mainSchema = xmlSchemaNewSchema(ctxt);
21259 if (mainSchema == NULL)
21260 goto exit_failure;
21261 /*
21262 * Create the schema constructor.
21263 */
21264 if (ctxt->constructor == NULL) {
21265 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21266 if (ctxt->constructor == NULL)
21267 goto exit_failure;
21268 /* Take ownership of the constructor to be able to free it. */
21269 ctxt->ownsConstructor = 1;
21270 }
21271 ctxt->constructor->mainSchema = mainSchema;
21272 /*
21273 * Locate and add the schema document.
21274 */
21275 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21276 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21277 NULL, NULL, &bucket);
21278 if (res == -1)
21279 goto exit_failure;
21280 if (res != 0)
21281 goto exit;
21282
21283 if (bucket == NULL) {
21284 /* TODO: Error code, actually we failed to *locate* the schema. */
21285 if (ctxt->URL)
21286 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21287 NULL, NULL,
21288 "Failed to locate the main schema resource at '%s'",
21289 ctxt->URL, NULL);
21290 else
21291 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21292 NULL, NULL,
21293 "Failed to locate the main schema resource",
21294 NULL, NULL);
21295 goto exit;
21296 }
21297 /* Then do the parsing for good. */
21298 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21299 goto exit_failure;
21300 if (ctxt->nberrors != 0)
21301 goto exit;
21302
21303 mainSchema->doc = bucket->doc;
21304 mainSchema->preserve = ctxt->preserve;
21305
21306 ctxt->schema = mainSchema;
21307
21308 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21309 goto exit_failure;
21310
21311 /*
21312 * TODO: This is not nice, since we cannot distinguish from the
21313 * result if there was an internal error or not.
21314 */
21315 exit:
21316 if (ctxt->nberrors != 0) {
21317 if (mainSchema) {
21318 xmlSchemaFree(mainSchema);
21319 mainSchema = NULL;
21320 }
21321 if (ctxt->constructor) {
21322 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21323 ctxt->constructor = NULL;
21324 ctxt->ownsConstructor = 0;
21325 }
21326 }
21327 ctxt->schema = NULL;
21328 return(mainSchema);
21329 exit_failure:
21330 /*
21331 * Quite verbose, but should catch internal errors, which were
21332 * not communicated.
21333 */
21334 if (mainSchema) {
21335 xmlSchemaFree(mainSchema);
21336 mainSchema = NULL;
21337 }
21338 if (ctxt->constructor) {
21339 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21340 ctxt->constructor = NULL;
21341 ctxt->ownsConstructor = 0;
21342 }
21343 PERROR_INT2("xmlSchemaParse",
21344 "An internal error occurred");
21345 ctxt->schema = NULL;
21346 return(NULL);
21347 }
21348
21349 /**
21350 * xmlSchemaSetParserErrors:
21351 * @ctxt: a schema validation context
21352 * @err: the error callback
21353 * @warn: the warning callback
21354 * @ctx: contextual data for the callbacks
21355 *
21356 * DEPRECATED: Use xmlSchemaSetParserStructuredErrors.
21357 *
21358 * Set the callback functions used to handle errors for a validation context
21359 */
21360 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)21361 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21362 xmlSchemaValidityErrorFunc err,
21363 xmlSchemaValidityWarningFunc warn, void *ctx)
21364 {
21365 if (ctxt == NULL)
21366 return;
21367 ctxt->error = err;
21368 ctxt->warning = warn;
21369 ctxt->errCtxt = ctx;
21370 if (ctxt->vctxt != NULL)
21371 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21372 }
21373
21374 /**
21375 * xmlSchemaSetParserStructuredErrors:
21376 * @ctxt: a schema parser context
21377 * @serror: the structured error function
21378 * @ctx: the functions context
21379 *
21380 * Set the structured error callback
21381 */
21382 void
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)21383 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21384 xmlStructuredErrorFunc serror,
21385 void *ctx)
21386 {
21387 if (ctxt == NULL)
21388 return;
21389 ctxt->serror = serror;
21390 ctxt->errCtxt = ctx;
21391 if (ctxt->vctxt != NULL)
21392 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21393 }
21394
21395 /**
21396 * xmlSchemaGetParserErrors:
21397 * @ctxt: a XMl-Schema parser context
21398 * @err: the error callback result
21399 * @warn: the warning callback result
21400 * @ctx: contextual data for the callbacks result
21401 *
21402 * Get the callback information used to handle errors for a parser context
21403 *
21404 * Returns -1 in case of failure, 0 otherwise
21405 */
21406 int
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)21407 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21408 xmlSchemaValidityErrorFunc * err,
21409 xmlSchemaValidityWarningFunc * warn, void **ctx)
21410 {
21411 if (ctxt == NULL)
21412 return(-1);
21413 if (err != NULL)
21414 *err = ctxt->error;
21415 if (warn != NULL)
21416 *warn = ctxt->warning;
21417 if (ctx != NULL)
21418 *ctx = ctxt->errCtxt;
21419 return(0);
21420 }
21421
21422 /**
21423 * xmlSchemaSetResourceLoader:
21424 * @ctxt: schema parser
21425 * @loader: resource loader
21426 * @data: user data which will be passed to the loader
21427 *
21428 * Register a callback function that will be called to load documents
21429 * or external entities.
21430 *
21431 * Available since 2.14.0.
21432 */
21433 void
xmlSchemaSetResourceLoader(xmlSchemaParserCtxtPtr ctxt,xmlResourceLoader loader,void * data)21434 xmlSchemaSetResourceLoader(xmlSchemaParserCtxtPtr ctxt,
21435 xmlResourceLoader loader, void *data) {
21436 if (ctxt == NULL)
21437 return;
21438 ctxt->resourceLoader = loader;
21439 ctxt->resourceCtxt = data;
21440 }
21441
21442 /**
21443 * xmlSchemaFacetTypeToString:
21444 * @type: the facet type
21445 *
21446 * Convert the xmlSchemaTypeType to a char string.
21447 *
21448 * Returns the char string representation of the facet type if the
21449 * type is a facet and an "Internal Error" string otherwise.
21450 */
21451 static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)21452 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21453 {
21454 switch (type) {
21455 case XML_SCHEMA_FACET_PATTERN:
21456 return (BAD_CAST "pattern");
21457 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21458 return (BAD_CAST "maxExclusive");
21459 case XML_SCHEMA_FACET_MAXINCLUSIVE:
21460 return (BAD_CAST "maxInclusive");
21461 case XML_SCHEMA_FACET_MINEXCLUSIVE:
21462 return (BAD_CAST "minExclusive");
21463 case XML_SCHEMA_FACET_MININCLUSIVE:
21464 return (BAD_CAST "minInclusive");
21465 case XML_SCHEMA_FACET_WHITESPACE:
21466 return (BAD_CAST "whiteSpace");
21467 case XML_SCHEMA_FACET_ENUMERATION:
21468 return (BAD_CAST "enumeration");
21469 case XML_SCHEMA_FACET_LENGTH:
21470 return (BAD_CAST "length");
21471 case XML_SCHEMA_FACET_MAXLENGTH:
21472 return (BAD_CAST "maxLength");
21473 case XML_SCHEMA_FACET_MINLENGTH:
21474 return (BAD_CAST "minLength");
21475 case XML_SCHEMA_FACET_TOTALDIGITS:
21476 return (BAD_CAST "totalDigits");
21477 case XML_SCHEMA_FACET_FRACTIONDIGITS:
21478 return (BAD_CAST "fractionDigits");
21479 default:
21480 break;
21481 }
21482 return (BAD_CAST "Internal Error");
21483 }
21484
21485 static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)21486 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21487 {
21488 /*
21489 * The normalization type can be changed only for types which are derived
21490 * from xsd:string.
21491 */
21492 if (type->type == XML_SCHEMA_TYPE_BASIC) {
21493 /*
21494 * Note that we assume a whitespace of preserve for anySimpleType.
21495 */
21496 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21497 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21498 return(XML_SCHEMA_WHITESPACE_PRESERVE);
21499 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21500 return(XML_SCHEMA_WHITESPACE_REPLACE);
21501 else {
21502 /*
21503 * For all `atomic` datatypes other than string (and types `derived`
21504 * by `restriction` from it) the value of whiteSpace is fixed to
21505 * collapse
21506 * Note that this includes built-in list datatypes.
21507 */
21508 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21509 }
21510 } else if (WXS_IS_LIST(type)) {
21511 /*
21512 * For list types the facet "whiteSpace" is fixed to "collapse".
21513 */
21514 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21515 } else if (WXS_IS_UNION(type)) {
21516 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21517 } else if (WXS_IS_ATOMIC(type)) {
21518 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21519 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21520 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21521 return (XML_SCHEMA_WHITESPACE_REPLACE);
21522 else
21523 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21524 }
21525 return (-1);
21526 }
21527
21528 /************************************************************************
21529 * *
21530 * Simple type validation *
21531 * *
21532 ************************************************************************/
21533
21534
21535 /************************************************************************
21536 * *
21537 * DOM Validation code *
21538 * *
21539 ************************************************************************/
21540
21541 /**
21542 * xmlSchemaAssembleByLocation:
21543 * @pctxt: a schema parser context
21544 * @vctxt: a schema validation context
21545 * @schema: the existing schema
21546 * @node: the node that fired the assembling
21547 * @nsName: the namespace name of the new schema
21548 * @location: the location of the schema
21549 *
21550 * Expands an existing schema by an additional schema.
21551 *
21552 * Returns 0 if the new schema is correct, a positive error code
21553 * number otherwise and -1 in case of an internal or API error.
21554 */
21555 static int
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * nsName,const xmlChar * location)21556 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21557 xmlSchemaPtr schema,
21558 xmlNodePtr node,
21559 const xmlChar *nsName,
21560 const xmlChar *location)
21561 {
21562 int ret = 0;
21563 xmlSchemaParserCtxtPtr pctxt;
21564 xmlSchemaBucketPtr bucket = NULL;
21565
21566 if ((vctxt == NULL) || (schema == NULL))
21567 return (-1);
21568
21569 if (vctxt->pctxt == NULL) {
21570 VERROR_INT("xmlSchemaAssembleByLocation",
21571 "no parser context available");
21572 return(-1);
21573 }
21574 pctxt = vctxt->pctxt;
21575 if (pctxt->constructor == NULL) {
21576 PERROR_INT("xmlSchemaAssembleByLocation",
21577 "no constructor");
21578 return(-1);
21579 }
21580 /*
21581 * Acquire the schema document.
21582 */
21583 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21584 location, node);
21585 /*
21586 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21587 * the process will automatically change this to
21588 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21589 */
21590 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21591 location, NULL, NULL, 0, node, NULL, nsName,
21592 &bucket);
21593 if (ret != 0)
21594 return(ret);
21595 if (bucket == NULL) {
21596 /*
21597 * Generate a warning that the document could not be located.
21598 */
21599 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21600 node, NULL,
21601 "The document at location '%s' could not be acquired",
21602 location, NULL, NULL);
21603 return(ret);
21604 }
21605 /*
21606 * The first located schema will be handled as if all other
21607 * schemas imported by XSI were imported by this first schema.
21608 */
21609 if ((bucket != NULL) &&
21610 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21611 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21612 /*
21613 * TODO: Is this handled like an import? I.e. is it not an error
21614 * if the schema cannot be located?
21615 */
21616 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21617 return(0);
21618 /*
21619 * We will reuse the parser context for every schema imported
21620 * directly via XSI. So reset the context.
21621 */
21622 pctxt->nberrors = 0;
21623 pctxt->err = 0;
21624 pctxt->doc = bucket->doc;
21625
21626 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21627 if (ret == -1) {
21628 pctxt->doc = NULL;
21629 goto exit_failure;
21630 }
21631 /* Paranoid error channelling. */
21632 if ((ret == 0) && (pctxt->nberrors != 0))
21633 ret = pctxt->err;
21634 if (pctxt->nberrors == 0) {
21635 /*
21636 * Only bother to fixup pending components, if there was
21637 * no error yet.
21638 * For every XSI acquired schema (and its sub-schemata) we will
21639 * fixup the components.
21640 */
21641 xmlSchemaFixupComponents(pctxt, bucket);
21642 ret = pctxt->err;
21643 /*
21644 * Not nice, but we need somehow to channel the schema parser
21645 * error to the validation context.
21646 */
21647 if ((ret != 0) && (vctxt->err == 0))
21648 vctxt->err = ret;
21649 vctxt->nberrors += pctxt->nberrors;
21650 } else {
21651 /* Add to validation error sum. */
21652 vctxt->nberrors += pctxt->nberrors;
21653 }
21654 pctxt->doc = NULL;
21655 return(ret);
21656 exit_failure:
21657 pctxt->doc = NULL;
21658 return (-1);
21659 }
21660
21661 static xmlSchemaAttrInfoPtr
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,int metaType)21662 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21663 int metaType)
21664 {
21665 if (vctxt->nbAttrInfos == 0)
21666 return (NULL);
21667 {
21668 int i;
21669 xmlSchemaAttrInfoPtr iattr;
21670
21671 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21672 iattr = vctxt->attrInfos[i];
21673 if (iattr->metaType == metaType)
21674 return (iattr);
21675 }
21676
21677 }
21678 return (NULL);
21679 }
21680
21681 /**
21682 * xmlSchemaAssembleByXSI:
21683 * @vctxt: a schema validation context
21684 *
21685 * Expands an existing schema by an additional schema using
21686 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21687 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21688 * must be set to 1.
21689 *
21690 * Returns 0 if the new schema is correct, a positive error code
21691 * number otherwise and -1 in case of an internal or API error.
21692 */
21693 static int
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)21694 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21695 {
21696 const xmlChar *cur, *end;
21697 const xmlChar *nsname = NULL, *location;
21698 int ret = 0;
21699 xmlSchemaAttrInfoPtr iattr;
21700
21701 /*
21702 * Parse the value; we will assume an even number of values
21703 * to be given (this is how Xerces and XSV work).
21704 *
21705 * URGENT TODO: !! This needs to work for both
21706 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21707 * element !!
21708 */
21709 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21710 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21711 if (iattr == NULL)
21712 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21713 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21714 if (iattr == NULL)
21715 return (0);
21716 cur = iattr->value;
21717 do {
21718 /*
21719 * TODO: Move the string parsing mechanism away from here.
21720 */
21721 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21722 /*
21723 * Get the namespace name.
21724 */
21725 while (IS_BLANK_CH(*cur))
21726 cur++;
21727 end = cur;
21728 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21729 end++;
21730 if (end == cur)
21731 break;
21732 /* TODO: Don't use the schema's dict. */
21733 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21734 cur = end;
21735 }
21736 /*
21737 * Get the URI.
21738 */
21739 while (IS_BLANK_CH(*cur))
21740 cur++;
21741 end = cur;
21742 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21743 end++;
21744 if (end == cur) {
21745 if (iattr->metaType ==
21746 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21747 {
21748 /*
21749 * If using @schemaLocation then tuples are expected.
21750 * I.e. the namespace name *and* the document's URI.
21751 */
21752 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21753 iattr->node, NULL,
21754 "The value must consist of tuples: the target namespace "
21755 "name and the document's URI", NULL, NULL, NULL);
21756 }
21757 break;
21758 }
21759 /* TODO: Don't use the schema's dict. */
21760 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21761 cur = end;
21762 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21763 iattr->node, nsname, location);
21764 if (ret == -1) {
21765 VERROR_INT("xmlSchemaAssembleByXSI",
21766 "assembling schemata");
21767 return (-1);
21768 }
21769 } while (*cur != 0);
21770 return (ret);
21771 }
21772
21773 static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,const xmlChar * prefix)21774 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21775 const xmlChar *prefix)
21776 {
21777 if (vctxt->sax != NULL) {
21778 int i, j;
21779 xmlSchemaNodeInfoPtr inode;
21780
21781 for (i = vctxt->depth; i >= 0; i--) {
21782 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21783 inode = vctxt->elemInfos[i];
21784 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21785 if (((prefix == NULL) &&
21786 (inode->nsBindings[j] == NULL)) ||
21787 ((prefix != NULL) && xmlStrEqual(prefix,
21788 inode->nsBindings[j]))) {
21789
21790 /*
21791 * Note that the namespace bindings are already
21792 * in a string dict.
21793 */
21794 return (inode->nsBindings[j+1]);
21795 }
21796 }
21797 }
21798 }
21799 return (NULL);
21800 #ifdef LIBXML_READER_ENABLED
21801 } else if (vctxt->reader != NULL) {
21802 xmlChar *nsName;
21803
21804 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21805 if (nsName != NULL) {
21806 const xmlChar *ret;
21807
21808 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21809 xmlFree(nsName);
21810 return (ret);
21811 } else
21812 return (NULL);
21813 #endif
21814 } else {
21815 xmlNsPtr ns;
21816
21817 if ((vctxt->inode->node == NULL) ||
21818 (vctxt->inode->node->doc == NULL)) {
21819 VERROR_INT("xmlSchemaLookupNamespace",
21820 "no node or node's doc available");
21821 return (NULL);
21822 }
21823 ns = xmlSearchNs(vctxt->inode->node->doc,
21824 vctxt->inode->node, prefix);
21825 if (ns != NULL)
21826 return (ns->href);
21827 return (NULL);
21828 }
21829 }
21830
21831 /*
21832 * This one works on the schema of the validation context.
21833 */
21834 static int
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)21835 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21836 xmlSchemaPtr schema,
21837 xmlNodePtr node,
21838 const xmlChar *value,
21839 xmlSchemaValPtr *val,
21840 int valNeeded)
21841 {
21842 int ret;
21843
21844 if (vctxt && (vctxt->schema == NULL)) {
21845 VERROR_INT("xmlSchemaValidateNotation",
21846 "a schema is needed on the validation context");
21847 return (-1);
21848 }
21849 ret = xmlValidateQName(value, 1);
21850 if (ret != 0)
21851 return (ret);
21852 {
21853 xmlChar *localName = NULL;
21854 xmlChar *prefix = NULL;
21855
21856 localName = xmlSplitQName2(value, &prefix);
21857 if (prefix != NULL) {
21858 const xmlChar *nsName = NULL;
21859
21860 if (vctxt != NULL)
21861 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21862 else if (node != NULL) {
21863 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21864 if (ns != NULL)
21865 nsName = ns->href;
21866 } else {
21867 xmlFree(prefix);
21868 xmlFree(localName);
21869 return (1);
21870 }
21871 if (nsName == NULL) {
21872 xmlFree(prefix);
21873 xmlFree(localName);
21874 return (1);
21875 }
21876 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21877 if ((valNeeded) && (val != NULL)) {
21878 (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21879 xmlStrdup(nsName));
21880 if (*val == NULL)
21881 ret = -1;
21882 }
21883 } else
21884 ret = 1;
21885 xmlFree(prefix);
21886 xmlFree(localName);
21887 } else {
21888 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21889 if (valNeeded && (val != NULL)) {
21890 (*val) = xmlSchemaNewNOTATIONValue(
21891 BAD_CAST xmlStrdup(value), NULL);
21892 if (*val == NULL)
21893 ret = -1;
21894 }
21895 } else
21896 return (1);
21897 }
21898 }
21899 return (ret);
21900 }
21901
21902 static int
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * lname,const xmlChar * nsname)21903 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21904 const xmlChar* lname,
21905 const xmlChar* nsname)
21906 {
21907 int i;
21908
21909 lname = xmlDictLookup(vctxt->dict, lname, -1);
21910 if (lname == NULL)
21911 return(-1);
21912 if (nsname != NULL) {
21913 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21914 if (nsname == NULL)
21915 return(-1);
21916 }
21917 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21918 if ((vctxt->nodeQNames->items [i] == lname) &&
21919 (vctxt->nodeQNames->items[i +1] == nsname))
21920 /* Already there */
21921 return(i);
21922 }
21923 /* Add new entry. */
21924 i = vctxt->nodeQNames->nbItems;
21925 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21926 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21927 return(i);
21928 }
21929
21930 /************************************************************************
21931 * *
21932 * Validation of identity-constraints (IDC) *
21933 * *
21934 ************************************************************************/
21935
21936 /**
21937 * xmlSchemaAugmentIDC:
21938 * @idcDef: the IDC definition
21939 *
21940 * Creates an augmented IDC definition item.
21941 *
21942 * Returns the item, or NULL on internal errors.
21943 */
21944 static void
xmlSchemaAugmentIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)21945 xmlSchemaAugmentIDC(void *payload, void *data,
21946 const xmlChar *name ATTRIBUTE_UNUSED)
21947 {
21948 xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
21949 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
21950 xmlSchemaIDCAugPtr aidc;
21951
21952 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21953 if (aidc == NULL) {
21954 xmlSchemaVErrMemory(vctxt);
21955 return;
21956 }
21957 aidc->keyrefDepth = -1;
21958 aidc->def = idcDef;
21959 aidc->next = NULL;
21960 if (vctxt->aidcs == NULL)
21961 vctxt->aidcs = aidc;
21962 else {
21963 aidc->next = vctxt->aidcs;
21964 vctxt->aidcs = aidc;
21965 }
21966 /*
21967 * Save if we have keyrefs at all.
21968 */
21969 if ((vctxt->hasKeyrefs == 0) &&
21970 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21971 vctxt->hasKeyrefs = 1;
21972 }
21973
21974 /**
21975 * xmlSchemaAugmentImportedIDC:
21976 * @imported: the imported schema
21977 *
21978 * Creates an augmented IDC definition for the imported schema.
21979 */
21980 static void
xmlSchemaAugmentImportedIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)21981 xmlSchemaAugmentImportedIDC(void *payload, void *data,
21982 const xmlChar *name ATTRIBUTE_UNUSED) {
21983 xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
21984 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
21985 if (imported->schema->idcDef != NULL) {
21986 xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
21987 }
21988 }
21989
21990 /**
21991 * xmlSchemaIDCNewBinding:
21992 * @idcDef: the IDC definition of this binding
21993 *
21994 * Creates a new IDC binding.
21995 *
21996 * Returns the new IDC binding, NULL on internal errors.
21997 */
21998 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)21999 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22000 {
22001 xmlSchemaPSVIIDCBindingPtr ret;
22002
22003 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22004 sizeof(xmlSchemaPSVIIDCBinding));
22005 if (ret == NULL) {
22006 xmlSchemaVErrMemory(NULL);
22007 return (NULL);
22008 }
22009 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22010 ret->definition = idcDef;
22011 return (ret);
22012 }
22013
22014 /**
22015 * xmlSchemaIDCStoreNodeTableItem:
22016 * @vctxt: the WXS validation context
22017 * @item: the IDC node table item
22018 *
22019 * The validation context is used to store IDC node table items.
22020 * They are stored to avoid copying them if IDC node-tables are merged
22021 * with corresponding parent IDC node-tables (bubbling).
22022 *
22023 * Returns 0 if succeeded, -1 on internal errors.
22024 */
22025 static int
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCNodePtr item)22026 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22027 xmlSchemaPSVIIDCNodePtr item)
22028 {
22029 /*
22030 * Add to global list.
22031 */
22032 if (vctxt->idcNodes == NULL) {
22033 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22034 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22035 if (vctxt->idcNodes == NULL) {
22036 xmlSchemaVErrMemory(vctxt);
22037 return (-1);
22038 }
22039 vctxt->sizeIdcNodes = 20;
22040 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22041 vctxt->sizeIdcNodes *= 2;
22042 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22043 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22044 sizeof(xmlSchemaPSVIIDCNodePtr));
22045 if (vctxt->idcNodes == NULL) {
22046 xmlSchemaVErrMemory(vctxt);
22047 return (-1);
22048 }
22049 }
22050 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22051
22052 return (0);
22053 }
22054
22055 /**
22056 * xmlSchemaIDCStoreKey:
22057 * @vctxt: the WXS validation context
22058 * @item: the IDC key
22059 *
22060 * The validation context is used to store an IDC key.
22061 *
22062 * Returns 0 if succeeded, -1 on internal errors.
22063 */
22064 static int
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCKeyPtr key)22065 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22066 xmlSchemaPSVIIDCKeyPtr key)
22067 {
22068 /*
22069 * Add to global list.
22070 */
22071 if (vctxt->idcKeys == NULL) {
22072 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22073 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22074 if (vctxt->idcKeys == NULL) {
22075 xmlSchemaVErrMemory(vctxt);
22076 return (-1);
22077 }
22078 vctxt->sizeIdcKeys = 40;
22079 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22080 vctxt->sizeIdcKeys *= 2;
22081 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22082 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22083 sizeof(xmlSchemaPSVIIDCKeyPtr));
22084 if (vctxt->idcKeys == NULL) {
22085 xmlSchemaVErrMemory(vctxt);
22086 return (-1);
22087 }
22088 }
22089 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22090
22091 return (0);
22092 }
22093
22094 /**
22095 * xmlSchemaIDCAppendNodeTableItem:
22096 * @bind: the IDC binding
22097 * @ntItem: the node-table item
22098 *
22099 * Appends the IDC node-table item to the binding.
22100 *
22101 * Returns 0 on success and -1 on internal errors.
22102 */
22103 static int
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,xmlSchemaPSVIIDCNodePtr ntItem)22104 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22105 xmlSchemaPSVIIDCNodePtr ntItem)
22106 {
22107 if (bind->nodeTable == NULL) {
22108 bind->sizeNodes = 10;
22109 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22110 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22111 if (bind->nodeTable == NULL) {
22112 xmlSchemaVErrMemory(NULL);
22113 return(-1);
22114 }
22115 } else if (bind->sizeNodes <= bind->nbNodes) {
22116 bind->sizeNodes *= 2;
22117 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22118 xmlRealloc(bind->nodeTable, bind->sizeNodes *
22119 sizeof(xmlSchemaPSVIIDCNodePtr));
22120 if (bind->nodeTable == NULL) {
22121 xmlSchemaVErrMemory(NULL);
22122 return(-1);
22123 }
22124 }
22125 bind->nodeTable[bind->nbNodes++] = ntItem;
22126 return(0);
22127 }
22128
22129 /**
22130 * xmlSchemaIDCAcquireBinding:
22131 * @vctxt: the WXS validation context
22132 * @matcher: the IDC matcher
22133 *
22134 * Looks up an PSVI IDC binding, for the IDC definition and
22135 * of the given matcher. If none found, a new one is created
22136 * and added to the IDC table.
22137 *
22138 * Returns an IDC binding or NULL on internal errors.
22139 */
22140 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22141 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22142 xmlSchemaIDCMatcherPtr matcher)
22143 {
22144 xmlSchemaNodeInfoPtr ielem;
22145
22146 ielem = vctxt->elemInfos[matcher->depth];
22147
22148 if (ielem->idcTable == NULL) {
22149 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22150 if (ielem->idcTable == NULL)
22151 return (NULL);
22152 return(ielem->idcTable);
22153 } else {
22154 xmlSchemaPSVIIDCBindingPtr bind = NULL;
22155
22156 bind = ielem->idcTable;
22157 do {
22158 if (bind->definition == matcher->aidc->def)
22159 return(bind);
22160 if (bind->next == NULL) {
22161 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22162 if (bind->next == NULL)
22163 return (NULL);
22164 return(bind->next);
22165 }
22166 bind = bind->next;
22167 } while (bind != NULL);
22168 }
22169 return (NULL);
22170 }
22171
22172 static xmlSchemaItemListPtr
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,xmlSchemaIDCMatcherPtr matcher)22173 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22174 xmlSchemaIDCMatcherPtr matcher)
22175 {
22176 if (matcher->targets == NULL)
22177 matcher->targets = xmlSchemaItemListCreate();
22178 return(matcher->targets);
22179 }
22180
22181 /**
22182 * xmlSchemaIDCFreeKey:
22183 * @key: the IDC key
22184 *
22185 * Frees an IDC key together with its compiled value.
22186 */
22187 static void
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)22188 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22189 {
22190 if (key->val != NULL)
22191 xmlSchemaFreeValue(key->val);
22192 xmlFree(key);
22193 }
22194
22195 /**
22196 * xmlSchemaIDCFreeBinding:
22197 *
22198 * Frees an IDC binding. Note that the node table-items
22199 * are not freed.
22200 */
22201 static void
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)22202 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22203 {
22204 if (bind->nodeTable != NULL)
22205 xmlFree(bind->nodeTable);
22206 if (bind->dupls != NULL)
22207 xmlSchemaItemListFree(bind->dupls);
22208 xmlFree(bind);
22209 }
22210
22211 /**
22212 * xmlSchemaIDCFreeIDCTable:
22213 * @bind: the first IDC binding in the list
22214 *
22215 * Frees an IDC table, i.e. all the IDC bindings in the list.
22216 */
22217 static void
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)22218 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22219 {
22220 xmlSchemaPSVIIDCBindingPtr prev;
22221
22222 while (bind != NULL) {
22223 prev = bind;
22224 bind = bind->next;
22225 xmlSchemaIDCFreeBinding(prev);
22226 }
22227 }
22228
22229 static void
xmlFreeIDCHashEntry(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)22230 xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
22231 {
22232 xmlIDCHashEntryPtr e = payload, n;
22233 while (e) {
22234 n = e->next;
22235 xmlFree(e);
22236 e = n;
22237 }
22238 }
22239
22240 /**
22241 * xmlSchemaIDCFreeMatcherList:
22242 * @matcher: the first IDC matcher in the list
22243 *
22244 * Frees a list of IDC matchers.
22245 */
22246 static void
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)22247 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22248 {
22249 xmlSchemaIDCMatcherPtr next;
22250
22251 while (matcher != NULL) {
22252 next = matcher->next;
22253 if (matcher->keySeqs != NULL) {
22254 int i;
22255 for (i = 0; i < matcher->sizeKeySeqs; i++)
22256 if (matcher->keySeqs[i] != NULL)
22257 xmlFree(matcher->keySeqs[i]);
22258 xmlFree(matcher->keySeqs);
22259 }
22260 if (matcher->targets != NULL) {
22261 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22262 int i;
22263 xmlSchemaPSVIIDCNodePtr idcNode;
22264 /*
22265 * Node-table items for keyrefs are not stored globally
22266 * to the validation context, since they are not bubbled.
22267 * We need to free them here.
22268 */
22269 for (i = 0; i < matcher->targets->nbItems; i++) {
22270 idcNode =
22271 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22272 xmlFree(idcNode->keys);
22273 xmlFree(idcNode);
22274 }
22275 }
22276 xmlSchemaItemListFree(matcher->targets);
22277 }
22278 if (matcher->htab != NULL)
22279 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22280 xmlFree(matcher);
22281 matcher = next;
22282 }
22283 }
22284
22285 /**
22286 * xmlSchemaIDCReleaseMatcherList:
22287 * @vctxt: the WXS validation context
22288 * @matcher: the first IDC matcher in the list
22289 *
22290 * Caches a list of IDC matchers for reuse.
22291 */
22292 static void
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22293 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22294 xmlSchemaIDCMatcherPtr matcher)
22295 {
22296 xmlSchemaIDCMatcherPtr next;
22297
22298 while (matcher != NULL) {
22299 next = matcher->next;
22300 if (matcher->keySeqs != NULL) {
22301 int i;
22302 /*
22303 * Don't free the array, but only the content.
22304 */
22305 for (i = 0; i < matcher->sizeKeySeqs; i++)
22306 if (matcher->keySeqs[i] != NULL) {
22307 xmlFree(matcher->keySeqs[i]);
22308 matcher->keySeqs[i] = NULL;
22309 }
22310 }
22311 if (matcher->targets) {
22312 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22313 int i;
22314 xmlSchemaPSVIIDCNodePtr idcNode;
22315 /*
22316 * Node-table items for keyrefs are not stored globally
22317 * to the validation context, since they are not bubbled.
22318 * We need to free them here.
22319 */
22320 for (i = 0; i < matcher->targets->nbItems; i++) {
22321 idcNode =
22322 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22323 xmlFree(idcNode->keys);
22324 xmlFree(idcNode);
22325 }
22326 }
22327 xmlSchemaItemListFree(matcher->targets);
22328 matcher->targets = NULL;
22329 }
22330 if (matcher->htab != NULL) {
22331 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22332 matcher->htab = NULL;
22333 }
22334 matcher->next = NULL;
22335 /*
22336 * Cache the matcher.
22337 */
22338 if (vctxt->idcMatcherCache != NULL)
22339 matcher->nextCached = vctxt->idcMatcherCache;
22340 vctxt->idcMatcherCache = matcher;
22341
22342 matcher = next;
22343 }
22344 }
22345
22346 /**
22347 * xmlSchemaIDCAddStateObject:
22348 * @vctxt: the WXS validation context
22349 * @matcher: the IDC matcher
22350 * @sel: the XPath information
22351 * @parent: the parent "selector" state object if any
22352 * @type: "selector" or "field"
22353 *
22354 * Creates/reuses and activates state objects for the given
22355 * XPath information; if the XPath expression consists of unions,
22356 * multiple state objects are created for every unioned expression.
22357 *
22358 * Returns 0 on success and -1 on internal errors.
22359 */
22360 static int
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher,xmlSchemaIDCSelectPtr sel,int type)22361 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22362 xmlSchemaIDCMatcherPtr matcher,
22363 xmlSchemaIDCSelectPtr sel,
22364 int type)
22365 {
22366 xmlSchemaIDCStateObjPtr sto;
22367
22368 /*
22369 * Reuse the state objects from the pool.
22370 */
22371 if (vctxt->xpathStatePool != NULL) {
22372 sto = vctxt->xpathStatePool;
22373 vctxt->xpathStatePool = sto->next;
22374 sto->next = NULL;
22375 } else {
22376 /*
22377 * Create a new state object.
22378 */
22379 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22380 if (sto == NULL) {
22381 xmlSchemaVErrMemory(NULL);
22382 return (-1);
22383 }
22384 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22385 }
22386 /*
22387 * Add to global list.
22388 */
22389 if (vctxt->xpathStates != NULL)
22390 sto->next = vctxt->xpathStates;
22391 vctxt->xpathStates = sto;
22392
22393 /*
22394 * Free the old xpath validation context.
22395 */
22396 if (sto->xpathCtxt != NULL)
22397 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22398
22399 /*
22400 * Create a new XPath (pattern) validation context.
22401 */
22402 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22403 (xmlPatternPtr) sel->xpathComp);
22404 if (sto->xpathCtxt == NULL) {
22405 VERROR_INT("xmlSchemaIDCAddStateObject",
22406 "failed to create an XPath validation context");
22407 return (-1);
22408 }
22409 sto->type = type;
22410 sto->depth = vctxt->depth;
22411 sto->matcher = matcher;
22412 sto->sel = sel;
22413 sto->nbHistory = 0;
22414
22415 return (0);
22416 }
22417
22418 /**
22419 * xmlSchemaXPathEvaluate:
22420 * @vctxt: the WXS validation context
22421 * @nodeType: the nodeType of the current node
22422 *
22423 * Evaluates all active XPath state objects.
22424 *
22425 * Returns the number of IC "field" state objects which resolved to
22426 * this node, 0 if none resolved and -1 on internal errors.
22427 */
22428 static int
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,xmlElementType nodeType)22429 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22430 xmlElementType nodeType)
22431 {
22432 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22433 int res, resolved = 0, depth = vctxt->depth;
22434
22435 if (vctxt->xpathStates == NULL)
22436 return (0);
22437
22438 if (nodeType == XML_ATTRIBUTE_NODE)
22439 depth++;
22440 /*
22441 * Process all active XPath state objects.
22442 */
22443 first = vctxt->xpathStates;
22444 sto = first;
22445 while (sto != head) {
22446 if (nodeType == XML_ELEMENT_NODE)
22447 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22448 vctxt->inode->localName, vctxt->inode->nsName);
22449 else
22450 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22451 vctxt->inode->localName, vctxt->inode->nsName);
22452
22453 if (res == -1) {
22454 VERROR_INT("xmlSchemaXPathEvaluate",
22455 "calling xmlStreamPush()");
22456 return (-1);
22457 }
22458 if (res == 0)
22459 goto next_sto;
22460 /*
22461 * Full match.
22462 */
22463 /*
22464 * Register a match in the state object history.
22465 */
22466 if (sto->history == NULL) {
22467 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22468 if (sto->history == NULL) {
22469 xmlSchemaVErrMemory(NULL);
22470 return(-1);
22471 }
22472 sto->sizeHistory = 5;
22473 } else if (sto->sizeHistory <= sto->nbHistory) {
22474 sto->sizeHistory *= 2;
22475 sto->history = (int *) xmlRealloc(sto->history,
22476 sto->sizeHistory * sizeof(int));
22477 if (sto->history == NULL) {
22478 xmlSchemaVErrMemory(NULL);
22479 return(-1);
22480 }
22481 }
22482 sto->history[sto->nbHistory++] = depth;
22483
22484 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22485 xmlSchemaIDCSelectPtr sel;
22486 /*
22487 * Activate state objects for the IDC fields of
22488 * the IDC selector.
22489 */
22490 sel = sto->matcher->aidc->def->fields;
22491 while (sel != NULL) {
22492 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22493 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22494 return (-1);
22495 sel = sel->next;
22496 }
22497 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22498 /*
22499 * An IDC key node was found by the IDC field.
22500 */
22501 /*
22502 * Notify that the character value of this node is
22503 * needed.
22504 */
22505 if (resolved == 0) {
22506 if ((vctxt->inode->flags &
22507 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22508 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22509 }
22510 resolved++;
22511 }
22512 next_sto:
22513 if (sto->next == NULL) {
22514 /*
22515 * Evaluate field state objects created on this node as well.
22516 */
22517 head = first;
22518 sto = vctxt->xpathStates;
22519 } else
22520 sto = sto->next;
22521 }
22522 return (resolved);
22523 }
22524
22525 static const xmlChar *
xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count,int for_hash)22526 xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
22527 xmlChar **buf,
22528 xmlSchemaPSVIIDCKeyPtr *seq,
22529 int count, int for_hash)
22530 {
22531 int i, res;
22532 xmlChar *value = NULL;
22533
22534 *buf = xmlStrdup(BAD_CAST "[");
22535 for (i = 0; i < count; i++) {
22536 *buf = xmlStrcat(*buf, BAD_CAST "'");
22537 if (!for_hash)
22538 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22539 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22540 &value);
22541 else {
22542 res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
22543 }
22544 if (res == 0)
22545 *buf = xmlStrcat(*buf, BAD_CAST value);
22546 else {
22547 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22548 "failed to compute a canonical value");
22549 *buf = xmlStrcat(*buf, BAD_CAST "???");
22550 }
22551 if (i < count -1)
22552 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22553 else
22554 *buf = xmlStrcat(*buf, BAD_CAST "'");
22555 if (value != NULL) {
22556 xmlFree(value);
22557 value = NULL;
22558 }
22559 }
22560 *buf = xmlStrcat(*buf, BAD_CAST "]");
22561
22562 return (BAD_CAST *buf);
22563 }
22564
22565 static const xmlChar *
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22566 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22567 xmlChar **buf,
22568 xmlSchemaPSVIIDCKeyPtr *seq,
22569 int count)
22570 {
22571 return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
22572 }
22573
22574 static const xmlChar *
xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22575 xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
22576 xmlChar **buf,
22577 xmlSchemaPSVIIDCKeyPtr *seq,
22578 int count)
22579 {
22580 return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
22581 }
22582
22583 /**
22584 * xmlSchemaXPathPop:
22585 * @vctxt: the WXS validation context
22586 *
22587 * Pops all XPath states.
22588 *
22589 * Returns 0 on success and -1 on internal errors.
22590 */
22591 static int
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)22592 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22593 {
22594 xmlSchemaIDCStateObjPtr sto;
22595 int res;
22596
22597 if (vctxt->xpathStates == NULL)
22598 return(0);
22599 sto = vctxt->xpathStates;
22600 do {
22601 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22602 if (res == -1)
22603 return (-1);
22604 sto = sto->next;
22605 } while (sto != NULL);
22606 return(0);
22607 }
22608
22609 /**
22610 * xmlSchemaXPathProcessHistory:
22611 * @vctxt: the WXS validation context
22612 * @type: the simple/complex type of the current node if any at all
22613 * @val: the precompiled value
22614 *
22615 * Processes and pops the history items of the IDC state objects.
22616 * IDC key-sequences are validated/created on IDC bindings.
22617 *
22618 * Returns 0 on success and -1 on internal errors.
22619 */
22620 static int
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,int depth)22621 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22622 int depth)
22623 {
22624 xmlSchemaIDCStateObjPtr sto, nextsto;
22625 int res, matchDepth;
22626 xmlSchemaPSVIIDCKeyPtr key = NULL;
22627 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22628
22629 if (vctxt->xpathStates == NULL)
22630 return (0);
22631 sto = vctxt->xpathStates;
22632
22633 /*
22634 * Evaluate the state objects.
22635 */
22636 while (sto != NULL) {
22637 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22638 if (res == -1) {
22639 VERROR_INT("xmlSchemaXPathProcessHistory",
22640 "calling xmlStreamPop()");
22641 return (-1);
22642 }
22643 if (sto->nbHistory == 0)
22644 goto deregister_check;
22645
22646 matchDepth = sto->history[sto->nbHistory -1];
22647
22648 /*
22649 * Only matches at the current depth are of interest.
22650 */
22651 if (matchDepth != depth) {
22652 sto = sto->next;
22653 continue;
22654 }
22655 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22656 /*
22657 * NOTE: According to
22658 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22659 * ... the simple-content of complex types is also allowed.
22660 */
22661
22662 if (WXS_IS_COMPLEX(type)) {
22663 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22664 /*
22665 * Sanity check for complex types with simple content.
22666 */
22667 simpleType = type->contentTypeDef;
22668 if (simpleType == NULL) {
22669 VERROR_INT("xmlSchemaXPathProcessHistory",
22670 "field resolves to a CT with simple content "
22671 "but the CT is missing the ST definition");
22672 return (-1);
22673 }
22674 } else
22675 simpleType = NULL;
22676 } else
22677 simpleType = type;
22678 if (simpleType == NULL) {
22679 xmlChar *str = NULL;
22680
22681 /*
22682 * Not qualified if the field resolves to a node of non
22683 * simple type.
22684 */
22685 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22686 XML_SCHEMAV_CVC_IDC, NULL,
22687 WXS_BASIC_CAST sto->matcher->aidc->def,
22688 "The XPath '%s' of a field of %s does evaluate to a node of "
22689 "non-simple type",
22690 sto->sel->xpath,
22691 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22692 FREE_AND_NULL(str);
22693 sto->nbHistory--;
22694 goto deregister_check;
22695 }
22696
22697 if ((key == NULL) && (vctxt->inode->val == NULL)) {
22698 /*
22699 * Failed to provide the normalized value; maybe
22700 * the value was invalid.
22701 */
22702 VERROR(XML_SCHEMAV_CVC_IDC,
22703 WXS_BASIC_CAST sto->matcher->aidc->def,
22704 "Warning: No precomputed value available, the value "
22705 "was either invalid or something strange happened");
22706 sto->nbHistory--;
22707 goto deregister_check;
22708 } else {
22709 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22710 xmlSchemaPSVIIDCKeyPtr *keySeq;
22711 int pos, idx;
22712
22713 /*
22714 * The key will be anchored on the matcher's list of
22715 * key-sequences. The position in this list is determined
22716 * by the target node's depth relative to the matcher's
22717 * depth of creation (i.e. the depth of the scope element).
22718 *
22719 * Element Depth Pos List-entries
22720 * <scope> 0 NULL
22721 * <bar> 1 NULL
22722 * <target/> 2 2 target
22723 * <bar>
22724 * </scope>
22725 *
22726 * The size of the list is only dependent on the depth of
22727 * the tree.
22728 * An entry will be NULLed in selector_leave, i.e. when
22729 * we hit the target's
22730 */
22731 pos = sto->depth - matcher->depth;
22732 idx = sto->sel->index;
22733
22734 /*
22735 * Create/grow the array of key-sequences.
22736 */
22737 if (matcher->keySeqs == NULL) {
22738 if (pos > 9)
22739 matcher->sizeKeySeqs = pos * 2;
22740 else
22741 matcher->sizeKeySeqs = 10;
22742 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22743 xmlMalloc(matcher->sizeKeySeqs *
22744 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22745 if (matcher->keySeqs == NULL) {
22746 xmlSchemaVErrMemory(NULL);
22747 return(-1);
22748 }
22749 memset(matcher->keySeqs, 0,
22750 matcher->sizeKeySeqs *
22751 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22752 } else if (pos >= matcher->sizeKeySeqs) {
22753 int i = matcher->sizeKeySeqs;
22754
22755 matcher->sizeKeySeqs = pos * 2;
22756 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22757 xmlRealloc(matcher->keySeqs,
22758 matcher->sizeKeySeqs *
22759 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22760 if (matcher->keySeqs == NULL) {
22761 xmlSchemaVErrMemory(NULL);
22762 return (-1);
22763 }
22764 /*
22765 * The array needs to be NULLed.
22766 * TODO: Use memset?
22767 */
22768 for (; i < matcher->sizeKeySeqs; i++)
22769 matcher->keySeqs[i] = NULL;
22770 }
22771
22772 /*
22773 * Get/create the key-sequence.
22774 */
22775 keySeq = matcher->keySeqs[pos];
22776 if (keySeq == NULL) {
22777 goto create_sequence;
22778 } else if (keySeq[idx] != NULL) {
22779 xmlChar *str = NULL;
22780 /*
22781 * cvc-identity-constraint:
22782 * 3 For each node in the `target node set` all
22783 * of the {fields}, with that node as the context
22784 * node, evaluate to either an empty node-set or
22785 * a node-set with exactly one member, which must
22786 * have a simple type.
22787 *
22788 * The key was already set; report an error.
22789 */
22790 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22791 XML_SCHEMAV_CVC_IDC, NULL,
22792 WXS_BASIC_CAST matcher->aidc->def,
22793 "The XPath '%s' of a field of %s evaluates to a "
22794 "node-set with more than one member",
22795 sto->sel->xpath,
22796 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22797 FREE_AND_NULL(str);
22798 sto->nbHistory--;
22799 goto deregister_check;
22800 } else
22801 goto create_key;
22802
22803 create_sequence:
22804 /*
22805 * Create a key-sequence.
22806 */
22807 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22808 matcher->aidc->def->nbFields *
22809 sizeof(xmlSchemaPSVIIDCKeyPtr));
22810 if (keySeq == NULL) {
22811 xmlSchemaVErrMemory(NULL);
22812 return(-1);
22813 }
22814 memset(keySeq, 0, matcher->aidc->def->nbFields *
22815 sizeof(xmlSchemaPSVIIDCKeyPtr));
22816 matcher->keySeqs[pos] = keySeq;
22817 create_key:
22818 /*
22819 * Create a key once per node only.
22820 */
22821 if (key == NULL) {
22822 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22823 sizeof(xmlSchemaPSVIIDCKey));
22824 if (key == NULL) {
22825 xmlSchemaVErrMemory(NULL);
22826 xmlFree(keySeq);
22827 matcher->keySeqs[pos] = NULL;
22828 return(-1);
22829 }
22830 /*
22831 * Consume the compiled value.
22832 */
22833 key->type = simpleType;
22834 key->val = vctxt->inode->val;
22835 vctxt->inode->val = NULL;
22836 /*
22837 * Store the key in a global list.
22838 */
22839 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22840 xmlSchemaIDCFreeKey(key);
22841 return (-1);
22842 }
22843 }
22844 keySeq[idx] = key;
22845 }
22846 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22847
22848 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22849 /* xmlSchemaPSVIIDCBindingPtr bind; */
22850 xmlSchemaPSVIIDCNodePtr ntItem;
22851 xmlSchemaIDCMatcherPtr matcher;
22852 xmlSchemaIDCPtr idc;
22853 xmlSchemaItemListPtr targets;
22854 int pos, i, j, nbKeys;
22855 /*
22856 * Here we have the following scenario:
22857 * An IDC 'selector' state object resolved to a target node,
22858 * during the time this target node was in the
22859 * ancestor-or-self axis, the 'field' state object(s) looked
22860 * out for matching nodes to create a key-sequence for this
22861 * target node. Now we are back to this target node and need
22862 * to put the key-sequence, together with the target node
22863 * itself, into the node-table of the corresponding IDC
22864 * binding.
22865 */
22866 matcher = sto->matcher;
22867 idc = matcher->aidc->def;
22868 nbKeys = idc->nbFields;
22869 pos = depth - matcher->depth;
22870 /*
22871 * Check if the matcher has any key-sequences at all, plus
22872 * if it has a key-sequence for the current target node.
22873 */
22874 if ((matcher->keySeqs == NULL) ||
22875 (matcher->sizeKeySeqs <= pos)) {
22876 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22877 goto selector_key_error;
22878 else
22879 goto selector_leave;
22880 }
22881
22882 keySeq = &(matcher->keySeqs[pos]);
22883 if (*keySeq == NULL) {
22884 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22885 goto selector_key_error;
22886 else
22887 goto selector_leave;
22888 }
22889
22890 for (i = 0; i < nbKeys; i++) {
22891 if ((*keySeq)[i] == NULL) {
22892 /*
22893 * Not qualified, if not all fields did resolve.
22894 */
22895 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22896 /*
22897 * All fields of a "key" IDC must resolve.
22898 */
22899 goto selector_key_error;
22900 }
22901 goto selector_leave;
22902 }
22903 }
22904 /*
22905 * All fields did resolve.
22906 */
22907
22908 /*
22909 * 4.1 If the {identity-constraint category} is unique(/key),
22910 * then no two members of the `qualified node set` have
22911 * `key-sequences` whose members are pairwise equal, as
22912 * defined by Equal in [XML Schemas: Datatypes].
22913 *
22914 * Get the IDC binding from the matcher and check for
22915 * duplicate key-sequences.
22916 */
22917 #if 0
22918 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22919 #endif
22920 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22921 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22922 (targets->nbItems != 0)) {
22923 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22924 xmlIDCHashEntryPtr e;
22925
22926 res = 0;
22927
22928 if (!matcher->htab)
22929 e = NULL;
22930 else {
22931 xmlChar *value = NULL;
22932 xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
22933 e = xmlHashLookup(matcher->htab, value);
22934 FREE_AND_NULL(value);
22935 }
22936
22937 /*
22938 * Compare the key-sequences, key by key.
22939 */
22940 for (;e; e = e->next) {
22941 bkeySeq =
22942 ((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
22943 for (j = 0; j < nbKeys; j++) {
22944 ckey = (*keySeq)[j];
22945 bkey = bkeySeq[j];
22946 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22947 if (res == -1) {
22948 return (-1);
22949 } else if (res == 0) {
22950 /*
22951 * One of the keys differs, so the key-sequence
22952 * won't be equal; get out.
22953 */
22954 break;
22955 }
22956 }
22957 if (res == 1) {
22958 /*
22959 * Duplicate key-sequence found.
22960 */
22961 break;
22962 }
22963 }
22964 if (e) {
22965 xmlChar *str = NULL, *strB = NULL;
22966 /*
22967 * TODO: Try to report the key-sequence.
22968 */
22969 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22970 XML_SCHEMAV_CVC_IDC, NULL,
22971 WXS_BASIC_CAST idc,
22972 "Duplicate key-sequence %s in %s",
22973 xmlSchemaFormatIDCKeySequence(vctxt, &str,
22974 (*keySeq), nbKeys),
22975 xmlSchemaGetIDCDesignation(&strB, idc));
22976 FREE_AND_NULL(str);
22977 FREE_AND_NULL(strB);
22978 goto selector_leave;
22979 }
22980 }
22981 /*
22982 * Add a node-table item to the IDC binding.
22983 */
22984 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22985 sizeof(xmlSchemaPSVIIDCNode));
22986 if (ntItem == NULL) {
22987 xmlSchemaVErrMemory(NULL);
22988 xmlFree(*keySeq);
22989 *keySeq = NULL;
22990 return(-1);
22991 }
22992 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
22993
22994 /*
22995 * Store the node-table item in a global list.
22996 */
22997 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22998 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22999 xmlFree(ntItem);
23000 xmlFree(*keySeq);
23001 *keySeq = NULL;
23002 return (-1);
23003 }
23004 ntItem->nodeQNameID = -1;
23005 } else {
23006 /*
23007 * Save a cached QName for this node on the IDC node, to be
23008 * able to report it, even if the node is not saved.
23009 */
23010 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23011 vctxt->inode->localName, vctxt->inode->nsName);
23012 if (ntItem->nodeQNameID == -1) {
23013 xmlFree(ntItem);
23014 xmlFree(*keySeq);
23015 *keySeq = NULL;
23016 return (-1);
23017 }
23018 }
23019 /*
23020 * Init the node-table item: Save the node, position and
23021 * consume the key-sequence.
23022 */
23023 ntItem->node = vctxt->node;
23024 ntItem->nodeLine = vctxt->inode->nodeLine;
23025 ntItem->keys = *keySeq;
23026 *keySeq = NULL;
23027 #if 0
23028 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23029 #endif
23030 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23031 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23032 /*
23033 * Free the item, since keyref items won't be
23034 * put on a global list.
23035 */
23036 xmlFree(ntItem->keys);
23037 xmlFree(ntItem);
23038 }
23039 return (-1);
23040 }
23041 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23042 xmlChar *value = NULL;
23043 xmlIDCHashEntryPtr r, e;
23044 if (!matcher->htab)
23045 matcher->htab = xmlHashCreate(4);
23046 xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
23047 e = xmlMalloc(sizeof *e);
23048 e->index = targets->nbItems - 1;
23049 r = xmlHashLookup(matcher->htab, value);
23050 if (r) {
23051 e->next = r->next;
23052 r->next = e;
23053 } else {
23054 e->next = NULL;
23055 xmlHashAddEntry(matcher->htab, value, e);
23056 }
23057 FREE_AND_NULL(value);
23058 }
23059
23060 goto selector_leave;
23061 selector_key_error:
23062 {
23063 xmlChar *str = NULL;
23064 /*
23065 * 4.2.1 (KEY) The `target node set` and the
23066 * `qualified node set` are equal, that is, every
23067 * member of the `target node set` is also a member
23068 * of the `qualified node set` and vice versa.
23069 */
23070 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23071 XML_SCHEMAV_CVC_IDC, NULL,
23072 WXS_BASIC_CAST idc,
23073 "Not all fields of %s evaluate to a node",
23074 xmlSchemaGetIDCDesignation(&str, idc), NULL);
23075 FREE_AND_NULL(str);
23076 }
23077 selector_leave:
23078 /*
23079 * Free the key-sequence if not added to the IDC table.
23080 */
23081 if ((keySeq != NULL) && (*keySeq != NULL)) {
23082 xmlFree(*keySeq);
23083 *keySeq = NULL;
23084 }
23085 } /* if selector */
23086
23087 sto->nbHistory--;
23088
23089 deregister_check:
23090 /*
23091 * Deregister state objects if they reach the depth of creation.
23092 */
23093 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23094 if (vctxt->xpathStates != sto) {
23095 VERROR_INT("xmlSchemaXPathProcessHistory",
23096 "The state object to be removed is not the first "
23097 "in the list");
23098 }
23099 nextsto = sto->next;
23100 /*
23101 * Unlink from the list of active XPath state objects.
23102 */
23103 vctxt->xpathStates = sto->next;
23104 sto->next = vctxt->xpathStatePool;
23105 /*
23106 * Link it to the pool of reusable state objects.
23107 */
23108 vctxt->xpathStatePool = sto;
23109 sto = nextsto;
23110 } else
23111 sto = sto->next;
23112 } /* while (sto != NULL) */
23113 return (0);
23114 }
23115
23116 /**
23117 * xmlSchemaIDCRegisterMatchers:
23118 * @vctxt: the WXS validation context
23119 * @elemDecl: the element declaration
23120 *
23121 * Creates helper objects to evaluate IDC selectors/fields
23122 * successively.
23123 *
23124 * Returns 0 if OK and -1 on internal errors.
23125 */
23126 static int
xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,xmlSchemaElementPtr elemDecl)23127 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23128 xmlSchemaElementPtr elemDecl)
23129 {
23130 xmlSchemaIDCMatcherPtr matcher, last = NULL;
23131 xmlSchemaIDCPtr idc, refIdc;
23132 xmlSchemaIDCAugPtr aidc;
23133
23134 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23135 if (idc == NULL)
23136 return (0);
23137
23138 if (vctxt->inode->idcMatchers != NULL) {
23139 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23140 "The chain of IDC matchers is expected to be empty");
23141 return (-1);
23142 }
23143 do {
23144 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23145 /*
23146 * Since IDCs bubbles are expensive we need to know the
23147 * depth at which the bubbles should stop; this will be
23148 * the depth of the top-most keyref IDC. If no keyref
23149 * references a key/unique IDC, the keyrefDepth will
23150 * be -1, indicating that no bubbles are needed.
23151 */
23152 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23153 if (refIdc != NULL) {
23154 /*
23155 * Remember that we have keyrefs on this node.
23156 */
23157 vctxt->inode->hasKeyrefs = 1;
23158 /*
23159 * Lookup the referenced augmented IDC info.
23160 */
23161 aidc = vctxt->aidcs;
23162 while (aidc != NULL) {
23163 if (aidc->def == refIdc)
23164 break;
23165 aidc = aidc->next;
23166 }
23167 if (aidc == NULL) {
23168 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23169 "Could not find an augmented IDC item for an IDC "
23170 "definition");
23171 return (-1);
23172 }
23173 if ((aidc->keyrefDepth == -1) ||
23174 (vctxt->depth < aidc->keyrefDepth))
23175 aidc->keyrefDepth = vctxt->depth;
23176 }
23177 }
23178 /*
23179 * Lookup the augmented IDC item for the IDC definition.
23180 */
23181 aidc = vctxt->aidcs;
23182 while (aidc != NULL) {
23183 if (aidc->def == idc)
23184 break;
23185 aidc = aidc->next;
23186 }
23187 if (aidc == NULL) {
23188 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23189 "Could not find an augmented IDC item for an IDC definition");
23190 return (-1);
23191 }
23192 /*
23193 * Create an IDC matcher for every IDC definition.
23194 */
23195 if (vctxt->idcMatcherCache != NULL) {
23196 /*
23197 * Reuse a cached matcher.
23198 */
23199 matcher = vctxt->idcMatcherCache;
23200 vctxt->idcMatcherCache = matcher->nextCached;
23201 matcher->nextCached = NULL;
23202 } else {
23203 matcher = (xmlSchemaIDCMatcherPtr)
23204 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23205 if (matcher == NULL) {
23206 xmlSchemaVErrMemory(vctxt);
23207 return (-1);
23208 }
23209 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23210 }
23211 if (last == NULL)
23212 vctxt->inode->idcMatchers = matcher;
23213 else
23214 last->next = matcher;
23215 last = matcher;
23216
23217 matcher->type = IDC_MATCHER;
23218 matcher->depth = vctxt->depth;
23219 matcher->aidc = aidc;
23220 matcher->idcType = aidc->def->type;
23221 /*
23222 * Init the automaton state object.
23223 */
23224 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23225 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23226 return (-1);
23227
23228 idc = idc->next;
23229 } while (idc != NULL);
23230 return (0);
23231 }
23232
23233 static int
xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23234 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23235 xmlSchemaNodeInfoPtr ielem)
23236 {
23237 xmlSchemaPSVIIDCBindingPtr bind;
23238 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23239 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23240 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23241
23242 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23243 /* vctxt->createIDCNodeTables */
23244 while (matcher != NULL) {
23245 /*
23246 * Skip keyref IDCs and empty IDC target-lists.
23247 */
23248 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23249 WXS_ILIST_IS_EMPTY(matcher->targets))
23250 {
23251 matcher = matcher->next;
23252 continue;
23253 }
23254 /*
23255 * If we _want_ the IDC node-table to be created in any case
23256 * then do so. Otherwise create them only if keyrefs need them.
23257 */
23258 if ((! vctxt->createIDCNodeTables) &&
23259 ((matcher->aidc->keyrefDepth == -1) ||
23260 (matcher->aidc->keyrefDepth > vctxt->depth)))
23261 {
23262 matcher = matcher->next;
23263 continue;
23264 }
23265 /*
23266 * Get/create the IDC binding on this element for the IDC definition.
23267 */
23268 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23269 if (bind == NULL)
23270 goto internal_error;
23271
23272 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23273 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23274 nbDupls = bind->dupls->nbItems;
23275 } else {
23276 dupls = NULL;
23277 nbDupls = 0;
23278 }
23279 if (bind->nodeTable != NULL) {
23280 nbNodeTable = bind->nbNodes;
23281 } else {
23282 nbNodeTable = 0;
23283 }
23284
23285 if ((nbNodeTable == 0) && (nbDupls == 0)) {
23286 /*
23287 * Transfer all IDC target-nodes to the IDC node-table.
23288 */
23289 bind->nodeTable =
23290 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23291 bind->sizeNodes = matcher->targets->sizeItems;
23292 bind->nbNodes = matcher->targets->nbItems;
23293
23294 matcher->targets->items = NULL;
23295 matcher->targets->sizeItems = 0;
23296 matcher->targets->nbItems = 0;
23297 if (matcher->htab) {
23298 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
23299 matcher->htab = NULL;
23300 }
23301 } else {
23302 /*
23303 * Compare the key-sequences and add to the IDC node-table.
23304 */
23305 nbTargets = matcher->targets->nbItems;
23306 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23307 nbFields = matcher->aidc->def->nbFields;
23308 i = 0;
23309 do {
23310 keys = targets[i]->keys;
23311 if (nbDupls) {
23312 /*
23313 * Search in already found duplicates first.
23314 */
23315 j = 0;
23316 do {
23317 if (nbFields == 1) {
23318 res = xmlSchemaAreValuesEqual(keys[0]->val,
23319 dupls[j]->keys[0]->val);
23320 if (res == -1)
23321 goto internal_error;
23322 if (res == 1) {
23323 /*
23324 * Equal key-sequence.
23325 */
23326 goto next_target;
23327 }
23328 } else {
23329 res = 0;
23330 ntkeys = dupls[j]->keys;
23331 for (k = 0; k < nbFields; k++) {
23332 res = xmlSchemaAreValuesEqual(keys[k]->val,
23333 ntkeys[k]->val);
23334 if (res == -1)
23335 goto internal_error;
23336 if (res == 0) {
23337 /*
23338 * One of the keys differs.
23339 */
23340 break;
23341 }
23342 }
23343 if (res == 1) {
23344 /*
23345 * Equal key-sequence found.
23346 */
23347 goto next_target;
23348 }
23349 }
23350 j++;
23351 } while (j < nbDupls);
23352 }
23353 if (nbNodeTable) {
23354 j = 0;
23355 do {
23356 if (nbFields == 1) {
23357 res = xmlSchemaAreValuesEqual(keys[0]->val,
23358 bind->nodeTable[j]->keys[0]->val);
23359 if (res == -1)
23360 goto internal_error;
23361 if (res == 0) {
23362 /*
23363 * The key-sequence differs.
23364 */
23365 goto next_node_table_entry;
23366 }
23367 } else {
23368 res = 0;
23369 ntkeys = bind->nodeTable[j]->keys;
23370 for (k = 0; k < nbFields; k++) {
23371 res = xmlSchemaAreValuesEqual(keys[k]->val,
23372 ntkeys[k]->val);
23373 if (res == -1)
23374 goto internal_error;
23375 if (res == 0) {
23376 /*
23377 * One of the keys differs.
23378 */
23379 goto next_node_table_entry;
23380 }
23381 }
23382 }
23383 /*
23384 * Add the duplicate to the list of duplicates.
23385 */
23386 if (bind->dupls == NULL) {
23387 bind->dupls = xmlSchemaItemListCreate();
23388 if (bind->dupls == NULL)
23389 goto internal_error;
23390 }
23391 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23392 goto internal_error;
23393 /*
23394 * Remove the duplicate entry from the IDC node-table.
23395 */
23396 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23397 bind->nbNodes--;
23398
23399 goto next_target;
23400
23401 next_node_table_entry:
23402 j++;
23403 } while (j < nbNodeTable);
23404 }
23405 /*
23406 * If everything is fine, then add the IDC target-node to
23407 * the IDC node-table.
23408 */
23409 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23410 goto internal_error;
23411
23412 next_target:
23413 i++;
23414 } while (i < nbTargets);
23415 }
23416 matcher = matcher->next;
23417 }
23418 return(0);
23419
23420 internal_error:
23421 return(-1);
23422 }
23423
23424 /**
23425 * xmlSchemaBubbleIDCNodeTables:
23426 * @depth: the current tree depth
23427 *
23428 * Merges IDC bindings of an element at @depth into the corresponding IDC
23429 * bindings of its parent element. If a duplicate note-table entry is found,
23430 * both, the parent node-table entry and child entry are discarded from the
23431 * node-table of the parent.
23432 *
23433 * Returns 0 if OK and -1 on internal errors.
23434 */
23435 static int
xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)23436 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23437 {
23438 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23439 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23440 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23441 xmlSchemaIDCAugPtr aidc;
23442 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23443
23444 bind = vctxt->inode->idcTable;
23445 if (bind == NULL) {
23446 /* Fine, no table, no bubbles. */
23447 return (0);
23448 }
23449
23450 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23451 /*
23452 * Walk all bindings; create new or add to existing bindings.
23453 * Remove duplicate key-sequences.
23454 */
23455 while (bind != NULL) {
23456
23457 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23458 goto next_binding;
23459 /*
23460 * Check if the key/unique IDC table needs to be bubbled.
23461 */
23462 if (! vctxt->createIDCNodeTables) {
23463 aidc = vctxt->aidcs;
23464 do {
23465 if (aidc->def == bind->definition) {
23466 if ((aidc->keyrefDepth == -1) ||
23467 (aidc->keyrefDepth >= vctxt->depth)) {
23468 goto next_binding;
23469 }
23470 break;
23471 }
23472 aidc = aidc->next;
23473 } while (aidc != NULL);
23474 }
23475
23476 if (parTable != NULL)
23477 parBind = *parTable;
23478 /*
23479 * Search a matching parent binding for the
23480 * IDC definition.
23481 */
23482 while (parBind != NULL) {
23483 if (parBind->definition == bind->definition)
23484 break;
23485 parBind = parBind->next;
23486 }
23487
23488 if (parBind != NULL) {
23489 /*
23490 * Compare every node-table entry of the child node,
23491 * i.e. the key-sequence within, ...
23492 */
23493 oldNum = parBind->nbNodes; /* Skip newly added items. */
23494
23495 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23496 oldDupls = parBind->dupls->nbItems;
23497 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23498 } else {
23499 dupls = NULL;
23500 oldDupls = 0;
23501 }
23502
23503 parNodes = parBind->nodeTable;
23504 nbFields = bind->definition->nbFields;
23505
23506 for (i = 0; i < bind->nbNodes; i++) {
23507 node = bind->nodeTable[i];
23508 if (node == NULL)
23509 continue;
23510 /*
23511 * ...with every key-sequence of the parent node, already
23512 * evaluated to be a duplicate key-sequence.
23513 */
23514 if (oldDupls) {
23515 j = 0;
23516 while (j < oldDupls) {
23517 if (nbFields == 1) {
23518 ret = xmlSchemaAreValuesEqual(
23519 node->keys[0]->val,
23520 dupls[j]->keys[0]->val);
23521 if (ret == -1)
23522 goto internal_error;
23523 if (ret == 0) {
23524 j++;
23525 continue;
23526 }
23527 } else {
23528 parNode = dupls[j];
23529 for (k = 0; k < nbFields; k++) {
23530 ret = xmlSchemaAreValuesEqual(
23531 node->keys[k]->val,
23532 parNode->keys[k]->val);
23533 if (ret == -1)
23534 goto internal_error;
23535 if (ret == 0)
23536 break;
23537 }
23538 }
23539 if (ret == 1)
23540 /* Duplicate found. */
23541 break;
23542 j++;
23543 }
23544 if (j != oldDupls) {
23545 /* Duplicate found. Skip this entry. */
23546 continue;
23547 }
23548 }
23549 /*
23550 * ... and with every key-sequence of the parent node.
23551 */
23552 if (oldNum) {
23553 j = 0;
23554 while (j < oldNum) {
23555 parNode = parNodes[j];
23556 if (nbFields == 1) {
23557 ret = xmlSchemaAreValuesEqual(
23558 node->keys[0]->val,
23559 parNode->keys[0]->val);
23560 if (ret == -1)
23561 goto internal_error;
23562 if (ret == 0) {
23563 j++;
23564 continue;
23565 }
23566 } else {
23567 for (k = 0; k < nbFields; k++) {
23568 ret = xmlSchemaAreValuesEqual(
23569 node->keys[k]->val,
23570 parNode->keys[k]->val);
23571 if (ret == -1)
23572 goto internal_error;
23573 if (ret == 0)
23574 break;
23575 }
23576 }
23577 if (ret == 1)
23578 /* Duplicate found. */
23579 break;
23580 j++;
23581 }
23582 if (j != oldNum) {
23583 /*
23584 * Handle duplicates. Move the duplicate in
23585 * the parent's node-table to the list of
23586 * duplicates.
23587 */
23588 oldNum--;
23589 parBind->nbNodes--;
23590 /*
23591 * Move last old item to pos of duplicate.
23592 */
23593 parNodes[j] = parNodes[oldNum];
23594
23595 if (parBind->nbNodes != oldNum) {
23596 /*
23597 * If new items exist, move last new item to
23598 * last of old items.
23599 */
23600 parNodes[oldNum] =
23601 parNodes[parBind->nbNodes];
23602 }
23603 if (parBind->dupls == NULL) {
23604 parBind->dupls = xmlSchemaItemListCreate();
23605 if (parBind->dupls == NULL)
23606 goto internal_error;
23607 }
23608 xmlSchemaItemListAdd(parBind->dupls, parNode);
23609 } else {
23610 /*
23611 * Add the node-table entry (node and key-sequence) of
23612 * the child node to the node table of the parent node.
23613 */
23614 if (parBind->nodeTable == NULL) {
23615 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23616 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23617 if (parBind->nodeTable == NULL) {
23618 xmlSchemaVErrMemory(NULL);
23619 goto internal_error;
23620 }
23621 parBind->sizeNodes = 1;
23622 } else if (parBind->nbNodes >= parBind->sizeNodes) {
23623 parBind->sizeNodes *= 2;
23624 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23625 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23626 sizeof(xmlSchemaPSVIIDCNodePtr));
23627 if (parBind->nodeTable == NULL) {
23628 xmlSchemaVErrMemory(NULL);
23629 goto internal_error;
23630 }
23631 }
23632 parNodes = parBind->nodeTable;
23633 /*
23634 * Append the new node-table entry to the 'new node-table
23635 * entries' section.
23636 */
23637 parNodes[parBind->nbNodes++] = node;
23638 }
23639
23640 }
23641
23642 }
23643 } else {
23644 /*
23645 * No binding for the IDC was found: create a new one and
23646 * copy all node-tables.
23647 */
23648 parBind = xmlSchemaIDCNewBinding(bind->definition);
23649 if (parBind == NULL)
23650 goto internal_error;
23651
23652 /*
23653 * TODO: Hmm, how to optimize the initial number of
23654 * allocated entries?
23655 */
23656 if (bind->nbNodes != 0) {
23657 /*
23658 * Add all IDC node-table entries.
23659 */
23660 if (! vctxt->psviExposeIDCNodeTables) {
23661 /*
23662 * Just move the entries.
23663 * NOTE: this is quite save here, since
23664 * all the keyref lookups have already been
23665 * performed.
23666 */
23667 parBind->nodeTable = bind->nodeTable;
23668 bind->nodeTable = NULL;
23669 parBind->sizeNodes = bind->sizeNodes;
23670 bind->sizeNodes = 0;
23671 parBind->nbNodes = bind->nbNodes;
23672 bind->nbNodes = 0;
23673 } else {
23674 /*
23675 * Copy the entries.
23676 */
23677 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23678 xmlMalloc(bind->nbNodes *
23679 sizeof(xmlSchemaPSVIIDCNodePtr));
23680 if (parBind->nodeTable == NULL) {
23681 xmlSchemaVErrMemory(NULL);
23682 xmlSchemaIDCFreeBinding(parBind);
23683 goto internal_error;
23684 }
23685 parBind->sizeNodes = bind->nbNodes;
23686 parBind->nbNodes = bind->nbNodes;
23687 memcpy(parBind->nodeTable, bind->nodeTable,
23688 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23689 }
23690 }
23691 if (bind->dupls) {
23692 /*
23693 * Move the duplicates.
23694 */
23695 if (parBind->dupls != NULL)
23696 xmlSchemaItemListFree(parBind->dupls);
23697 parBind->dupls = bind->dupls;
23698 bind->dupls = NULL;
23699 }
23700 if (parTable != NULL) {
23701 if (*parTable == NULL)
23702 *parTable = parBind;
23703 else {
23704 parBind->next = *parTable;
23705 *parTable = parBind;
23706 }
23707 }
23708 }
23709
23710 next_binding:
23711 bind = bind->next;
23712 }
23713 return (0);
23714
23715 internal_error:
23716 return(-1);
23717 }
23718
23719 /**
23720 * xmlSchemaCheckCVCIDCKeyRef:
23721 * @vctxt: the WXS validation context
23722 * @elemDecl: the element declaration
23723 *
23724 * Check the cvc-idc-keyref constraints.
23725 */
23726 static int
xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)23727 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23728 {
23729 xmlSchemaIDCMatcherPtr matcher;
23730 xmlSchemaPSVIIDCBindingPtr bind;
23731
23732 matcher = vctxt->inode->idcMatchers;
23733 /*
23734 * Find a keyref.
23735 */
23736 while (matcher != NULL) {
23737 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23738 matcher->targets &&
23739 matcher->targets->nbItems)
23740 {
23741 int i, j, k, res, nbFields, hasDupls;
23742 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23743 xmlSchemaPSVIIDCNodePtr refNode = NULL;
23744 xmlHashTablePtr table = NULL;
23745
23746 nbFields = matcher->aidc->def->nbFields;
23747
23748 /*
23749 * Find the IDC node-table for the referenced IDC key/unique.
23750 */
23751 bind = vctxt->inode->idcTable;
23752 while (bind != NULL) {
23753 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23754 bind->definition)
23755 break;
23756 bind = bind->next;
23757 }
23758 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23759 /*
23760 * Search for a matching key-sequences.
23761 */
23762 if (bind) {
23763 table = xmlHashCreate(bind->nbNodes * 2);
23764 for (j = 0; j < bind->nbNodes; j++) {
23765 xmlChar *value;
23766 xmlIDCHashEntryPtr r, e;
23767 keys = bind->nodeTable[j]->keys;
23768 xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
23769 e = xmlMalloc(sizeof *e);
23770 e->index = j;
23771 r = xmlHashLookup(table, value);
23772 if (r) {
23773 e->next = r->next;
23774 r->next = e;
23775 } else {
23776 e->next = NULL;
23777 xmlHashAddEntry(table, value, e);
23778 }
23779 FREE_AND_NULL(value);
23780 }
23781 }
23782 for (i = 0; i < matcher->targets->nbItems; i++) {
23783 res = 0;
23784 refNode = matcher->targets->items[i];
23785 if (bind != NULL) {
23786 xmlChar *value;
23787 xmlIDCHashEntryPtr e;
23788 refKeys = refNode->keys;
23789 xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
23790 e = xmlHashLookup(table, value);
23791 FREE_AND_NULL(value);
23792 res = 0;
23793 for (;e; e = e->next) {
23794 keys = bind->nodeTable[e->index]->keys;
23795 for (k = 0; k < nbFields; k++) {
23796 res = xmlSchemaAreValuesEqual(keys[k]->val,
23797 refKeys[k]->val);
23798 if (res == 0)
23799 break;
23800 else if (res == -1) {
23801 return (-1);
23802 }
23803 }
23804 if (res == 1) {
23805 /*
23806 * Match found.
23807 */
23808 break;
23809 }
23810 }
23811 if ((res == 0) && hasDupls) {
23812 /*
23813 * Search in duplicates
23814 */
23815 for (j = 0; j < bind->dupls->nbItems; j++) {
23816 keys = ((xmlSchemaPSVIIDCNodePtr)
23817 bind->dupls->items[j])->keys;
23818 for (k = 0; k < nbFields; k++) {
23819 res = xmlSchemaAreValuesEqual(keys[k]->val,
23820 refKeys[k]->val);
23821 if (res == 0)
23822 break;
23823 else if (res == -1) {
23824 return (-1);
23825 }
23826 }
23827 if (res == 1) {
23828 /*
23829 * Match in duplicates found.
23830 */
23831 xmlChar *str = NULL, *strB = NULL;
23832 xmlSchemaKeyrefErr(vctxt,
23833 XML_SCHEMAV_CVC_IDC, refNode,
23834 (xmlSchemaTypePtr) matcher->aidc->def,
23835 "More than one match found for "
23836 "key-sequence %s of keyref '%s'",
23837 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23838 refNode->keys, nbFields),
23839 xmlSchemaGetComponentQName(&strB,
23840 matcher->aidc->def));
23841 FREE_AND_NULL(str);
23842 FREE_AND_NULL(strB);
23843 break;
23844 }
23845 }
23846 }
23847 }
23848
23849 if (res == 0) {
23850 xmlChar *str = NULL, *strB = NULL;
23851 xmlSchemaKeyrefErr(vctxt,
23852 XML_SCHEMAV_CVC_IDC, refNode,
23853 (xmlSchemaTypePtr) matcher->aidc->def,
23854 "No match found for key-sequence %s of keyref '%s'",
23855 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23856 refNode->keys, nbFields),
23857 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23858 FREE_AND_NULL(str);
23859 FREE_AND_NULL(strB);
23860 }
23861 }
23862 if (table) {
23863 xmlHashFree(table, xmlFreeIDCHashEntry);
23864 }
23865 }
23866 matcher = matcher->next;
23867 }
23868 /* TODO: Return an error if any error encountered. */
23869 return (0);
23870 }
23871
23872 /************************************************************************
23873 * *
23874 * XML Reader validation code *
23875 * *
23876 ************************************************************************/
23877
23878 static xmlSchemaAttrInfoPtr
xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)23879 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23880 {
23881 xmlSchemaAttrInfoPtr iattr;
23882 /*
23883 * Grow/create list of attribute infos.
23884 */
23885 if (vctxt->attrInfos == NULL) {
23886 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23887 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23888 vctxt->sizeAttrInfos = 1;
23889 if (vctxt->attrInfos == NULL) {
23890 xmlSchemaVErrMemory(vctxt);
23891 return (NULL);
23892 }
23893 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23894 vctxt->sizeAttrInfos++;
23895 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23896 xmlRealloc(vctxt->attrInfos,
23897 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23898 if (vctxt->attrInfos == NULL) {
23899 xmlSchemaVErrMemory(vctxt);
23900 return (NULL);
23901 }
23902 } else {
23903 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23904 if (iattr->localName != NULL) {
23905 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23906 "attr info not cleared");
23907 return (NULL);
23908 }
23909 iattr->nodeType = XML_ATTRIBUTE_NODE;
23910 return (iattr);
23911 }
23912 /*
23913 * Create an attribute info.
23914 */
23915 iattr = (xmlSchemaAttrInfoPtr)
23916 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23917 if (iattr == NULL) {
23918 xmlSchemaVErrMemory(vctxt);
23919 return (NULL);
23920 }
23921 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23922 iattr->nodeType = XML_ATTRIBUTE_NODE;
23923 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23924
23925 return (iattr);
23926 }
23927
23928 static int
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,xmlNodePtr attrNode,int nodeLine,const xmlChar * localName,const xmlChar * nsName,int ownedNames,xmlChar * value,int ownedValue)23929 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23930 xmlNodePtr attrNode,
23931 int nodeLine,
23932 const xmlChar *localName,
23933 const xmlChar *nsName,
23934 int ownedNames,
23935 xmlChar *value,
23936 int ownedValue)
23937 {
23938 xmlSchemaAttrInfoPtr attr;
23939
23940 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23941 if (attr == NULL) {
23942 VERROR_INT("xmlSchemaPushAttribute",
23943 "calling xmlSchemaGetFreshAttrInfo()");
23944 return (-1);
23945 }
23946 attr->node = attrNode;
23947 attr->nodeLine = nodeLine;
23948 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23949 attr->localName = localName;
23950 attr->nsName = nsName;
23951 if (ownedNames)
23952 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23953 /*
23954 * Evaluate if it's an XSI attribute.
23955 */
23956 if (nsName != NULL) {
23957 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23958 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23959 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23960 }
23961 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23962 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23963 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23964 }
23965 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23966 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23967 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23968 }
23969 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23970 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23971 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23972 }
23973 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23974 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23975 }
23976 }
23977 attr->value = value;
23978 if (ownedValue)
23979 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23980 if (attr->metaType != 0)
23981 attr->state = XML_SCHEMAS_ATTR_META;
23982 return (0);
23983 }
23984
23985 /**
23986 * xmlSchemaClearElemInfo:
23987 * @vctxt: the WXS validation context
23988 * @ielem: the element information item
23989 */
23990 static void
xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23991 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23992 xmlSchemaNodeInfoPtr ielem)
23993 {
23994 ielem->hasKeyrefs = 0;
23995 ielem->appliedXPath = 0;
23996 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23997 FREE_AND_NULL(ielem->localName);
23998 FREE_AND_NULL(ielem->nsName);
23999 } else {
24000 ielem->localName = NULL;
24001 ielem->nsName = NULL;
24002 }
24003 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24004 FREE_AND_NULL(ielem->value);
24005 } else {
24006 ielem->value = NULL;
24007 }
24008 if (ielem->val != NULL) {
24009 /*
24010 * PSVI TODO: Be careful not to free it when the value is
24011 * exposed via PSVI.
24012 */
24013 xmlSchemaFreeValue(ielem->val);
24014 ielem->val = NULL;
24015 }
24016 if (ielem->idcMatchers != NULL) {
24017 /*
24018 * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24019 * Does it work?
24020 */
24021 xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24022 #if 0
24023 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24024 #endif
24025 ielem->idcMatchers = NULL;
24026 }
24027 if (ielem->idcTable != NULL) {
24028 /*
24029 * OPTIMIZE TODO: Use a pool of IDC tables??.
24030 */
24031 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24032 ielem->idcTable = NULL;
24033 }
24034 if (ielem->regexCtxt != NULL) {
24035 xmlRegFreeExecCtxt(ielem->regexCtxt);
24036 ielem->regexCtxt = NULL;
24037 }
24038 if (ielem->nsBindings != NULL) {
24039 xmlFree((xmlChar **)ielem->nsBindings);
24040 ielem->nsBindings = NULL;
24041 ielem->nbNsBindings = 0;
24042 ielem->sizeNsBindings = 0;
24043 }
24044 }
24045
24046 /**
24047 * xmlSchemaGetFreshElemInfo:
24048 * @vctxt: the schema validation context
24049 *
24050 * Creates/reuses and initializes the element info item for
24051 * the current tree depth.
24052 *
24053 * Returns the element info item or NULL on API or internal errors.
24054 */
24055 static xmlSchemaNodeInfoPtr
xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)24056 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24057 {
24058 xmlSchemaNodeInfoPtr info = NULL;
24059
24060 if (vctxt->depth > vctxt->sizeElemInfos) {
24061 VERROR_INT("xmlSchemaGetFreshElemInfo",
24062 "inconsistent depth encountered");
24063 return (NULL);
24064 }
24065 if (vctxt->elemInfos == NULL) {
24066 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24067 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24068 if (vctxt->elemInfos == NULL) {
24069 xmlSchemaVErrMemory(vctxt);
24070 return (NULL);
24071 }
24072 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24073 vctxt->sizeElemInfos = 10;
24074 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24075 int i = vctxt->sizeElemInfos;
24076
24077 vctxt->sizeElemInfos *= 2;
24078 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24079 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24080 sizeof(xmlSchemaNodeInfoPtr));
24081 if (vctxt->elemInfos == NULL) {
24082 xmlSchemaVErrMemory(vctxt);
24083 return (NULL);
24084 }
24085 /*
24086 * We need the new memory to be NULLed.
24087 * TODO: Use memset instead?
24088 */
24089 for (; i < vctxt->sizeElemInfos; i++)
24090 vctxt->elemInfos[i] = NULL;
24091 } else
24092 info = vctxt->elemInfos[vctxt->depth];
24093
24094 if (info == NULL) {
24095 info = (xmlSchemaNodeInfoPtr)
24096 xmlMalloc(sizeof(xmlSchemaNodeInfo));
24097 if (info == NULL) {
24098 xmlSchemaVErrMemory(vctxt);
24099 return (NULL);
24100 }
24101 vctxt->elemInfos[vctxt->depth] = info;
24102 } else {
24103 if (info->localName != NULL) {
24104 VERROR_INT("xmlSchemaGetFreshElemInfo",
24105 "elem info has not been cleared");
24106 return (NULL);
24107 }
24108 }
24109 memset(info, 0, sizeof(xmlSchemaNodeInfo));
24110 info->nodeType = XML_ELEMENT_NODE;
24111 info->depth = vctxt->depth;
24112
24113 return (info);
24114 }
24115
24116 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24117 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24118 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24119
24120 static int
xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long length,int fireErrors)24121 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24122 xmlNodePtr node,
24123 xmlSchemaTypePtr type,
24124 xmlSchemaValType valType,
24125 const xmlChar * value,
24126 xmlSchemaValPtr val,
24127 unsigned long length,
24128 int fireErrors)
24129 {
24130 int ret, error = 0, found;
24131
24132 xmlSchemaTypePtr tmpType;
24133 xmlSchemaFacetLinkPtr facetLink;
24134 xmlSchemaFacetPtr facet;
24135 unsigned long len = 0;
24136 xmlSchemaWhitespaceValueType ws;
24137
24138 /*
24139 * In Libxml2, derived built-in types have currently no explicit facets.
24140 */
24141 if (type->type == XML_SCHEMA_TYPE_BASIC)
24142 return (0);
24143
24144 /*
24145 * NOTE: Do not jump away, if the facetSet of the given type is
24146 * empty: until now, "pattern" and "enumeration" facets of the
24147 * *base types* need to be checked as well.
24148 */
24149 if (type->facetSet == NULL)
24150 goto pattern_and_enum;
24151
24152 if (! WXS_IS_ATOMIC(type)) {
24153 if (WXS_IS_LIST(type))
24154 goto WXS_IS_LIST;
24155 else
24156 goto pattern_and_enum;
24157 }
24158
24159 /*
24160 * Whitespace handling is only of importance for string-based
24161 * types.
24162 */
24163 tmpType = xmlSchemaGetPrimitiveType(type);
24164 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24165 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24166 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24167 } else
24168 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24169
24170 /*
24171 * If the value was not computed (for string or
24172 * anySimpleType based types), then use the provided
24173 * type.
24174 */
24175 if (val != NULL)
24176 valType = xmlSchemaGetValType(val);
24177
24178 ret = 0;
24179 for (facetLink = type->facetSet; facetLink != NULL;
24180 facetLink = facetLink->next) {
24181 /*
24182 * Skip the pattern "whiteSpace": it is used to
24183 * format the character content beforehand.
24184 */
24185 switch (facetLink->facet->type) {
24186 case XML_SCHEMA_FACET_WHITESPACE:
24187 case XML_SCHEMA_FACET_PATTERN:
24188 case XML_SCHEMA_FACET_ENUMERATION:
24189 continue;
24190 case XML_SCHEMA_FACET_LENGTH:
24191 case XML_SCHEMA_FACET_MINLENGTH:
24192 case XML_SCHEMA_FACET_MAXLENGTH:
24193 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24194 valType, value, val, &len, ws);
24195 break;
24196 default:
24197 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24198 valType, value, val, ws);
24199 break;
24200 }
24201 if (ret < 0) {
24202 AERROR_INT("xmlSchemaValidateFacets",
24203 "validating against a atomic type facet");
24204 return (-1);
24205 } else if (ret > 0) {
24206 if (fireErrors)
24207 xmlSchemaFacetErr(actxt, ret, node,
24208 value, len, type, facetLink->facet, NULL, NULL, NULL);
24209 else
24210 return (ret);
24211 if (error == 0)
24212 error = ret;
24213 }
24214 ret = 0;
24215 }
24216
24217 WXS_IS_LIST:
24218 if (! WXS_IS_LIST(type))
24219 goto pattern_and_enum;
24220 /*
24221 * "length", "minLength" and "maxLength" of list types.
24222 */
24223 ret = 0;
24224 for (facetLink = type->facetSet; facetLink != NULL;
24225 facetLink = facetLink->next) {
24226
24227 switch (facetLink->facet->type) {
24228 case XML_SCHEMA_FACET_LENGTH:
24229 case XML_SCHEMA_FACET_MINLENGTH:
24230 case XML_SCHEMA_FACET_MAXLENGTH:
24231 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24232 value, length, NULL);
24233 break;
24234 default:
24235 continue;
24236 }
24237 if (ret < 0) {
24238 AERROR_INT("xmlSchemaValidateFacets",
24239 "validating against a list type facet");
24240 return (-1);
24241 } else if (ret > 0) {
24242 if (fireErrors)
24243 xmlSchemaFacetErr(actxt, ret, node,
24244 value, length, type, facetLink->facet, NULL, NULL, NULL);
24245 else
24246 return (ret);
24247 if (error == 0)
24248 error = ret;
24249 }
24250 ret = 0;
24251 }
24252
24253 pattern_and_enum:
24254 found = 0;
24255 /*
24256 * Process enumerations. Facet values are in the value space
24257 * of the defining type's base type. This seems to be a bug in the
24258 * XML Schema 1.0 spec. Use the whitespace type of the base type.
24259 * Only the first set of enumerations in the ancestor-or-self axis
24260 * is used for validation.
24261 */
24262 ret = 0;
24263 tmpType = type;
24264 do {
24265 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24266 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24267 continue;
24268 found = 1;
24269 ret = xmlSchemaAreValuesEqual(facet->val, val);
24270 if (ret == 1)
24271 break;
24272 else if (ret < 0) {
24273 AERROR_INT("xmlSchemaValidateFacets",
24274 "validating against an enumeration facet");
24275 return (-1);
24276 }
24277 }
24278 if (ret != 0)
24279 break;
24280 /*
24281 * Break on the first set of enumerations. Any additional
24282 * enumerations which might be existent on the ancestors
24283 * of the current type are restricted by this set; thus
24284 * *must* *not* be taken into account.
24285 */
24286 if (found)
24287 break;
24288 tmpType = tmpType->baseType;
24289 } while ((tmpType != NULL) &&
24290 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24291 if (found && (ret == 0)) {
24292 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24293 if (fireErrors) {
24294 xmlSchemaFacetErr(actxt, ret, node,
24295 value, 0, type, NULL, NULL, NULL, NULL);
24296 } else
24297 return (ret);
24298 if (error == 0)
24299 error = ret;
24300 }
24301
24302 /*
24303 * Process patters. Pattern facets are ORed at type level
24304 * and ANDed if derived. Walk the base type axis.
24305 */
24306 tmpType = type;
24307 facet = NULL;
24308 do {
24309 found = 0;
24310 for (facetLink = tmpType->facetSet; facetLink != NULL;
24311 facetLink = facetLink->next) {
24312 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24313 continue;
24314 found = 1;
24315 /*
24316 * NOTE that for patterns, @value needs to be the
24317 * normalized value.
24318 */
24319 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24320 if (ret == 1)
24321 break;
24322 else if (ret < 0) {
24323 AERROR_INT("xmlSchemaValidateFacets",
24324 "validating against a pattern facet");
24325 return (-1);
24326 } else {
24327 /*
24328 * Save the last non-validating facet.
24329 */
24330 facet = facetLink->facet;
24331 }
24332 }
24333 if (found && (ret != 1)) {
24334 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24335 if (fireErrors) {
24336 xmlSchemaFacetErr(actxt, ret, node,
24337 value, 0, type, facet, NULL, NULL, NULL);
24338 } else
24339 return (ret);
24340 if (error == 0)
24341 error = ret;
24342 break;
24343 }
24344 tmpType = tmpType->baseType;
24345 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24346
24347 return (error);
24348 }
24349
24350 static xmlChar *
xmlSchemaNormalizeValue(xmlSchemaTypePtr type,const xmlChar * value)24351 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24352 const xmlChar *value)
24353 {
24354 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24355 case XML_SCHEMA_WHITESPACE_COLLAPSE:
24356 return (xmlSchemaCollapseString(value));
24357 case XML_SCHEMA_WHITESPACE_REPLACE:
24358 return (xmlSchemaWhiteSpaceReplace(value));
24359 default:
24360 return (NULL);
24361 }
24362 }
24363
24364 static int
xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)24365 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24366 const xmlChar *value,
24367 xmlSchemaValPtr *val,
24368 int valNeeded)
24369 {
24370 int ret;
24371 xmlChar *stripped;
24372 const xmlChar *nsName;
24373 xmlChar *local, *prefix = NULL;
24374
24375 ret = xmlValidateQName(value, 1);
24376 if (ret != 0) {
24377 if (ret == -1) {
24378 VERROR_INT("xmlSchemaValidateQName",
24379 "calling xmlValidateQName()");
24380 return (-1);
24381 }
24382 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24383 }
24384 /*
24385 * NOTE: xmlSplitQName2 will always return a duplicated
24386 * strings.
24387 */
24388 /* TODO: Export and use xmlSchemaStrip instead */
24389 stripped = xmlSchemaCollapseString(value);
24390 local = xmlSplitQName2(stripped ? stripped : value, &prefix);
24391 xmlFree(stripped);
24392 if (local == NULL)
24393 local = xmlStrdup(value);
24394 /*
24395 * OPTIMIZE TODO: Use flags for:
24396 * - is there any namespace binding?
24397 * - is there a default namespace?
24398 */
24399 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24400
24401 if (prefix != NULL) {
24402 xmlFree(prefix);
24403 /*
24404 * A namespace must be found if the prefix is
24405 * NOT NULL.
24406 */
24407 if (nsName == NULL) {
24408 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24409 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24410 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24411 "The QName value '%s' has no "
24412 "corresponding namespace declaration in "
24413 "scope", value, NULL);
24414 if (local != NULL)
24415 xmlFree(local);
24416 return (ret);
24417 }
24418 }
24419 if (valNeeded && val) {
24420 if (nsName != NULL)
24421 *val = xmlSchemaNewQNameValue(
24422 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24423 else
24424 *val = xmlSchemaNewQNameValue(NULL,
24425 BAD_CAST local);
24426 } else
24427 xmlFree(local);
24428 return (0);
24429 }
24430
24431 /*
24432 * cvc-simple-type
24433 */
24434 static int
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * retVal,int fireErrors,int normalize,int isNormalized)24435 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24436 xmlNodePtr node,
24437 xmlSchemaTypePtr type,
24438 const xmlChar *value,
24439 xmlSchemaValPtr *retVal,
24440 int fireErrors,
24441 int normalize,
24442 int isNormalized)
24443 {
24444 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24445 xmlSchemaValPtr val = NULL;
24446 /* xmlSchemaWhitespaceValueType ws; */
24447 xmlChar *normValue = NULL;
24448
24449 #define NORMALIZE(atype) \
24450 if ((! isNormalized) && \
24451 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24452 normValue = xmlSchemaNormalizeValue(atype, value); \
24453 if (normValue != NULL) \
24454 value = normValue; \
24455 isNormalized = 1; \
24456 }
24457
24458 if ((retVal != NULL) && (*retVal != NULL)) {
24459 xmlSchemaFreeValue(*retVal);
24460 *retVal = NULL;
24461 }
24462 /*
24463 * 3.14.4 Simple Type Definition Validation Rules
24464 * Validation Rule: String Valid
24465 */
24466 /*
24467 * 1 It is schema-valid with respect to that definition as defined
24468 * by Datatype Valid in [XML Schemas: Datatypes].
24469 */
24470 /*
24471 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24472 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24473 * the string must be a `declared entity name`.
24474 */
24475 /*
24476 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24477 * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24478 * then every whitespace-delimited substring of the string must be a `declared
24479 * entity name`.
24480 */
24481 /*
24482 * 2.3 otherwise no further condition applies.
24483 */
24484 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24485 valNeeded = 1;
24486 if (value == NULL)
24487 value = BAD_CAST "";
24488 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24489 xmlSchemaTypePtr biType; /* The built-in type. */
24490 /*
24491 * SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24492 * a literal in the `lexical space` of {base type definition}"
24493 */
24494 /*
24495 * Whitespace-normalize.
24496 */
24497 NORMALIZE(type);
24498 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24499 /*
24500 * Get the built-in type.
24501 */
24502 biType = type->baseType;
24503 while ((biType != NULL) &&
24504 (biType->type != XML_SCHEMA_TYPE_BASIC))
24505 biType = biType->baseType;
24506
24507 if (biType == NULL) {
24508 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24509 "could not get the built-in type");
24510 goto internal_error;
24511 }
24512 } else
24513 biType = type;
24514 /*
24515 * NOTATIONs need to be processed here, since they need
24516 * to lookup in the hashtable of NOTATION declarations of the schema.
24517 */
24518 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24519 switch (biType->builtInType) {
24520 case XML_SCHEMAS_NOTATION:
24521 ret = xmlSchemaValidateNotation(
24522 (xmlSchemaValidCtxtPtr) actxt,
24523 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24524 NULL, value, &val, valNeeded);
24525 break;
24526 case XML_SCHEMAS_QNAME:
24527 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24528 value, &val, valNeeded);
24529 break;
24530 default:
24531 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24532 if (valNeeded)
24533 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24534 value, &val, node);
24535 else
24536 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24537 value, NULL, node);
24538 break;
24539 }
24540 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24541 switch (biType->builtInType) {
24542 case XML_SCHEMAS_NOTATION:
24543 ret = xmlSchemaValidateNotation(NULL,
24544 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24545 value, &val, valNeeded);
24546 break;
24547 default:
24548 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24549 if (valNeeded)
24550 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24551 value, &val, node);
24552 else
24553 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24554 value, NULL, node);
24555 break;
24556 }
24557 } else {
24558 /*
24559 * Validation via a public API is not implemented yet.
24560 */
24561 goto internal_error;
24562 }
24563 if (ret != 0) {
24564 if (ret < 0) {
24565 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24566 "validating against a built-in type");
24567 goto internal_error;
24568 }
24569 if (WXS_IS_LIST(type))
24570 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24571 else
24572 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24573 }
24574 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24575 /*
24576 * Check facets.
24577 */
24578 ret = xmlSchemaValidateFacets(actxt, node, type,
24579 (xmlSchemaValType) biType->builtInType, value, val,
24580 0, fireErrors);
24581 if (ret != 0) {
24582 if (ret < 0) {
24583 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24584 "validating facets of atomic simple type");
24585 goto internal_error;
24586 }
24587 if (WXS_IS_LIST(type))
24588 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24589 else
24590 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24591 }
24592 }
24593 else if (fireErrors && (ret > 0))
24594 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24595 } else if (WXS_IS_LIST(type)) {
24596
24597 xmlSchemaTypePtr itemType;
24598 const xmlChar *cur, *end;
24599 xmlChar *tmpValue = NULL;
24600 unsigned long len = 0;
24601 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24602 /* 1.2.2 if {variety} is `list` then the string must be a sequence
24603 * of white space separated tokens, each of which `match`es a literal
24604 * in the `lexical space` of {item type definition}
24605 */
24606 /*
24607 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24608 * the list type has an enum or pattern facet.
24609 */
24610 NORMALIZE(type);
24611 /*
24612 * VAL TODO: Optimize validation of empty values.
24613 * VAL TODO: We do not have computed values for lists.
24614 */
24615 itemType = WXS_LIST_ITEMTYPE(type);
24616 cur = value;
24617 do {
24618 while (IS_BLANK_CH(*cur))
24619 cur++;
24620 end = cur;
24621 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24622 end++;
24623 if (end == cur)
24624 break;
24625 tmpValue = xmlStrndup(cur, end - cur);
24626 len++;
24627
24628 if (valNeeded)
24629 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24630 tmpValue, &curVal, fireErrors, 0, 1);
24631 else
24632 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24633 tmpValue, NULL, fireErrors, 0, 1);
24634 FREE_AND_NULL(tmpValue);
24635 if (curVal != NULL) {
24636 /*
24637 * Add to list of computed values.
24638 */
24639 if (val == NULL)
24640 val = curVal;
24641 else
24642 xmlSchemaValueAppend(prevVal, curVal);
24643 prevVal = curVal;
24644 curVal = NULL;
24645 }
24646 if (ret != 0) {
24647 if (ret < 0) {
24648 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24649 "validating an item of list simple type");
24650 goto internal_error;
24651 }
24652 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24653 break;
24654 }
24655 cur = end;
24656 } while (*cur != 0);
24657 FREE_AND_NULL(tmpValue);
24658 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24659 /*
24660 * Apply facets (pattern, enumeration).
24661 */
24662 ret = xmlSchemaValidateFacets(actxt, node, type,
24663 XML_SCHEMAS_UNKNOWN, value, val,
24664 len, fireErrors);
24665 if (ret != 0) {
24666 if (ret < 0) {
24667 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24668 "validating facets of list simple type");
24669 goto internal_error;
24670 }
24671 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24672 }
24673 }
24674 if (fireErrors && (ret > 0)) {
24675 /*
24676 * Report the normalized value.
24677 */
24678 normalize = 1;
24679 NORMALIZE(type);
24680 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24681 }
24682 } else if (WXS_IS_UNION(type)) {
24683 xmlSchemaTypeLinkPtr memberLink;
24684 /*
24685 * TODO: For all datatypes `derived` by `union` whiteSpace does
24686 * not apply directly; however, the normalization behavior of `union`
24687 * types is controlled by the value of whiteSpace on that one of the
24688 * `memberTypes` against which the `union` is successfully validated.
24689 *
24690 * This means that the value is normalized by the first validating
24691 * member type, then the facets of the union type are applied. This
24692 * needs changing of the value!
24693 */
24694
24695 /*
24696 * 1.2.3 if {variety} is `union` then the string must `match` a
24697 * literal in the `lexical space` of at least one member of
24698 * {member type definitions}
24699 */
24700 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24701 if (memberLink == NULL) {
24702 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24703 "union simple type has no member types");
24704 goto internal_error;
24705 }
24706 /*
24707 * Always normalize union type values, since we currently
24708 * cannot store the whitespace information with the value
24709 * itself; otherwise a later value-comparison would be
24710 * not possible.
24711 */
24712 while (memberLink != NULL) {
24713 if (valNeeded)
24714 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24715 memberLink->type, value, &val, 0, 1, 0);
24716 else
24717 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24718 memberLink->type, value, NULL, 0, 1, 0);
24719 if (ret <= 0)
24720 break;
24721 memberLink = memberLink->next;
24722 }
24723 if (ret != 0) {
24724 if (ret < 0) {
24725 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24726 "validating members of union simple type");
24727 goto internal_error;
24728 }
24729 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24730 }
24731 /*
24732 * Apply facets (pattern, enumeration).
24733 */
24734 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24735 /*
24736 * The normalization behavior of `union` types is controlled by
24737 * the value of whiteSpace on that one of the `memberTypes`
24738 * against which the `union` is successfully validated.
24739 */
24740 NORMALIZE(memberLink->type);
24741 ret = xmlSchemaValidateFacets(actxt, node, type,
24742 XML_SCHEMAS_UNKNOWN, value, val,
24743 0, fireErrors);
24744 if (ret != 0) {
24745 if (ret < 0) {
24746 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24747 "validating facets of union simple type");
24748 goto internal_error;
24749 }
24750 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24751 }
24752 }
24753 if (fireErrors && (ret > 0))
24754 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24755 }
24756
24757 if (normValue != NULL)
24758 xmlFree(normValue);
24759 if (ret == 0) {
24760 if (retVal != NULL)
24761 *retVal = val;
24762 else if (val != NULL)
24763 xmlSchemaFreeValue(val);
24764 } else if (val != NULL)
24765 xmlSchemaFreeValue(val);
24766 return (ret);
24767 internal_error:
24768 if (normValue != NULL)
24769 xmlFree(normValue);
24770 if (val != NULL)
24771 xmlSchemaFreeValue(val);
24772 return (-1);
24773 }
24774
24775 static int
xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,const xmlChar ** nsName,const xmlChar ** localName)24776 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24777 const xmlChar *value,
24778 const xmlChar **nsName,
24779 const xmlChar **localName)
24780 {
24781 int ret = 0;
24782
24783 if ((nsName == NULL) || (localName == NULL))
24784 return (-1);
24785 *nsName = NULL;
24786 *localName = NULL;
24787
24788 ret = xmlValidateQName(value, 1);
24789 if (ret == -1)
24790 return (-1);
24791 if (ret > 0) {
24792 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24793 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24794 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24795 return (1);
24796 }
24797 {
24798 xmlChar *local = NULL;
24799 xmlChar *prefix;
24800
24801 /*
24802 * NOTE: xmlSplitQName2 will return a duplicated
24803 * string.
24804 */
24805 local = xmlSplitQName2(value, &prefix);
24806 if (local == NULL)
24807 *localName = xmlDictLookup(vctxt->dict, value, -1);
24808 else {
24809 *localName = xmlDictLookup(vctxt->dict, local, -1);
24810 xmlFree(local);
24811 }
24812
24813 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24814
24815 if (prefix != NULL) {
24816 xmlFree(prefix);
24817 /*
24818 * A namespace must be found if the prefix is NOT NULL.
24819 */
24820 if (*nsName == NULL) {
24821 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24822 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24823 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24824 "The QName value '%s' has no "
24825 "corresponding namespace declaration in scope",
24826 value, NULL);
24827 return (2);
24828 }
24829 }
24830 }
24831 return (0);
24832 }
24833
24834 static int
xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaAttrInfoPtr iattr,xmlSchemaTypePtr * localType,xmlSchemaElementPtr elemDecl)24835 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24836 xmlSchemaAttrInfoPtr iattr,
24837 xmlSchemaTypePtr *localType,
24838 xmlSchemaElementPtr elemDecl)
24839 {
24840 int ret = 0;
24841 /*
24842 * cvc-elt (3.3.4) : (4)
24843 * AND
24844 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24845 * (1.2.1.2.1) - (1.2.1.2.4)
24846 * Handle 'xsi:type'.
24847 */
24848 if (localType == NULL)
24849 return (-1);
24850 *localType = NULL;
24851 if (iattr == NULL)
24852 return (0);
24853 else {
24854 const xmlChar *nsName = NULL, *local = NULL;
24855 /*
24856 * TODO: We should report a *warning* that the type was overridden
24857 * by the instance.
24858 */
24859 ACTIVATE_ATTRIBUTE(iattr);
24860 /*
24861 * (cvc-elt) (3.3.4) : (4.1)
24862 * (cvc-assess-elt) (1.2.1.2.2)
24863 */
24864 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24865 &nsName, &local);
24866 if (ret != 0) {
24867 if (ret < 0) {
24868 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24869 "calling xmlSchemaQNameExpand() to validate the "
24870 "attribute 'xsi:type'");
24871 goto internal_error;
24872 }
24873 goto exit;
24874 }
24875 /*
24876 * (cvc-elt) (3.3.4) : (4.2)
24877 * (cvc-assess-elt) (1.2.1.2.3)
24878 */
24879 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24880 if (*localType == NULL) {
24881 xmlChar *str = NULL;
24882
24883 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24884 XML_SCHEMAV_CVC_ELT_4_2, NULL,
24885 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24886 "The QName value '%s' of the xsi:type attribute does not "
24887 "resolve to a type definition",
24888 xmlSchemaFormatQName(&str, nsName, local), NULL);
24889 FREE_AND_NULL(str);
24890 ret = vctxt->err;
24891 goto exit;
24892 }
24893 if (elemDecl != NULL) {
24894 int set = 0;
24895
24896 /*
24897 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24898 * "The `local type definition` must be validly
24899 * derived from the {type definition} given the union of
24900 * the {disallowed substitutions} and the {type definition}'s
24901 * {prohibited substitutions}, as defined in
24902 * Type Derivation OK (Complex) ($3.4.6)
24903 * (if it is a complex type definition),
24904 * or given {disallowed substitutions} as defined in Type
24905 * Derivation OK (Simple) ($3.14.6) (if it is a simple type
24906 * definition)."
24907 *
24908 * {disallowed substitutions}: the "block" on the element decl.
24909 * {prohibited substitutions}: the "block" on the type def.
24910 */
24911 /*
24912 * OPTIMIZE TODO: We could map types already evaluated
24913 * to be validly derived from other types to avoid checking
24914 * this over and over for the same types.
24915 */
24916 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24917 (elemDecl->subtypes->flags &
24918 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24919 set |= SUBSET_EXTENSION;
24920
24921 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24922 (elemDecl->subtypes->flags &
24923 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24924 set |= SUBSET_RESTRICTION;
24925
24926 /*
24927 * REMOVED and CHANGED since this produced a parser context
24928 * which adds to the string dict of the schema. So this would
24929 * change the schema and we don't want this. We don't need
24930 * the parser context anymore.
24931 *
24932 * if ((vctxt->pctxt == NULL) &&
24933 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24934 * return (-1);
24935 */
24936
24937 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24938 elemDecl->subtypes, set) != 0) {
24939 xmlChar *str = NULL;
24940
24941 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24942 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24943 "The type definition '%s', specified by xsi:type, is "
24944 "blocked or not validly derived from the type definition "
24945 "of the element declaration",
24946 xmlSchemaFormatQName(&str,
24947 (*localType)->targetNamespace,
24948 (*localType)->name),
24949 NULL);
24950 FREE_AND_NULL(str);
24951 ret = vctxt->err;
24952 *localType = NULL;
24953 }
24954 }
24955 }
24956 exit:
24957 ACTIVATE_ELEM;
24958 return (ret);
24959 internal_error:
24960 ACTIVATE_ELEM;
24961 return (-1);
24962 }
24963
24964 static int
xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)24965 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24966 {
24967 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24968 xmlSchemaTypePtr actualType;
24969
24970 /*
24971 * cvc-elt (3.3.4) : 1
24972 */
24973 if (elemDecl == NULL) {
24974 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24975 "No matching declaration available");
24976 return (vctxt->err);
24977 }
24978 actualType = WXS_ELEM_TYPEDEF(elemDecl);
24979 /*
24980 * cvc-elt (3.3.4) : 2
24981 */
24982 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24983 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24984 "The element declaration is abstract");
24985 return (vctxt->err);
24986 }
24987 if (actualType == NULL) {
24988 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24989 "The type definition is absent");
24990 return (XML_SCHEMAV_CVC_TYPE_1);
24991 }
24992 if (vctxt->nbAttrInfos != 0) {
24993 int ret;
24994 xmlSchemaAttrInfoPtr iattr;
24995 /*
24996 * cvc-elt (3.3.4) : 3
24997 * Handle 'xsi:nil'.
24998 */
24999 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25000 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25001 if (iattr) {
25002 ACTIVATE_ATTRIBUTE(iattr);
25003 /*
25004 * Validate the value.
25005 */
25006 ret = xmlSchemaVCheckCVCSimpleType(
25007 ACTXT_CAST vctxt, NULL,
25008 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25009 iattr->value, &(iattr->val), 1, 0, 0);
25010 ACTIVATE_ELEM;
25011 if (ret < 0) {
25012 VERROR_INT("xmlSchemaValidateElemDecl",
25013 "calling xmlSchemaVCheckCVCSimpleType() to "
25014 "validate the attribute 'xsi:nil'");
25015 return (-1);
25016 }
25017 if (ret == 0) {
25018 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25019 /*
25020 * cvc-elt (3.3.4) : 3.1
25021 */
25022 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25023 "The element is not 'nillable'");
25024 /* Does not return an error on purpose. */
25025 } else {
25026 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25027 /*
25028 * cvc-elt (3.3.4) : 3.2.2
25029 */
25030 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25031 (elemDecl->value != NULL)) {
25032 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25033 "The element cannot be 'nilled' because "
25034 "there is a fixed value constraint defined "
25035 "for it");
25036 /* Does not return an error on purpose. */
25037 } else
25038 vctxt->inode->flags |=
25039 XML_SCHEMA_ELEM_INFO_NILLED;
25040 }
25041 }
25042 }
25043 }
25044 /*
25045 * cvc-elt (3.3.4) : 4
25046 * Handle 'xsi:type'.
25047 */
25048 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25049 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25050 if (iattr) {
25051 xmlSchemaTypePtr localType = NULL;
25052
25053 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25054 elemDecl);
25055 if (ret != 0) {
25056 if (ret == -1) {
25057 VERROR_INT("xmlSchemaValidateElemDecl",
25058 "calling xmlSchemaProcessXSIType() to "
25059 "process the attribute 'xsi:type'");
25060 return (-1);
25061 }
25062 /* Does not return an error on purpose. */
25063 }
25064 if (localType != NULL) {
25065 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25066 actualType = localType;
25067 }
25068 }
25069 }
25070 /*
25071 * IDC: Register identity-constraint XPath matchers.
25072 */
25073 if ((elemDecl->idcs != NULL) &&
25074 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25075 return (-1);
25076 /*
25077 * No actual type definition.
25078 */
25079 if (actualType == NULL) {
25080 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25081 "The type definition is absent");
25082 return (XML_SCHEMAV_CVC_TYPE_1);
25083 }
25084 /*
25085 * Remember the actual type definition.
25086 */
25087 vctxt->inode->typeDef = actualType;
25088
25089 return (0);
25090 }
25091
25092 static int
xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)25093 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25094 {
25095 xmlSchemaAttrInfoPtr iattr;
25096 int ret = 0, i;
25097
25098 /*
25099 * SPEC cvc-type (3.1.1)
25100 * "The attributes of must be empty, excepting those whose namespace
25101 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25102 * whose local name is one of type, nil, schemaLocation or
25103 * noNamespaceSchemaLocation."
25104 */
25105 if (vctxt->nbAttrInfos == 0)
25106 return (0);
25107 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25108 iattr = vctxt->attrInfos[i];
25109 if (! iattr->metaType) {
25110 ACTIVATE_ATTRIBUTE(iattr)
25111 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25112 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25113 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25114 }
25115 }
25116 ACTIVATE_ELEM
25117 return (ret);
25118 }
25119
25120 /*
25121 * Cleanup currently used attribute infos.
25122 */
25123 static void
xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)25124 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25125 {
25126 int i;
25127 xmlSchemaAttrInfoPtr attr;
25128
25129 if (vctxt->nbAttrInfos == 0)
25130 return;
25131 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25132 attr = vctxt->attrInfos[i];
25133 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25134 if (attr->localName != NULL)
25135 xmlFree((xmlChar *) attr->localName);
25136 if (attr->nsName != NULL)
25137 xmlFree((xmlChar *) attr->nsName);
25138 }
25139 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25140 if (attr->value != NULL)
25141 xmlFree((xmlChar *) attr->value);
25142 }
25143 if (attr->val != NULL) {
25144 xmlSchemaFreeValue(attr->val);
25145 attr->val = NULL;
25146 }
25147 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25148 }
25149 vctxt->nbAttrInfos = 0;
25150 }
25151
25152 /*
25153 * 3.4.4 Complex Type Definition Validation Rules
25154 * Element Locally Valid (Complex Type) (cvc-complex-type)
25155 * 3.2.4 Attribute Declaration Validation Rules
25156 * Validation Rule: Attribute Locally Valid (cvc-attribute)
25157 * Attribute Locally Valid (Use) (cvc-au)
25158 *
25159 * Only "assessed" attribute information items will be visible to
25160 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25161 */
25162 static int
xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)25163 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25164 {
25165 xmlSchemaTypePtr type = vctxt->inode->typeDef;
25166 xmlSchemaItemListPtr attrUseList;
25167 xmlSchemaAttributeUsePtr attrUse = NULL;
25168 xmlSchemaAttributePtr attrDecl = NULL;
25169 xmlSchemaAttrInfoPtr iattr, tmpiattr;
25170 int i, j, found, nbAttrs, nbUses;
25171 int xpathRes = 0, res, wildIDs = 0, fixed;
25172 xmlNodePtr defAttrOwnerElem = NULL;
25173
25174 /*
25175 * SPEC (cvc-attribute)
25176 * (1) "The declaration must not be `absent` (see Missing
25177 * Sub-components ($5.3) for how this can fail to be
25178 * the case)."
25179 * (2) "Its {type definition} must not be absent."
25180 *
25181 * NOTE (1) + (2): This is not handled here, since we currently do not
25182 * allow validation against schemas which have missing sub-components.
25183 *
25184 * SPEC (cvc-complex-type)
25185 * (3) "For each attribute information item in the element information
25186 * item's [attributes] excepting those whose [namespace name] is
25187 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25188 * [local name] is one of type, nil, schemaLocation or
25189 * noNamespaceSchemaLocation, the appropriate case among the following
25190 * must be true:
25191 *
25192 */
25193 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25194 /*
25195 * @nbAttrs is the number of attributes present in the instance.
25196 */
25197 nbAttrs = vctxt->nbAttrInfos;
25198 if (attrUseList != NULL)
25199 nbUses = attrUseList->nbItems;
25200 else
25201 nbUses = 0;
25202 for (i = 0; i < nbUses; i++) {
25203 found = 0;
25204 attrUse = attrUseList->items[i];
25205 attrDecl = WXS_ATTRUSE_DECL(attrUse);
25206 for (j = 0; j < nbAttrs; j++) {
25207 iattr = vctxt->attrInfos[j];
25208 /*
25209 * SPEC (cvc-complex-type) (3)
25210 * Skip meta attributes.
25211 */
25212 if (iattr->metaType)
25213 continue;
25214 if (iattr->localName[0] != attrDecl->name[0])
25215 continue;
25216 if (!xmlStrEqual(iattr->localName, attrDecl->name))
25217 continue;
25218 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25219 continue;
25220 found = 1;
25221 /*
25222 * SPEC (cvc-complex-type)
25223 * (3.1) "If there is among the {attribute uses} an attribute
25224 * use with an {attribute declaration} whose {name} matches
25225 * the attribute information item's [local name] and whose
25226 * {target namespace} is identical to the attribute information
25227 * item's [namespace name] (where an `absent` {target namespace}
25228 * is taken to be identical to a [namespace name] with no value),
25229 * then the attribute information must be `valid` with respect
25230 * to that attribute use as per Attribute Locally Valid (Use)
25231 * ($3.5.4). In this case the {attribute declaration} of that
25232 * attribute use is the `context-determined declaration` for the
25233 * attribute information item with respect to Schema-Validity
25234 * Assessment (Attribute) ($3.2.4) and
25235 * Assessment Outcome (Attribute) ($3.2.5).
25236 */
25237 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25238 iattr->use = attrUse;
25239 /*
25240 * Context-determined declaration.
25241 */
25242 iattr->decl = attrDecl;
25243 iattr->typeDef = attrDecl->subtypes;
25244 break;
25245 }
25246
25247 if (found)
25248 continue;
25249
25250 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25251 /*
25252 * Handle non-existent, required attributes.
25253 *
25254 * SPEC (cvc-complex-type)
25255 * (4) "The {attribute declaration} of each attribute use in
25256 * the {attribute uses} whose {required} is true matches one
25257 * of the attribute information items in the element information
25258 * item's [attributes] as per clause 3.1 above."
25259 */
25260 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25261 if (tmpiattr == NULL) {
25262 VERROR_INT(
25263 "xmlSchemaVAttributesComplex",
25264 "calling xmlSchemaGetFreshAttrInfo()");
25265 return (-1);
25266 }
25267 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25268 tmpiattr->use = attrUse;
25269 tmpiattr->decl = attrDecl;
25270 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25271 ((attrUse->defValue != NULL) ||
25272 (attrDecl->defValue != NULL))) {
25273 /*
25274 * Handle non-existent, optional, default/fixed attributes.
25275 */
25276 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25277 if (tmpiattr == NULL) {
25278 VERROR_INT(
25279 "xmlSchemaVAttributesComplex",
25280 "calling xmlSchemaGetFreshAttrInfo()");
25281 return (-1);
25282 }
25283 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25284 tmpiattr->use = attrUse;
25285 tmpiattr->decl = attrDecl;
25286 tmpiattr->typeDef = attrDecl->subtypes;
25287 tmpiattr->localName = attrDecl->name;
25288 tmpiattr->nsName = attrDecl->targetNamespace;
25289 }
25290 }
25291
25292 if (vctxt->nbAttrInfos == 0)
25293 return (0);
25294 /*
25295 * Validate against the wildcard.
25296 */
25297 if (type->attributeWildcard != NULL) {
25298 /*
25299 * SPEC (cvc-complex-type)
25300 * (3.2.1) "There must be an {attribute wildcard}."
25301 */
25302 for (i = 0; i < nbAttrs; i++) {
25303 iattr = vctxt->attrInfos[i];
25304 /*
25305 * SPEC (cvc-complex-type) (3)
25306 * Skip meta attributes.
25307 */
25308 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25309 continue;
25310 /*
25311 * SPEC (cvc-complex-type)
25312 * (3.2.2) "The attribute information item must be `valid` with
25313 * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25314 *
25315 * SPEC Item Valid (Wildcard) (cvc-wildcard)
25316 * "... its [namespace name] must be `valid` with respect to
25317 * the wildcard constraint, as defined in Wildcard allows
25318 * Namespace Name ($3.10.4)."
25319 */
25320 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25321 iattr->nsName) == 0) {
25322 /*
25323 * Handle processContents.
25324 *
25325 * SPEC (cvc-wildcard):
25326 * processContents | context-determined declaration:
25327 * "strict" "mustFind"
25328 * "lax" "none"
25329 * "skip" "skip"
25330 */
25331 if (type->attributeWildcard->processContents ==
25332 XML_SCHEMAS_ANY_SKIP) {
25333 /*
25334 * context-determined declaration = "skip"
25335 *
25336 * SPEC PSVI Assessment Outcome (Attribute)
25337 * [validity] = "notKnown"
25338 * [validation attempted] = "none"
25339 */
25340 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25341 continue;
25342 }
25343 /*
25344 * Find an attribute declaration.
25345 */
25346 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25347 iattr->localName, iattr->nsName);
25348 if (iattr->decl != NULL) {
25349 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25350 /*
25351 * SPEC (cvc-complex-type)
25352 * (5) "Let [Definition:] the wild IDs be the set of
25353 * all attribute information item to which clause 3.2
25354 * applied and whose `validation` resulted in a
25355 * `context-determined declaration` of mustFind or no
25356 * `context-determined declaration` at all, and whose
25357 * [local name] and [namespace name] resolve (as
25358 * defined by QName resolution (Instance) ($3.15.4)) to
25359 * an attribute declaration whose {type definition} is
25360 * or is derived from ID. Then all of the following
25361 * must be true:"
25362 */
25363 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25364 if (xmlSchemaIsDerivedFromBuiltInType(
25365 iattr->typeDef, XML_SCHEMAS_ID)) {
25366 /*
25367 * SPEC (5.1) "There must be no more than one
25368 * item in `wild IDs`."
25369 */
25370 if (wildIDs != 0) {
25371 /* VAL TODO */
25372 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25373 continue;
25374 }
25375 wildIDs++;
25376 /*
25377 * SPEC (cvc-complex-type)
25378 * (5.2) "If `wild IDs` is non-empty, there must not
25379 * be any attribute uses among the {attribute uses}
25380 * whose {attribute declaration}'s {type definition}
25381 * is or is derived from ID."
25382 */
25383 if (attrUseList != NULL) {
25384 for (j = 0; j < attrUseList->nbItems; j++) {
25385 if (xmlSchemaIsDerivedFromBuiltInType(
25386 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25387 XML_SCHEMAS_ID)) {
25388 /* URGENT VAL TODO: implement */
25389 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25390 break;
25391 }
25392 }
25393 }
25394 }
25395 } else if (type->attributeWildcard->processContents ==
25396 XML_SCHEMAS_ANY_LAX) {
25397 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25398 /*
25399 * SPEC PSVI Assessment Outcome (Attribute)
25400 * [validity] = "notKnown"
25401 * [validation attempted] = "none"
25402 */
25403 } else {
25404 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25405 }
25406 }
25407 }
25408 }
25409
25410 if (vctxt->nbAttrInfos == 0)
25411 return (0);
25412
25413 /*
25414 * Get the owner element; needed for creation of default attributes.
25415 * This fixes bug #341337, reported by David Grohmann.
25416 */
25417 if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25418 xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25419 if (ielem && ielem->node && ielem->node->doc)
25420 defAttrOwnerElem = ielem->node;
25421 }
25422 /*
25423 * Validate values, create default attributes, evaluate IDCs.
25424 */
25425 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25426 iattr = vctxt->attrInfos[i];
25427 /*
25428 * VAL TODO: Note that we won't try to resolve IDCs to
25429 * "lax" and "skip" validated attributes. Check what to
25430 * do in this case.
25431 */
25432 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25433 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25434 continue;
25435 /*
25436 * VAL TODO: What to do if the type definition is missing?
25437 */
25438 if (iattr->typeDef == NULL) {
25439 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25440 continue;
25441 }
25442
25443 ACTIVATE_ATTRIBUTE(iattr);
25444 fixed = 0;
25445 xpathRes = 0;
25446
25447 if (vctxt->xpathStates != NULL) {
25448 /*
25449 * Evaluate IDCs.
25450 */
25451 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25452 XML_ATTRIBUTE_NODE);
25453 if (xpathRes == -1) {
25454 VERROR_INT("xmlSchemaVAttributesComplex",
25455 "calling xmlSchemaXPathEvaluate()");
25456 goto internal_error;
25457 }
25458 }
25459
25460 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25461 /*
25462 * Default/fixed attributes.
25463 * We need the value only if we need to resolve IDCs or
25464 * will create default attributes.
25465 */
25466 if ((xpathRes) || (defAttrOwnerElem)) {
25467 if (iattr->use->defValue != NULL) {
25468 iattr->value = (xmlChar *) iattr->use->defValue;
25469 iattr->val = iattr->use->defVal;
25470 } else {
25471 iattr->value = (xmlChar *) iattr->decl->defValue;
25472 iattr->val = iattr->decl->defVal;
25473 }
25474 /*
25475 * IDCs will consume the precomputed default value,
25476 * so we need to clone it.
25477 */
25478 if (iattr->val == NULL) {
25479 VERROR_INT("xmlSchemaVAttributesComplex",
25480 "default/fixed value on an attribute use was "
25481 "not precomputed");
25482 goto internal_error;
25483 }
25484 iattr->val = xmlSchemaCopyValue(iattr->val);
25485 if (iattr->val == NULL) {
25486 VERROR_INT("xmlSchemaVAttributesComplex",
25487 "calling xmlSchemaCopyValue()");
25488 goto internal_error;
25489 }
25490 }
25491 /*
25492 * PSVI: Add the default attribute to the current element.
25493 * VAL TODO: Should we use the *normalized* value? This currently
25494 * uses the *initial* value.
25495 */
25496
25497 if (defAttrOwnerElem) {
25498 xmlChar *normValue;
25499 const xmlChar *value;
25500
25501 value = iattr->value;
25502 /*
25503 * Normalize the value.
25504 */
25505 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25506 iattr->value);
25507 if (normValue != NULL)
25508 value = BAD_CAST normValue;
25509
25510 if (iattr->nsName == NULL) {
25511 if (xmlNewProp(defAttrOwnerElem,
25512 iattr->localName, value) == NULL) {
25513 VERROR_INT("xmlSchemaVAttributesComplex",
25514 "calling xmlNewProp()");
25515 if (normValue != NULL)
25516 xmlFree(normValue);
25517 goto internal_error;
25518 }
25519 } else {
25520 xmlNsPtr ns;
25521
25522 ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25523 defAttrOwnerElem, iattr->nsName);
25524 if (ns == NULL) {
25525 xmlChar prefix[13];
25526 int counter = 0;
25527
25528 /*
25529 * Create a namespace declaration on the validation
25530 * root node if no namespace declaration is in scope.
25531 */
25532 do {
25533 snprintf((char *) prefix, 13, "p%d", counter++);
25534 ns = xmlSearchNs(defAttrOwnerElem->doc,
25535 defAttrOwnerElem, BAD_CAST prefix);
25536 if (counter > 1000) {
25537 VERROR_INT(
25538 "xmlSchemaVAttributesComplex",
25539 "could not compute a ns prefix for a "
25540 "default/fixed attribute");
25541 if (normValue != NULL)
25542 xmlFree(normValue);
25543 goto internal_error;
25544 }
25545 } while (ns != NULL);
25546 ns = xmlNewNs(vctxt->validationRoot,
25547 iattr->nsName, BAD_CAST prefix);
25548 }
25549 /*
25550 * TODO:
25551 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25552 * If we have QNames: do we need to ensure there's a
25553 * prefix defined for the QName?
25554 */
25555 xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25556 }
25557 if (normValue != NULL)
25558 xmlFree(normValue);
25559 }
25560 /*
25561 * Go directly to IDC evaluation.
25562 */
25563 goto eval_idcs;
25564 }
25565 /*
25566 * Validate the value.
25567 */
25568 if (vctxt->value != NULL) {
25569 /*
25570 * Free last computed value; just for safety reasons.
25571 */
25572 xmlSchemaFreeValue(vctxt->value);
25573 vctxt->value = NULL;
25574 }
25575 /*
25576 * Note that the attribute *use* can be unavailable, if
25577 * the attribute was a wild attribute.
25578 */
25579 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25580 ((iattr->use != NULL) &&
25581 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25582 fixed = 1;
25583 else
25584 fixed = 0;
25585 /*
25586 * SPEC (cvc-attribute)
25587 * (3) "The item's `normalized value` must be locally `valid`
25588 * with respect to that {type definition} as per
25589 * String Valid ($3.14.4)."
25590 *
25591 * VAL TODO: Do we already have the
25592 * "normalized attribute value" here?
25593 */
25594 if (xpathRes || fixed) {
25595 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25596 /*
25597 * Request a computed value.
25598 */
25599 res = xmlSchemaVCheckCVCSimpleType(
25600 ACTXT_CAST vctxt,
25601 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25602 1, 1, 0);
25603 } else {
25604 res = xmlSchemaVCheckCVCSimpleType(
25605 ACTXT_CAST vctxt,
25606 iattr->node, iattr->typeDef, iattr->value, NULL,
25607 1, 0, 0);
25608 }
25609
25610 if (res != 0) {
25611 if (res == -1) {
25612 VERROR_INT("xmlSchemaVAttributesComplex",
25613 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25614 goto internal_error;
25615 }
25616 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25617 /*
25618 * SPEC PSVI Assessment Outcome (Attribute)
25619 * [validity] = "invalid"
25620 */
25621 goto eval_idcs;
25622 }
25623
25624 if (fixed) {
25625 /*
25626 * SPEC Attribute Locally Valid (Use) (cvc-au)
25627 * "For an attribute information item to be `valid`
25628 * with respect to an attribute use its *normalized*
25629 * value must match the *canonical* lexical
25630 * representation of the attribute use's {value
25631 * constraint}value, if it is present and fixed."
25632 *
25633 * VAL TODO: The requirement for the *canonical* value
25634 * will be removed in XML Schema 1.1.
25635 */
25636 /*
25637 * SPEC Attribute Locally Valid (cvc-attribute)
25638 * (4) "The item's *actual* value must match the *value* of
25639 * the {value constraint}, if it is present and fixed."
25640 */
25641 if (iattr->val == NULL) {
25642 /* VAL TODO: A value was not precomputed. */
25643 goto eval_idcs;
25644 }
25645 if ((iattr->use != NULL) &&
25646 (iattr->use->defValue != NULL)) {
25647 if (iattr->use->defVal == NULL) {
25648 /* VAL TODO: A default value was not precomputed. */
25649 goto eval_idcs;
25650 }
25651 iattr->vcValue = iattr->use->defValue;
25652 /*
25653 if (xmlSchemaCompareValuesWhtsp(attr->val,
25654 (xmlSchemaWhitespaceValueType) ws,
25655 attr->use->defVal,
25656 (xmlSchemaWhitespaceValueType) ws) != 0) {
25657 */
25658 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25659 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25660 } else {
25661 if (iattr->decl->defVal == NULL) {
25662 /* VAL TODO: A default value was not precomputed. */
25663 goto eval_idcs;
25664 }
25665 iattr->vcValue = iattr->decl->defValue;
25666 /*
25667 if (xmlSchemaCompareValuesWhtsp(attr->val,
25668 (xmlSchemaWhitespaceValueType) ws,
25669 attrDecl->defVal,
25670 (xmlSchemaWhitespaceValueType) ws) != 0) {
25671 */
25672 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25673 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25674 }
25675 /*
25676 * [validity] = "valid"
25677 */
25678 }
25679 eval_idcs:
25680 /*
25681 * Evaluate IDCs.
25682 */
25683 if (xpathRes) {
25684 if (xmlSchemaXPathProcessHistory(vctxt,
25685 vctxt->depth +1) == -1) {
25686 VERROR_INT("xmlSchemaVAttributesComplex",
25687 "calling xmlSchemaXPathEvaluate()");
25688 goto internal_error;
25689 }
25690 } else if (vctxt->xpathStates != NULL)
25691 xmlSchemaXPathPop(vctxt);
25692 }
25693
25694 /*
25695 * Report errors.
25696 */
25697 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25698 iattr = vctxt->attrInfos[i];
25699 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25700 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25701 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25702 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25703 continue;
25704 ACTIVATE_ATTRIBUTE(iattr);
25705 switch (iattr->state) {
25706 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25707 xmlChar *str = NULL;
25708 ACTIVATE_ELEM;
25709 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25710 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25711 "The attribute '%s' is required but missing",
25712 xmlSchemaFormatQName(&str,
25713 iattr->decl->targetNamespace,
25714 iattr->decl->name),
25715 NULL);
25716 FREE_AND_NULL(str)
25717 break;
25718 }
25719 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25720 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25721 "The type definition is absent");
25722 break;
25723 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25724 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25725 XML_SCHEMAV_CVC_AU, NULL, NULL,
25726 "The value '%s' does not match the fixed "
25727 "value constraint '%s'",
25728 iattr->value, iattr->vcValue);
25729 break;
25730 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25731 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25732 "No matching global attribute declaration available, but "
25733 "demanded by the strict wildcard");
25734 break;
25735 case XML_SCHEMAS_ATTR_UNKNOWN:
25736 if (iattr->metaType)
25737 break;
25738 /*
25739 * MAYBE VAL TODO: One might report different error messages
25740 * for the following errors.
25741 */
25742 if (type->attributeWildcard == NULL) {
25743 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25744 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25745 } else {
25746 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25747 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25748 }
25749 break;
25750 default:
25751 break;
25752 }
25753 }
25754
25755 ACTIVATE_ELEM;
25756 return (0);
25757 internal_error:
25758 ACTIVATE_ELEM;
25759 return (-1);
25760 }
25761
25762 static int
xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,int * skip)25763 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25764 int *skip)
25765 {
25766 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25767 /*
25768 * The namespace of the element was already identified to be
25769 * matching the wildcard.
25770 */
25771 if ((skip == NULL) || (wild == NULL) ||
25772 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25773 VERROR_INT("xmlSchemaValidateElemWildcard",
25774 "bad arguments");
25775 return (-1);
25776 }
25777 *skip = 0;
25778 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25779 /*
25780 * URGENT VAL TODO: Either we need to position the stream to the
25781 * next sibling, or walk the whole subtree.
25782 */
25783 *skip = 1;
25784 return (0);
25785 }
25786 {
25787 xmlSchemaElementPtr decl = NULL;
25788
25789 decl = xmlSchemaGetElem(vctxt->schema,
25790 vctxt->inode->localName, vctxt->inode->nsName);
25791 if (decl != NULL) {
25792 vctxt->inode->decl = decl;
25793 return (0);
25794 }
25795 }
25796 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25797 /* VAL TODO: Change to proper error code. */
25798 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25799 "No matching global element declaration available, but "
25800 "demanded by the strict wildcard");
25801 return (vctxt->err);
25802 }
25803 if (vctxt->nbAttrInfos != 0) {
25804 xmlSchemaAttrInfoPtr iattr;
25805 /*
25806 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25807 * (1.2.1.2.1) - (1.2.1.2.3 )
25808 *
25809 * Use the xsi:type attribute for the type definition.
25810 */
25811 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25812 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25813 if (iattr != NULL) {
25814 if (xmlSchemaProcessXSIType(vctxt, iattr,
25815 &(vctxt->inode->typeDef), NULL) == -1) {
25816 VERROR_INT("xmlSchemaValidateElemWildcard",
25817 "calling xmlSchemaProcessXSIType() to "
25818 "process the attribute 'xsi:nil'");
25819 return (-1);
25820 }
25821 /*
25822 * Don't return an error on purpose.
25823 */
25824 return (0);
25825 }
25826 }
25827 /*
25828 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25829 *
25830 * Fallback to "anyType".
25831 */
25832 vctxt->inode->typeDef =
25833 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25834 return (0);
25835 }
25836
25837 /*
25838 * xmlSchemaCheckCOSValidDefault:
25839 *
25840 * This will be called if: not nilled, no content and a default/fixed
25841 * value is provided.
25842 */
25843
25844 static int
xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val)25845 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25846 const xmlChar *value,
25847 xmlSchemaValPtr *val)
25848 {
25849 int ret = 0;
25850 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25851
25852 /*
25853 * cos-valid-default:
25854 * Schema Component Constraint: Element Default Valid (Immediate)
25855 * For a string to be a valid default with respect to a type
25856 * definition the appropriate case among the following must be true:
25857 */
25858 if WXS_IS_COMPLEX(inode->typeDef) {
25859 /*
25860 * Complex type.
25861 *
25862 * SPEC (2.1) "its {content type} must be a simple type definition
25863 * or mixed."
25864 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25865 * type}'s particle must be `emptiable` as defined by
25866 * Particle Emptiable ($3.9.6)."
25867 */
25868 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25869 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25870 (! WXS_EMPTIABLE(inode->typeDef)))) {
25871 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25872 /* NOTE that this covers (2.2.2) as well. */
25873 VERROR(ret, NULL,
25874 "For a string to be a valid default, the type definition "
25875 "must be a simple type or a complex type with simple content "
25876 "or mixed content and a particle emptiable");
25877 return(ret);
25878 }
25879 }
25880 /*
25881 * 1 If the type definition is a simple type definition, then the string
25882 * must be `valid` with respect to that definition as defined by String
25883 * Valid ($3.14.4).
25884 *
25885 * AND
25886 *
25887 * 2.2.1 If the {content type} is a simple type definition, then the
25888 * string must be `valid` with respect to that simple type definition
25889 * as defined by String Valid ($3.14.4).
25890 */
25891 if (WXS_IS_SIMPLE(inode->typeDef)) {
25892
25893 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25894 NULL, inode->typeDef, value, val, 1, 1, 0);
25895
25896 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25897
25898 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25899 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25900 }
25901 if (ret < 0) {
25902 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25903 "calling xmlSchemaVCheckCVCSimpleType()");
25904 }
25905 return (ret);
25906 }
25907
25908 static void
xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED,void * transdata,void * inputdata)25909 xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
25910 const xmlChar * name ATTRIBUTE_UNUSED,
25911 void *transdata, void *inputdata)
25912 {
25913 xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
25914 xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
25915 inode->decl = item;
25916 }
25917
25918 static int
xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)25919 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25920 {
25921 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25922 if (vctxt->inode == NULL) {
25923 VERROR_INT("xmlSchemaValidatorPushElem",
25924 "calling xmlSchemaGetFreshElemInfo()");
25925 return (-1);
25926 }
25927 vctxt->nbAttrInfos = 0;
25928 return (0);
25929 }
25930
25931 static int
xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr inode,xmlSchemaTypePtr type,const xmlChar * value)25932 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25933 xmlSchemaNodeInfoPtr inode,
25934 xmlSchemaTypePtr type,
25935 const xmlChar *value)
25936 {
25937 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25938 return (xmlSchemaVCheckCVCSimpleType(
25939 ACTXT_CAST vctxt, NULL,
25940 type, value, &(inode->val), 1, 1, 0));
25941 else
25942 return (xmlSchemaVCheckCVCSimpleType(
25943 ACTXT_CAST vctxt, NULL,
25944 type, value, NULL, 1, 0, 0));
25945 }
25946
25947
25948
25949 /*
25950 * Process END of element.
25951 */
25952 static int
xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)25953 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25954 {
25955 int ret = 0;
25956 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25957
25958 if (vctxt->nbAttrInfos != 0)
25959 xmlSchemaClearAttrInfos(vctxt);
25960 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25961 /*
25962 * This element was not expected;
25963 * we will not validate child elements of broken parents.
25964 * Skip validation of all content of the parent.
25965 */
25966 vctxt->skipDepth = vctxt->depth -1;
25967 goto end_elem;
25968 }
25969 if ((inode->typeDef == NULL) ||
25970 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25971 /*
25972 * 1. the type definition might be missing if the element was
25973 * error prone
25974 * 2. it might be abstract.
25975 */
25976 goto end_elem;
25977 }
25978 /*
25979 * Check the content model.
25980 */
25981 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25982 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25983
25984 /*
25985 * Workaround for "anyType".
25986 */
25987 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25988 goto character_content;
25989
25990 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25991 xmlChar *values[10];
25992 int terminal, nbval = 10, nbneg;
25993
25994 if (inode->regexCtxt == NULL) {
25995 /*
25996 * Create the regex context.
25997 */
25998 inode->regexCtxt =
25999 xmlRegNewExecCtxt(inode->typeDef->contModel,
26000 xmlSchemaVContentModelCallback, vctxt);
26001 if (inode->regexCtxt == NULL) {
26002 VERROR_INT("xmlSchemaValidatorPopElem",
26003 "failed to create a regex context");
26004 goto internal_error;
26005 }
26006 }
26007
26008 /*
26009 * Do not check further content if the node has been nilled
26010 */
26011 if (INODE_NILLED(inode)) {
26012 ret = 0;
26013 goto skip_nilled;
26014 }
26015
26016 /*
26017 * Get hold of the still expected content, since a further
26018 * call to xmlRegExecPushString() will lose this information.
26019 */
26020 xmlRegExecNextValues(inode->regexCtxt,
26021 &nbval, &nbneg, &values[0], &terminal);
26022 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26023 if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26024 /*
26025 * Still missing something.
26026 */
26027 ret = 1;
26028 inode->flags |=
26029 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26030 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26031 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26032 "Missing child element(s)",
26033 nbval, nbneg, values);
26034 } else {
26035 /*
26036 * Content model is satisfied.
26037 */
26038 ret = 0;
26039 }
26040
26041 }
26042 }
26043
26044 skip_nilled:
26045
26046 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26047 goto end_elem;
26048
26049 character_content:
26050
26051 if (vctxt->value != NULL) {
26052 xmlSchemaFreeValue(vctxt->value);
26053 vctxt->value = NULL;
26054 }
26055 /*
26056 * Check character content.
26057 */
26058 if (inode->decl == NULL) {
26059 /*
26060 * Speedup if no declaration exists.
26061 */
26062 if (WXS_IS_SIMPLE(inode->typeDef)) {
26063 ret = xmlSchemaVCheckINodeDataType(vctxt,
26064 inode, inode->typeDef, inode->value);
26065 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26066 ret = xmlSchemaVCheckINodeDataType(vctxt,
26067 inode, inode->typeDef->contentTypeDef,
26068 inode->value);
26069 }
26070 if (ret < 0) {
26071 VERROR_INT("xmlSchemaValidatorPopElem",
26072 "calling xmlSchemaVCheckCVCSimpleType()");
26073 goto internal_error;
26074 }
26075 goto end_elem;
26076 }
26077 /*
26078 * cvc-elt (3.3.4) : 5
26079 * The appropriate case among the following must be true:
26080 */
26081 /*
26082 * cvc-elt (3.3.4) : 5.1
26083 * If the declaration has a {value constraint},
26084 * the item has neither element nor character [children] and
26085 * clause 3.2 has not applied, then all of the following must be true:
26086 */
26087 if ((inode->decl->value != NULL) &&
26088 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26089 (! INODE_NILLED(inode))) {
26090 /*
26091 * cvc-elt (3.3.4) : 5.1.1
26092 * If the `actual type definition` is a `local type definition`
26093 * then the canonical lexical representation of the {value constraint}
26094 * value must be a valid default for the `actual type definition` as
26095 * defined in Element Default Valid (Immediate) ($3.3.6).
26096 */
26097 /*
26098 * NOTE: 'local' above means types acquired by xsi:type.
26099 * NOTE: Although the *canonical* value is stated, it is not
26100 * relevant if canonical or not. Additionally XML Schema 1.1
26101 * will removed this requirement as well.
26102 */
26103 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26104
26105 ret = xmlSchemaCheckCOSValidDefault(vctxt,
26106 inode->decl->value, &(inode->val));
26107 if (ret != 0) {
26108 if (ret < 0) {
26109 VERROR_INT("xmlSchemaValidatorPopElem",
26110 "calling xmlSchemaCheckCOSValidDefault()");
26111 goto internal_error;
26112 }
26113 goto end_elem;
26114 }
26115 /*
26116 * Stop here, to avoid redundant validation of the value
26117 * (see following).
26118 */
26119 goto default_psvi;
26120 }
26121 /*
26122 * cvc-elt (3.3.4) : 5.1.2
26123 * The element information item with the canonical lexical
26124 * representation of the {value constraint} value used as its
26125 * `normalized value` must be `valid` with respect to the
26126 * `actual type definition` as defined by Element Locally Valid (Type)
26127 * ($3.3.4).
26128 */
26129 if (WXS_IS_SIMPLE(inode->typeDef)) {
26130 ret = xmlSchemaVCheckINodeDataType(vctxt,
26131 inode, inode->typeDef, inode->decl->value);
26132 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26133 ret = xmlSchemaVCheckINodeDataType(vctxt,
26134 inode, inode->typeDef->contentTypeDef,
26135 inode->decl->value);
26136 }
26137 if (ret != 0) {
26138 if (ret < 0) {
26139 VERROR_INT("xmlSchemaValidatorPopElem",
26140 "calling xmlSchemaVCheckCVCSimpleType()");
26141 goto internal_error;
26142 }
26143 goto end_elem;
26144 }
26145
26146 default_psvi:
26147 /*
26148 * PSVI: Create a text node on the instance element.
26149 */
26150 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26151 (inode->node != NULL)) {
26152 xmlNodePtr textChild;
26153 xmlChar *normValue;
26154 /*
26155 * VAL TODO: Normalize the value.
26156 */
26157 normValue = xmlSchemaNormalizeValue(inode->typeDef,
26158 inode->decl->value);
26159 if (normValue != NULL) {
26160 textChild = xmlNewDocText(inode->node->doc,
26161 BAD_CAST normValue);
26162 xmlFree(normValue);
26163 } else
26164 textChild = xmlNewDocText(inode->node->doc,
26165 inode->decl->value);
26166 if (textChild == NULL) {
26167 VERROR_INT("xmlSchemaValidatorPopElem",
26168 "calling xmlNewDocText()");
26169 goto internal_error;
26170 } else
26171 xmlAddChild(inode->node, textChild);
26172 }
26173
26174 } else if (! INODE_NILLED(inode)) {
26175 /*
26176 * 5.2.1 The element information item must be `valid` with respect
26177 * to the `actual type definition` as defined by Element Locally
26178 * Valid (Type) ($3.3.4).
26179 */
26180 if (WXS_IS_SIMPLE(inode->typeDef)) {
26181 /*
26182 * SPEC (cvc-type) (3.1)
26183 * "If the type definition is a simple type definition, ..."
26184 * (3.1.3) "If clause 3.2 of Element Locally Valid
26185 * (Element) ($3.3.4) did not apply, then the `normalized value`
26186 * must be `valid` with respect to the type definition as defined
26187 * by String Valid ($3.14.4).
26188 */
26189 ret = xmlSchemaVCheckINodeDataType(vctxt,
26190 inode, inode->typeDef, inode->value);
26191 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26192 /*
26193 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26194 * definition, then the element information item must be
26195 * `valid` with respect to the type definition as per
26196 * Element Locally Valid (Complex Type) ($3.4.4);"
26197 *
26198 * SPEC (cvc-complex-type) (2.2)
26199 * "If the {content type} is a simple type definition, ...
26200 * the `normalized value` of the element information item is
26201 * `valid` with respect to that simple type definition as
26202 * defined by String Valid ($3.14.4)."
26203 */
26204 ret = xmlSchemaVCheckINodeDataType(vctxt,
26205 inode, inode->typeDef->contentTypeDef, inode->value);
26206 }
26207 if (ret != 0) {
26208 if (ret < 0) {
26209 VERROR_INT("xmlSchemaValidatorPopElem",
26210 "calling xmlSchemaVCheckCVCSimpleType()");
26211 goto internal_error;
26212 }
26213 goto end_elem;
26214 }
26215 /*
26216 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26217 * not applied, all of the following must be true:
26218 */
26219 if ((inode->decl->value != NULL) &&
26220 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26221
26222 /*
26223 * TODO: We will need a computed value, when comparison is
26224 * done on computed values.
26225 */
26226 /*
26227 * 5.2.2.1 The element information item must have no element
26228 * information item [children].
26229 */
26230 if (inode->flags &
26231 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26232 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26233 VERROR(ret, NULL,
26234 "The content must not contain element nodes since "
26235 "there is a fixed value constraint");
26236 goto end_elem;
26237 } else {
26238 /*
26239 * 5.2.2.2 The appropriate case among the following must
26240 * be true:
26241 */
26242 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26243 /*
26244 * 5.2.2.2.1 If the {content type} of the `actual type
26245 * definition` is mixed, then the *initial value* of the
26246 * item must match the canonical lexical representation
26247 * of the {value constraint} value.
26248 *
26249 * ... the *initial value* of an element information
26250 * item is the string composed of, in order, the
26251 * [character code] of each character information item in
26252 * the [children] of that element information item.
26253 */
26254 if (! xmlStrEqual(inode->value, inode->decl->value)){
26255 /*
26256 * VAL TODO: Report invalid & expected values as well.
26257 * VAL TODO: Implement the canonical stuff.
26258 */
26259 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26260 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26261 ret, NULL, NULL,
26262 "The initial value '%s' does not match the fixed "
26263 "value constraint '%s'",
26264 inode->value, inode->decl->value);
26265 goto end_elem;
26266 }
26267 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26268 /*
26269 * 5.2.2.2.2 If the {content type} of the `actual type
26270 * definition` is a simple type definition, then the
26271 * *actual value* of the item must match the canonical
26272 * lexical representation of the {value constraint} value.
26273 */
26274 /*
26275 * VAL TODO: *actual value* is the normalized value, impl.
26276 * this.
26277 * VAL TODO: Report invalid & expected values as well.
26278 * VAL TODO: Implement a comparison with the computed values.
26279 */
26280 if (! xmlStrEqual(inode->value,
26281 inode->decl->value)) {
26282 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26283 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26284 ret, NULL, NULL,
26285 "The actual value '%s' does not match the fixed "
26286 "value constraint '%s'",
26287 inode->value,
26288 inode->decl->value);
26289 goto end_elem;
26290 }
26291 }
26292 }
26293 }
26294 }
26295
26296 end_elem:
26297 if (vctxt->depth < 0) {
26298 /* TODO: raise error? */
26299 return (0);
26300 }
26301 if (vctxt->depth == vctxt->skipDepth)
26302 vctxt->skipDepth = -1;
26303 /*
26304 * Evaluate the history of XPath state objects.
26305 */
26306 if (inode->appliedXPath &&
26307 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26308 goto internal_error;
26309 /*
26310 * MAYBE TODO:
26311 * SPEC (6) "The element information item must be `valid` with
26312 * respect to each of the {identity-constraint definitions} as per
26313 * Identity-constraint Satisfied ($3.11.4)."
26314 */
26315 /*
26316 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26317 * need to be built in any case.
26318 * We will currently build IDC node-tables and bubble them only if
26319 * keyrefs do exist.
26320 */
26321
26322 /*
26323 * Add the current IDC target-nodes to the IDC node-tables.
26324 */
26325 if ((inode->idcMatchers != NULL) &&
26326 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26327 {
26328 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26329 goto internal_error;
26330 }
26331 /*
26332 * Validate IDC keyrefs.
26333 */
26334 if (vctxt->inode->hasKeyrefs)
26335 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26336 goto internal_error;
26337 /*
26338 * Merge/free the IDC table.
26339 */
26340 if (inode->idcTable != NULL) {
26341 if ((vctxt->depth > 0) &&
26342 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26343 {
26344 /*
26345 * Merge the IDC node table with the table of the parent node.
26346 */
26347 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26348 goto internal_error;
26349 }
26350 }
26351 /*
26352 * Clear the current ielem.
26353 * VAL TODO: Don't free the PSVI IDC tables if they are
26354 * requested for the PSVI.
26355 */
26356 xmlSchemaClearElemInfo(vctxt, inode);
26357 /*
26358 * Skip further processing if we are on the validation root.
26359 */
26360 if (vctxt->depth == 0) {
26361 vctxt->depth--;
26362 vctxt->inode = NULL;
26363 return (0);
26364 }
26365 /*
26366 * Reset the keyrefDepth if needed.
26367 */
26368 if (vctxt->aidcs != NULL) {
26369 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26370 do {
26371 if (aidc->keyrefDepth == vctxt->depth) {
26372 /*
26373 * A 'keyrefDepth' of a key/unique IDC matches the current
26374 * depth, this means that we are leaving the scope of the
26375 * top-most keyref IDC which refers to this IDC.
26376 */
26377 aidc->keyrefDepth = -1;
26378 }
26379 aidc = aidc->next;
26380 } while (aidc != NULL);
26381 }
26382 vctxt->depth--;
26383 vctxt->inode = vctxt->elemInfos[vctxt->depth];
26384 /*
26385 * VAL TODO: 7 If the element information item is the `validation root`, it must be
26386 * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26387 */
26388 return (ret);
26389
26390 internal_error:
26391 vctxt->err = -1;
26392 return (-1);
26393 }
26394
26395 /*
26396 * 3.4.4 Complex Type Definition Validation Rules
26397 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26398 */
26399 static int
xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)26400 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26401 {
26402 xmlSchemaNodeInfoPtr pielem;
26403 xmlSchemaTypePtr ptype;
26404 int ret = 0;
26405
26406 if (vctxt->depth <= 0) {
26407 VERROR_INT("xmlSchemaValidateChildElem",
26408 "not intended for the validation root");
26409 return (-1);
26410 }
26411 pielem = vctxt->elemInfos[vctxt->depth -1];
26412 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26413 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26414 /*
26415 * Handle 'nilled' elements.
26416 */
26417 if (INODE_NILLED(pielem)) {
26418 /*
26419 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26420 */
26421 ACTIVATE_PARENT_ELEM;
26422 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26423 VERROR(ret, NULL,
26424 "Neither character nor element content is allowed, "
26425 "because the element was 'nilled'");
26426 ACTIVATE_ELEM;
26427 goto unexpected_elem;
26428 }
26429
26430 ptype = pielem->typeDef;
26431
26432 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26433 /*
26434 * Workaround for "anyType": we have currently no content model
26435 * assigned for "anyType", so handle it explicitly.
26436 * "anyType" has an unbounded, lax "any" wildcard.
26437 */
26438 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26439 vctxt->inode->localName,
26440 vctxt->inode->nsName);
26441
26442 if (vctxt->inode->decl == NULL) {
26443 xmlSchemaAttrInfoPtr iattr;
26444 /*
26445 * Process "xsi:type".
26446 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26447 */
26448 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26449 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26450 if (iattr != NULL) {
26451 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26452 &(vctxt->inode->typeDef), NULL);
26453 if (ret != 0) {
26454 if (ret == -1) {
26455 VERROR_INT("xmlSchemaValidateChildElem",
26456 "calling xmlSchemaProcessXSIType() to "
26457 "process the attribute 'xsi:nil'");
26458 return (-1);
26459 }
26460 return (ret);
26461 }
26462 } else {
26463 /*
26464 * Fallback to "anyType".
26465 *
26466 * SPEC (cvc-assess-elt)
26467 * "If the item cannot be `strictly assessed`, [...]
26468 * an element information item's schema validity may be laxly
26469 * assessed if its `context-determined declaration` is not
26470 * skip by `validating` with respect to the `ur-type
26471 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26472 */
26473 vctxt->inode->typeDef =
26474 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26475 }
26476 }
26477 return (0);
26478 }
26479
26480 switch (ptype->contentType) {
26481 case XML_SCHEMA_CONTENT_EMPTY:
26482 /*
26483 * SPEC (2.1) "If the {content type} is empty, then the
26484 * element information item has no character or element
26485 * information item [children]."
26486 */
26487 ACTIVATE_PARENT_ELEM
26488 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26489 VERROR(ret, NULL,
26490 "Element content is not allowed, "
26491 "because the content type is empty");
26492 ACTIVATE_ELEM
26493 goto unexpected_elem;
26494 break;
26495
26496 case XML_SCHEMA_CONTENT_MIXED:
26497 case XML_SCHEMA_CONTENT_ELEMENTS: {
26498 xmlRegExecCtxtPtr regexCtxt;
26499 xmlChar *values[10];
26500 int terminal, nbval = 10, nbneg;
26501
26502 /* VAL TODO: Optimized "anyType" validation.*/
26503
26504 if (ptype->contModel == NULL) {
26505 VERROR_INT("xmlSchemaValidateChildElem",
26506 "type has elem content but no content model");
26507 return (-1);
26508 }
26509 /*
26510 * Safety belt for evaluation if the cont. model was already
26511 * examined to be invalid.
26512 */
26513 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26514 VERROR_INT("xmlSchemaValidateChildElem",
26515 "validating elem, but elem content is already invalid");
26516 return (-1);
26517 }
26518
26519 regexCtxt = pielem->regexCtxt;
26520 if (regexCtxt == NULL) {
26521 /*
26522 * Create the regex context.
26523 */
26524 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26525 xmlSchemaVContentModelCallback, vctxt);
26526 if (regexCtxt == NULL) {
26527 VERROR_INT("xmlSchemaValidateChildElem",
26528 "failed to create a regex context");
26529 return (-1);
26530 }
26531 pielem->regexCtxt = regexCtxt;
26532 }
26533
26534 /*
26535 * SPEC (2.4) "If the {content type} is element-only or mixed,
26536 * then the sequence of the element information item's
26537 * element information item [children], if any, taken in
26538 * order, is `valid` with respect to the {content type}'s
26539 * particle, as defined in Element Sequence Locally Valid
26540 * (Particle) ($3.9.4)."
26541 */
26542 ret = xmlRegExecPushString2(regexCtxt,
26543 vctxt->inode->localName,
26544 vctxt->inode->nsName,
26545 vctxt->inode);
26546 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26547 VERROR_INT("xmlSchemaValidateChildElem",
26548 "calling xmlRegExecPushString2()");
26549 return (-1);
26550 }
26551 if (ret < 0) {
26552 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26553 &values[0], &terminal);
26554 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26555 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26556 "This element is not expected",
26557 nbval, nbneg, values);
26558 ret = vctxt->err;
26559 goto unexpected_elem;
26560 } else
26561 ret = 0;
26562 }
26563 break;
26564 case XML_SCHEMA_CONTENT_SIMPLE:
26565 case XML_SCHEMA_CONTENT_BASIC:
26566 ACTIVATE_PARENT_ELEM
26567 if (WXS_IS_COMPLEX(ptype)) {
26568 /*
26569 * SPEC (cvc-complex-type) (2.2)
26570 * "If the {content type} is a simple type definition, then
26571 * the element information item has no element information
26572 * item [children], ..."
26573 */
26574 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26575 VERROR(ret, NULL, "Element content is not allowed, "
26576 "because the content type is a simple type definition");
26577 } else {
26578 /*
26579 * SPEC (cvc-type) (3.1.2) "The element information item must
26580 * have no element information item [children]."
26581 */
26582 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26583 VERROR(ret, NULL, "Element content is not allowed, "
26584 "because the type definition is simple");
26585 }
26586 ACTIVATE_ELEM
26587 ret = vctxt->err;
26588 goto unexpected_elem;
26589 break;
26590
26591 default:
26592 break;
26593 }
26594 return (ret);
26595 unexpected_elem:
26596 /*
26597 * Pop this element and set the skipDepth to skip
26598 * all further content of the parent element.
26599 */
26600 vctxt->skipDepth = vctxt->depth;
26601 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26602 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26603 return (ret);
26604 }
26605
26606 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26607 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26608 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26609
26610 static int
xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,int nodeType,const xmlChar * value,int len,int mode,int * consumed)26611 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26612 int nodeType, const xmlChar *value, int len,
26613 int mode, int *consumed)
26614 {
26615 /*
26616 * Unfortunately we have to duplicate the text sometimes.
26617 * OPTIMIZE: Maybe we could skip it, if:
26618 * 1. content type is simple
26619 * 2. whitespace is "collapse"
26620 * 3. it consists of whitespace only
26621 *
26622 * Process character content.
26623 */
26624 if (consumed != NULL)
26625 *consumed = 0;
26626 if (INODE_NILLED(vctxt->inode)) {
26627 /*
26628 * SPEC cvc-elt (3.3.4 - 3.2.1)
26629 * "The element information item must have no character or
26630 * element information item [children]."
26631 */
26632 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26633 "Neither character nor element content is allowed "
26634 "because the element is 'nilled'");
26635 return (vctxt->err);
26636 }
26637 /*
26638 * SPEC (2.1) "If the {content type} is empty, then the
26639 * element information item has no character or element
26640 * information item [children]."
26641 */
26642 if (vctxt->inode->typeDef->contentType ==
26643 XML_SCHEMA_CONTENT_EMPTY) {
26644 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26645 "Character content is not allowed, "
26646 "because the content type is empty");
26647 return (vctxt->err);
26648 }
26649
26650 if (vctxt->inode->typeDef->contentType ==
26651 XML_SCHEMA_CONTENT_ELEMENTS) {
26652 if ((nodeType != XML_TEXT_NODE) ||
26653 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26654 /*
26655 * SPEC cvc-complex-type (2.3)
26656 * "If the {content type} is element-only, then the
26657 * element information item has no character information
26658 * item [children] other than those whose [character
26659 * code] is defined as a white space in [XML 1.0 (Second
26660 * Edition)]."
26661 */
26662 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26663 "Character content other than whitespace is not allowed "
26664 "because the content type is 'element-only'");
26665 return (vctxt->err);
26666 }
26667 return (0);
26668 }
26669
26670 if ((value == NULL) || (value[0] == 0))
26671 return (0);
26672 /*
26673 * Save the value.
26674 * NOTE that even if the content type is *mixed*, we need the
26675 * *initial value* for default/fixed value constraints.
26676 */
26677 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26678 ((vctxt->inode->decl == NULL) ||
26679 (vctxt->inode->decl->value == NULL)))
26680 return (0);
26681
26682 if (vctxt->inode->value == NULL) {
26683 /*
26684 * Set the value.
26685 */
26686 switch (mode) {
26687 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26688 /*
26689 * When working on a tree.
26690 */
26691 vctxt->inode->value = value;
26692 break;
26693 case XML_SCHEMA_PUSH_TEXT_CREATED:
26694 /*
26695 * When working with the reader.
26696 * The value will be freed by the element info.
26697 */
26698 vctxt->inode->value = value;
26699 if (consumed != NULL)
26700 *consumed = 1;
26701 vctxt->inode->flags |=
26702 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26703 break;
26704 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26705 /*
26706 * When working with SAX.
26707 * The value will be freed by the element info.
26708 */
26709 if (len != -1)
26710 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26711 else
26712 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26713 vctxt->inode->flags |=
26714 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26715 break;
26716 default:
26717 break;
26718 }
26719 } else {
26720 if (len < 0)
26721 len = xmlStrlen(value);
26722 /*
26723 * Concat the value.
26724 */
26725 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26726 vctxt->inode->value = BAD_CAST xmlStrncat(
26727 (xmlChar *) vctxt->inode->value, value, len);
26728 } else {
26729 vctxt->inode->value =
26730 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26731 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26732 }
26733 }
26734
26735 return (0);
26736 }
26737
26738 static int
xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)26739 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26740 {
26741 int ret = 0;
26742
26743 if ((vctxt->skipDepth != -1) &&
26744 (vctxt->depth >= vctxt->skipDepth)) {
26745 VERROR_INT("xmlSchemaValidateElem",
26746 "in skip-state");
26747 goto internal_error;
26748 }
26749 if (vctxt->xsiAssemble) {
26750 /*
26751 * We will stop validation if there was an error during
26752 * dynamic schema construction.
26753 * Note that we simply set @skipDepth to 0, this could
26754 * mean that a streaming document via SAX would be
26755 * still read to the end but it won't be validated any more.
26756 * TODO: If we are sure how to stop the validation at once
26757 * for all input scenarios, then this should be changed to
26758 * instantly stop the validation.
26759 */
26760 ret = xmlSchemaAssembleByXSI(vctxt);
26761 if (ret != 0) {
26762 if (ret == -1)
26763 goto internal_error;
26764 vctxt->skipDepth = 0;
26765 return(ret);
26766 }
26767 /*
26768 * Augment the IDC definitions for the main schema and all imported ones
26769 * NOTE: main schema is the first in the imported list
26770 */
26771 xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
26772 vctxt);
26773 }
26774 if (vctxt->depth > 0) {
26775 /*
26776 * Validate this element against the content model
26777 * of the parent.
26778 */
26779 ret = xmlSchemaValidateChildElem(vctxt);
26780 if (ret != 0) {
26781 if (ret < 0) {
26782 VERROR_INT("xmlSchemaValidateElem",
26783 "calling xmlSchemaStreamValidateChildElement()");
26784 goto internal_error;
26785 }
26786 goto exit;
26787 }
26788 if (vctxt->depth == vctxt->skipDepth)
26789 goto exit;
26790 if ((vctxt->inode->decl == NULL) &&
26791 (vctxt->inode->typeDef == NULL)) {
26792 VERROR_INT("xmlSchemaValidateElem",
26793 "the child element was valid but neither the "
26794 "declaration nor the type was set");
26795 goto internal_error;
26796 }
26797 } else {
26798 /*
26799 * Get the declaration of the validation root.
26800 */
26801 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26802 vctxt->inode->localName,
26803 vctxt->inode->nsName);
26804 if (vctxt->inode->decl == NULL) {
26805 ret = XML_SCHEMAV_CVC_ELT_1;
26806 VERROR(ret, NULL,
26807 "No matching global declaration available "
26808 "for the validation root");
26809 goto exit;
26810 }
26811 }
26812
26813 if (vctxt->inode->decl == NULL)
26814 goto type_validation;
26815
26816 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26817 int skip;
26818 /*
26819 * Wildcards.
26820 */
26821 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26822 if (ret != 0) {
26823 if (ret < 0) {
26824 VERROR_INT("xmlSchemaValidateElem",
26825 "calling xmlSchemaValidateElemWildcard()");
26826 goto internal_error;
26827 }
26828 goto exit;
26829 }
26830 if (skip) {
26831 vctxt->skipDepth = vctxt->depth;
26832 goto exit;
26833 }
26834 /*
26835 * The declaration might be set by the wildcard validation,
26836 * when the processContents is "lax" or "strict".
26837 */
26838 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26839 /*
26840 * Clear the "decl" field to not confuse further processing.
26841 */
26842 vctxt->inode->decl = NULL;
26843 goto type_validation;
26844 }
26845 }
26846 /*
26847 * Validate against the declaration.
26848 */
26849 ret = xmlSchemaValidateElemDecl(vctxt);
26850 if (ret != 0) {
26851 if (ret < 0) {
26852 VERROR_INT("xmlSchemaValidateElem",
26853 "calling xmlSchemaValidateElemDecl()");
26854 goto internal_error;
26855 }
26856 goto exit;
26857 }
26858 /*
26859 * Validate against the type definition.
26860 */
26861 type_validation:
26862
26863 if (vctxt->inode->typeDef == NULL) {
26864 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26865 ret = XML_SCHEMAV_CVC_TYPE_1;
26866 VERROR(ret, NULL,
26867 "The type definition is absent");
26868 goto exit;
26869 }
26870 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26871 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26872 ret = XML_SCHEMAV_CVC_TYPE_2;
26873 VERROR(ret, NULL,
26874 "The type definition is abstract");
26875 goto exit;
26876 }
26877 /*
26878 * Evaluate IDCs. Do it here, since new IDC matchers are registered
26879 * during validation against the declaration. This must be done
26880 * _before_ attribute validation.
26881 */
26882 if (vctxt->xpathStates != NULL) {
26883 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26884 vctxt->inode->appliedXPath = 1;
26885 if (ret == -1) {
26886 VERROR_INT("xmlSchemaValidateElem",
26887 "calling xmlSchemaXPathEvaluate()");
26888 goto internal_error;
26889 }
26890 }
26891 /*
26892 * Validate attributes.
26893 */
26894 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26895 if ((vctxt->nbAttrInfos != 0) ||
26896 (vctxt->inode->typeDef->attrUses != NULL)) {
26897
26898 ret = xmlSchemaVAttributesComplex(vctxt);
26899 }
26900 } else if (vctxt->nbAttrInfos != 0) {
26901
26902 ret = xmlSchemaVAttributesSimple(vctxt);
26903 }
26904 /*
26905 * Clear registered attributes.
26906 */
26907 if (vctxt->nbAttrInfos != 0)
26908 xmlSchemaClearAttrInfos(vctxt);
26909 if (ret == -1) {
26910 VERROR_INT("xmlSchemaValidateElem",
26911 "calling attributes validation");
26912 goto internal_error;
26913 }
26914 /*
26915 * Don't return an error if attributes are invalid on purpose.
26916 */
26917 ret = 0;
26918
26919 exit:
26920 if (ret != 0)
26921 vctxt->skipDepth = vctxt->depth;
26922 return (ret);
26923 internal_error:
26924 return (-1);
26925 }
26926
26927 #ifdef XML_SCHEMA_READER_ENABLED
26928 static int
xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)26929 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26930 {
26931 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26932 int depth, nodeType, ret = 0, consumed;
26933 xmlSchemaNodeInfoPtr ielem;
26934
26935 vctxt->depth = -1;
26936 ret = xmlTextReaderRead(vctxt->reader);
26937 /*
26938 * Move to the document element.
26939 */
26940 while (ret == 1) {
26941 nodeType = xmlTextReaderNodeType(vctxt->reader);
26942 if (nodeType == XML_ELEMENT_NODE)
26943 goto root_found;
26944 ret = xmlTextReaderRead(vctxt->reader);
26945 }
26946 goto exit;
26947
26948 root_found:
26949
26950 do {
26951 depth = xmlTextReaderDepth(vctxt->reader);
26952 nodeType = xmlTextReaderNodeType(vctxt->reader);
26953
26954 if (nodeType == XML_ELEMENT_NODE) {
26955
26956 vctxt->depth++;
26957 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26958 VERROR_INT("xmlSchemaVReaderWalk",
26959 "calling xmlSchemaValidatorPushElem()");
26960 goto internal_error;
26961 }
26962 ielem = vctxt->inode;
26963 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26964 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26965 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26966 /*
26967 * Is the element empty?
26968 */
26969 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26970 if (ret == -1) {
26971 VERROR_INT("xmlSchemaVReaderWalk",
26972 "calling xmlTextReaderIsEmptyElement()");
26973 goto internal_error;
26974 }
26975 if (ret) {
26976 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26977 }
26978 /*
26979 * Register attributes.
26980 */
26981 vctxt->nbAttrInfos = 0;
26982 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26983 if (ret == -1) {
26984 VERROR_INT("xmlSchemaVReaderWalk",
26985 "calling xmlTextReaderMoveToFirstAttribute()");
26986 goto internal_error;
26987 }
26988 if (ret == 1) {
26989 do {
26990 /*
26991 * VAL TODO: How do we know that the reader works on a
26992 * node tree, to be able to pass a node here?
26993 */
26994 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26995 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26996 xmlTextReaderNamespaceUri(vctxt->reader), 1,
26997 xmlTextReaderValue(vctxt->reader), 1) == -1) {
26998
26999 VERROR_INT("xmlSchemaVReaderWalk",
27000 "calling xmlSchemaValidatorPushAttribute()");
27001 goto internal_error;
27002 }
27003 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27004 if (ret == -1) {
27005 VERROR_INT("xmlSchemaVReaderWalk",
27006 "calling xmlTextReaderMoveToFirstAttribute()");
27007 goto internal_error;
27008 }
27009 } while (ret == 1);
27010 /*
27011 * Back to element position.
27012 */
27013 ret = xmlTextReaderMoveToElement(vctxt->reader);
27014 if (ret == -1) {
27015 VERROR_INT("xmlSchemaVReaderWalk",
27016 "calling xmlTextReaderMoveToElement()");
27017 goto internal_error;
27018 }
27019 }
27020 /*
27021 * Validate the element.
27022 */
27023 ret= xmlSchemaValidateElem(vctxt);
27024 if (ret != 0) {
27025 if (ret == -1) {
27026 VERROR_INT("xmlSchemaVReaderWalk",
27027 "calling xmlSchemaValidateElem()");
27028 goto internal_error;
27029 }
27030 goto exit;
27031 }
27032 if (vctxt->depth == vctxt->skipDepth) {
27033 int curDepth;
27034 /*
27035 * Skip all content.
27036 */
27037 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27038 ret = xmlTextReaderRead(vctxt->reader);
27039 curDepth = xmlTextReaderDepth(vctxt->reader);
27040 while ((ret == 1) && (curDepth != depth)) {
27041 ret = xmlTextReaderRead(vctxt->reader);
27042 curDepth = xmlTextReaderDepth(vctxt->reader);
27043 }
27044 if (ret < 0) {
27045 /*
27046 * VAL TODO: A reader error occurred; what to do here?
27047 */
27048 ret = 1;
27049 goto exit;
27050 }
27051 }
27052 goto leave_elem;
27053 }
27054 /*
27055 * READER VAL TODO: Is an END_ELEM really never called
27056 * if the elem is empty?
27057 */
27058 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27059 goto leave_elem;
27060 } else if (nodeType == END_ELEM) {
27061 /*
27062 * Process END of element.
27063 */
27064 leave_elem:
27065 ret = xmlSchemaValidatorPopElem(vctxt);
27066 if (ret != 0) {
27067 if (ret < 0) {
27068 VERROR_INT("xmlSchemaVReaderWalk",
27069 "calling xmlSchemaValidatorPopElem()");
27070 goto internal_error;
27071 }
27072 goto exit;
27073 }
27074 if (vctxt->depth >= 0)
27075 ielem = vctxt->inode;
27076 else
27077 ielem = NULL;
27078 } else if ((nodeType == XML_TEXT_NODE) ||
27079 (nodeType == XML_CDATA_SECTION_NODE) ||
27080 (nodeType == WHTSP) ||
27081 (nodeType == SIGN_WHTSP)) {
27082 /*
27083 * Process character content.
27084 */
27085 xmlChar *value;
27086
27087 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27088 nodeType = XML_TEXT_NODE;
27089
27090 value = xmlTextReaderValue(vctxt->reader);
27091 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27092 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27093 if (! consumed)
27094 xmlFree(value);
27095 if (ret == -1) {
27096 VERROR_INT("xmlSchemaVReaderWalk",
27097 "calling xmlSchemaVPushText()");
27098 goto internal_error;
27099 }
27100 } else if ((nodeType == XML_ENTITY_NODE) ||
27101 (nodeType == XML_ENTITY_REF_NODE)) {
27102 /*
27103 * VAL TODO: What to do with entities?
27104 */
27105 TODO
27106 }
27107 /*
27108 * Read next node.
27109 */
27110 ret = xmlTextReaderRead(vctxt->reader);
27111 } while (ret == 1);
27112
27113 exit:
27114 return (ret);
27115 internal_error:
27116 return (-1);
27117 }
27118 #endif
27119
27120 /************************************************************************
27121 * *
27122 * SAX validation handlers *
27123 * *
27124 ************************************************************************/
27125
27126 /*
27127 * Process text content.
27128 */
27129 static void
xmlSchemaSAXHandleText(void * ctx,const xmlChar * ch,int len)27130 xmlSchemaSAXHandleText(void *ctx,
27131 const xmlChar * ch,
27132 int len)
27133 {
27134 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27135
27136 if (vctxt->depth < 0)
27137 return;
27138 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27139 return;
27140 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27141 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27142 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27143 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27144 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27145 "calling xmlSchemaVPushText()");
27146 vctxt->err = -1;
27147 xmlStopParser(vctxt->parserCtxt);
27148 }
27149 }
27150
27151 /*
27152 * Process CDATA content.
27153 */
27154 static void
xmlSchemaSAXHandleCDataSection(void * ctx,const xmlChar * ch,int len)27155 xmlSchemaSAXHandleCDataSection(void *ctx,
27156 const xmlChar * ch,
27157 int len)
27158 {
27159 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27160
27161 if (vctxt->depth < 0)
27162 return;
27163 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27164 return;
27165 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27166 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27167 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27168 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27169 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27170 "calling xmlSchemaVPushText()");
27171 vctxt->err = -1;
27172 xmlStopParser(vctxt->parserCtxt);
27173 }
27174 }
27175
27176 static void
xmlSchemaSAXHandleReference(void * ctx ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED)27177 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27178 const xmlChar * name ATTRIBUTE_UNUSED)
27179 {
27180 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27181
27182 if (vctxt->depth < 0)
27183 return;
27184 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27185 return;
27186 /* SAX VAL TODO: What to do here? */
27187 }
27188
27189 static void
xmlSchemaSAXHandleStartElementNs(void * ctx,const xmlChar * localname,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI,int nb_namespaces,const xmlChar ** namespaces,int nb_attributes,int nb_defaulted ATTRIBUTE_UNUSED,const xmlChar ** attributes)27190 xmlSchemaSAXHandleStartElementNs(void *ctx,
27191 const xmlChar * localname,
27192 const xmlChar * prefix ATTRIBUTE_UNUSED,
27193 const xmlChar * URI,
27194 int nb_namespaces,
27195 const xmlChar ** namespaces,
27196 int nb_attributes,
27197 int nb_defaulted ATTRIBUTE_UNUSED,
27198 const xmlChar ** attributes)
27199 {
27200 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27201 int ret;
27202 xmlSchemaNodeInfoPtr ielem;
27203 int i, j;
27204
27205 /*
27206 * SAX VAL TODO: What to do with nb_defaulted?
27207 */
27208 /*
27209 * Skip elements if inside a "skip" wildcard or invalid.
27210 */
27211 vctxt->depth++;
27212 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27213 return;
27214 /*
27215 * Push the element.
27216 */
27217 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27218 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27219 "calling xmlSchemaValidatorPushElem()");
27220 goto internal_error;
27221 }
27222 ielem = vctxt->inode;
27223 /*
27224 * TODO: Is this OK?
27225 */
27226 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27227 ielem->localName = localname;
27228 ielem->nsName = URI;
27229 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27230 /*
27231 * Register namespaces on the elem info.
27232 */
27233 if (nb_namespaces != 0) {
27234 /*
27235 * Although the parser builds its own namespace list,
27236 * we have no access to it, so we'll use an own one.
27237 */
27238 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27239 /*
27240 * Store prefix and namespace name.
27241 */
27242 if (ielem->nsBindings == NULL) {
27243 ielem->nsBindings =
27244 (const xmlChar **) xmlMalloc(10 *
27245 sizeof(const xmlChar *));
27246 if (ielem->nsBindings == NULL) {
27247 xmlSchemaVErrMemory(vctxt);
27248 goto internal_error;
27249 }
27250 ielem->nbNsBindings = 0;
27251 ielem->sizeNsBindings = 5;
27252 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27253 ielem->sizeNsBindings *= 2;
27254 ielem->nsBindings =
27255 (const xmlChar **) xmlRealloc(
27256 (void *) ielem->nsBindings,
27257 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27258 if (ielem->nsBindings == NULL) {
27259 xmlSchemaVErrMemory(vctxt);
27260 goto internal_error;
27261 }
27262 }
27263
27264 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27265 if (namespaces[j+1][0] == 0) {
27266 /*
27267 * Handle xmlns="".
27268 */
27269 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27270 } else
27271 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27272 namespaces[j+1];
27273 ielem->nbNsBindings++;
27274 }
27275 }
27276 /*
27277 * Register attributes.
27278 * SAX VAL TODO: We are not adding namespace declaration
27279 * attributes yet.
27280 */
27281 if (nb_attributes != 0) {
27282 int valueLen, k, l;
27283 xmlChar *value;
27284
27285 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27286 /*
27287 * Duplicate the value, changing any & to a literal ampersand.
27288 *
27289 * libxml2 differs from normal SAX here in that it escapes all ampersands
27290 * as & instead of delivering the raw converted string. Changing the
27291 * behavior at this point would break applications that use this API, so
27292 * we are forced to work around it.
27293 */
27294 valueLen = attributes[j+4] - attributes[j+3];
27295 value = xmlMalloc(valueLen + 1);
27296 if (value == NULL) {
27297 xmlSchemaVErrMemory(vctxt);
27298 goto internal_error;
27299 }
27300 for (k = 0, l = 0; k < valueLen; l++) {
27301 if (k < valueLen - 4 &&
27302 attributes[j+3][k+0] == '&' &&
27303 attributes[j+3][k+1] == '#' &&
27304 attributes[j+3][k+2] == '3' &&
27305 attributes[j+3][k+3] == '8' &&
27306 attributes[j+3][k+4] == ';') {
27307 value[l] = '&';
27308 k += 5;
27309 } else {
27310 value[l] = attributes[j+3][k];
27311 k++;
27312 }
27313 }
27314 value[l] = '\0';
27315 /*
27316 * TODO: Set the node line.
27317 */
27318 ret = xmlSchemaValidatorPushAttribute(vctxt,
27319 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27320 value, 1);
27321 if (ret == -1) {
27322 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27323 "calling xmlSchemaValidatorPushAttribute()");
27324 goto internal_error;
27325 }
27326 }
27327 }
27328 /*
27329 * Validate the element.
27330 */
27331 ret = xmlSchemaValidateElem(vctxt);
27332 if (ret != 0) {
27333 if (ret == -1) {
27334 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27335 "calling xmlSchemaValidateElem()");
27336 goto internal_error;
27337 }
27338 goto exit;
27339 }
27340
27341 exit:
27342 return;
27343 internal_error:
27344 vctxt->err = -1;
27345 xmlStopParser(vctxt->parserCtxt);
27346 }
27347
27348 static void
xmlSchemaSAXHandleEndElementNs(void * ctx,const xmlChar * localname ATTRIBUTE_UNUSED,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI ATTRIBUTE_UNUSED)27349 xmlSchemaSAXHandleEndElementNs(void *ctx,
27350 const xmlChar * localname ATTRIBUTE_UNUSED,
27351 const xmlChar * prefix ATTRIBUTE_UNUSED,
27352 const xmlChar * URI ATTRIBUTE_UNUSED)
27353 {
27354 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27355 int res;
27356
27357 /*
27358 * Skip elements if inside a "skip" wildcard or if invalid.
27359 */
27360 if (vctxt->skipDepth != -1) {
27361 if (vctxt->depth > vctxt->skipDepth) {
27362 vctxt->depth--;
27363 return;
27364 } else
27365 vctxt->skipDepth = -1;
27366 }
27367 /*
27368 * SAX VAL TODO: Just a temporary check.
27369 */
27370 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27371 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27372 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27373 "elem pop mismatch");
27374 }
27375 res = xmlSchemaValidatorPopElem(vctxt);
27376 if (res != 0) {
27377 if (res < 0) {
27378 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27379 "calling xmlSchemaValidatorPopElem()");
27380 goto internal_error;
27381 }
27382 goto exit;
27383 }
27384 exit:
27385 return;
27386 internal_error:
27387 vctxt->err = -1;
27388 xmlStopParser(vctxt->parserCtxt);
27389 }
27390
27391 /************************************************************************
27392 * *
27393 * Validation interfaces *
27394 * *
27395 ************************************************************************/
27396
27397 /**
27398 * xmlSchemaNewValidCtxt:
27399 * @schema: a precompiled XML Schemas
27400 *
27401 * Create an XML Schemas validation context based on the given schema.
27402 *
27403 * Returns the validation context or NULL in case of error
27404 */
27405 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)27406 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27407 {
27408 xmlSchemaValidCtxtPtr ret;
27409
27410 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27411 if (ret == NULL) {
27412 xmlSchemaVErrMemory(NULL);
27413 return (NULL);
27414 }
27415 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27416 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27417 ret->dict = xmlDictCreate();
27418 ret->nodeQNames = xmlSchemaItemListCreate();
27419 ret->schema = schema;
27420 return (ret);
27421 }
27422
27423 /**
27424 * xmlSchemaValidateSetFilename:
27425 * @vctxt: the schema validation context
27426 * @filename: the file name
27427 *
27428 * Workaround to provide file error reporting information when this is
27429 * not provided by current APIs
27430 */
27431 void
xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt,const char * filename)27432 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27433 if (vctxt == NULL)
27434 return;
27435 if (vctxt->filename != NULL)
27436 xmlFree(vctxt->filename);
27437 if (filename != NULL)
27438 vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27439 else
27440 vctxt->filename = NULL;
27441 }
27442
27443 /**
27444 * xmlSchemaClearValidCtxt:
27445 * @vctxt: the schema validation context
27446 *
27447 * Free the resources associated to the schema validation context;
27448 * leaves some fields alive intended for reuse of the context.
27449 */
27450 static void
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)27451 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27452 {
27453 if (vctxt == NULL)
27454 return;
27455
27456 /*
27457 * TODO: Should we clear the flags?
27458 * Might be problematic if one reuses the context
27459 * and assumes that the options remain the same.
27460 */
27461 vctxt->flags = 0;
27462 vctxt->validationRoot = NULL;
27463 vctxt->doc = NULL;
27464 #ifdef LIBXML_READER_ENABLED
27465 vctxt->reader = NULL;
27466 #endif
27467 vctxt->hasKeyrefs = 0;
27468
27469 if (vctxt->value != NULL) {
27470 xmlSchemaFreeValue(vctxt->value);
27471 vctxt->value = NULL;
27472 }
27473 /*
27474 * Augmented IDC information.
27475 */
27476 if (vctxt->aidcs != NULL) {
27477 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27478 do {
27479 next = cur->next;
27480 xmlFree(cur);
27481 cur = next;
27482 } while (cur != NULL);
27483 vctxt->aidcs = NULL;
27484 }
27485
27486 if (vctxt->idcNodes != NULL) {
27487 int i;
27488 xmlSchemaPSVIIDCNodePtr item;
27489
27490 for (i = 0; i < vctxt->nbIdcNodes; i++) {
27491 item = vctxt->idcNodes[i];
27492 xmlFree(item->keys);
27493 xmlFree(item);
27494 }
27495 xmlFree(vctxt->idcNodes);
27496 vctxt->idcNodes = NULL;
27497 vctxt->nbIdcNodes = 0;
27498 vctxt->sizeIdcNodes = 0;
27499 }
27500
27501 if (vctxt->idcKeys != NULL) {
27502 int i;
27503 for (i = 0; i < vctxt->nbIdcKeys; i++)
27504 xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27505 xmlFree(vctxt->idcKeys);
27506 vctxt->idcKeys = NULL;
27507 vctxt->nbIdcKeys = 0;
27508 vctxt->sizeIdcKeys = 0;
27509 }
27510
27511 /*
27512 * Note that we won't delete the XPath state pool here.
27513 */
27514 if (vctxt->xpathStates != NULL) {
27515 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27516 vctxt->xpathStates = NULL;
27517 }
27518 /*
27519 * Attribute info.
27520 */
27521 if (vctxt->nbAttrInfos != 0) {
27522 xmlSchemaClearAttrInfos(vctxt);
27523 }
27524 /*
27525 * Element info.
27526 */
27527 if (vctxt->elemInfos != NULL) {
27528 int i;
27529 xmlSchemaNodeInfoPtr ei;
27530
27531 for (i = 0; i < vctxt->sizeElemInfos; i++) {
27532 ei = vctxt->elemInfos[i];
27533 if (ei == NULL)
27534 break;
27535 xmlSchemaClearElemInfo(vctxt, ei);
27536 }
27537 }
27538 xmlSchemaItemListClear(vctxt->nodeQNames);
27539 /* Recreate the dict. */
27540 xmlDictFree(vctxt->dict);
27541 /*
27542 * TODO: Is is save to recreate it? Do we have a scenario
27543 * where the user provides the dict?
27544 */
27545 vctxt->dict = xmlDictCreate();
27546
27547 if (vctxt->filename != NULL) {
27548 xmlFree(vctxt->filename);
27549 vctxt->filename = NULL;
27550 }
27551
27552 /*
27553 * Note that some cleanup functions can move items to the cache,
27554 * so the cache shouldn't be freed too early.
27555 */
27556 if (vctxt->idcMatcherCache != NULL) {
27557 xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27558
27559 while (matcher) {
27560 tmp = matcher;
27561 matcher = matcher->nextCached;
27562 xmlSchemaIDCFreeMatcherList(tmp);
27563 }
27564 vctxt->idcMatcherCache = NULL;
27565 }
27566 }
27567
27568 /**
27569 * xmlSchemaFreeValidCtxt:
27570 * @ctxt: the schema validation context
27571 *
27572 * Free the resources associated to the schema validation context
27573 */
27574 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)27575 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27576 {
27577 if (ctxt == NULL)
27578 return;
27579 if (ctxt->value != NULL)
27580 xmlSchemaFreeValue(ctxt->value);
27581 if (ctxt->pctxt != NULL)
27582 xmlSchemaFreeParserCtxt(ctxt->pctxt);
27583 if (ctxt->idcNodes != NULL) {
27584 int i;
27585 xmlSchemaPSVIIDCNodePtr item;
27586
27587 for (i = 0; i < ctxt->nbIdcNodes; i++) {
27588 item = ctxt->idcNodes[i];
27589 xmlFree(item->keys);
27590 xmlFree(item);
27591 }
27592 xmlFree(ctxt->idcNodes);
27593 }
27594 if (ctxt->idcKeys != NULL) {
27595 int i;
27596 for (i = 0; i < ctxt->nbIdcKeys; i++)
27597 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27598 xmlFree(ctxt->idcKeys);
27599 }
27600
27601 if (ctxt->xpathStates != NULL) {
27602 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27603 ctxt->xpathStates = NULL;
27604 }
27605 if (ctxt->xpathStatePool != NULL) {
27606 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27607 ctxt->xpathStatePool = NULL;
27608 }
27609
27610 /*
27611 * Augmented IDC information.
27612 */
27613 if (ctxt->aidcs != NULL) {
27614 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27615 do {
27616 next = cur->next;
27617 xmlFree(cur);
27618 cur = next;
27619 } while (cur != NULL);
27620 }
27621 if (ctxt->attrInfos != NULL) {
27622 int i;
27623 xmlSchemaAttrInfoPtr attr;
27624
27625 /* Just a paranoid call to the cleanup. */
27626 if (ctxt->nbAttrInfos != 0)
27627 xmlSchemaClearAttrInfos(ctxt);
27628 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27629 attr = ctxt->attrInfos[i];
27630 xmlFree(attr);
27631 }
27632 xmlFree(ctxt->attrInfos);
27633 }
27634 if (ctxt->elemInfos != NULL) {
27635 int i;
27636 xmlSchemaNodeInfoPtr ei;
27637
27638 for (i = 0; i < ctxt->sizeElemInfos; i++) {
27639 ei = ctxt->elemInfos[i];
27640 if (ei == NULL)
27641 break;
27642 xmlSchemaClearElemInfo(ctxt, ei);
27643 xmlFree(ei);
27644 }
27645 xmlFree(ctxt->elemInfos);
27646 }
27647 if (ctxt->nodeQNames != NULL)
27648 xmlSchemaItemListFree(ctxt->nodeQNames);
27649 if (ctxt->dict != NULL)
27650 xmlDictFree(ctxt->dict);
27651 if (ctxt->filename != NULL)
27652 xmlFree(ctxt->filename);
27653 xmlFree(ctxt);
27654 }
27655
27656 /**
27657 * xmlSchemaIsValid:
27658 * @ctxt: the schema validation context
27659 *
27660 * Check if any error was detected during validation.
27661 *
27662 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27663 * of internal error.
27664 */
27665 int
xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)27666 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27667 {
27668 if (ctxt == NULL)
27669 return(-1);
27670 return(ctxt->err == 0);
27671 }
27672
27673 /**
27674 * xmlSchemaSetValidErrors:
27675 * @ctxt: a schema validation context
27676 * @err: the error function
27677 * @warn: the warning function
27678 * @ctx: the functions context
27679 *
27680 * DEPRECATED: Use xmlSchemaSetValidStructuredErrors.
27681 *
27682 * Set the error and warning callback information
27683 */
27684 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)27685 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27686 xmlSchemaValidityErrorFunc err,
27687 xmlSchemaValidityWarningFunc warn, void *ctx)
27688 {
27689 if (ctxt == NULL)
27690 return;
27691 ctxt->error = err;
27692 ctxt->warning = warn;
27693 ctxt->errCtxt = ctx;
27694 if (ctxt->pctxt != NULL)
27695 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27696 }
27697
27698 /**
27699 * xmlSchemaSetValidStructuredErrors:
27700 * @ctxt: a schema validation context
27701 * @serror: the structured error function
27702 * @ctx: the functions context
27703 *
27704 * Set the structured error callback
27705 */
27706 void
xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)27707 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27708 xmlStructuredErrorFunc serror, void *ctx)
27709 {
27710 if (ctxt == NULL)
27711 return;
27712 ctxt->serror = serror;
27713 ctxt->error = NULL;
27714 ctxt->warning = NULL;
27715 ctxt->errCtxt = ctx;
27716 if (ctxt->pctxt != NULL)
27717 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27718 }
27719
27720 /**
27721 * xmlSchemaGetValidErrors:
27722 * @ctxt: a XML-Schema validation context
27723 * @err: the error function result
27724 * @warn: the warning function result
27725 * @ctx: the functions context result
27726 *
27727 * Get the error and warning callback information
27728 *
27729 * Returns -1 in case of error and 0 otherwise
27730 */
27731 int
xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)27732 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27733 xmlSchemaValidityErrorFunc * err,
27734 xmlSchemaValidityWarningFunc * warn, void **ctx)
27735 {
27736 if (ctxt == NULL)
27737 return (-1);
27738 if (err != NULL)
27739 *err = ctxt->error;
27740 if (warn != NULL)
27741 *warn = ctxt->warning;
27742 if (ctx != NULL)
27743 *ctx = ctxt->errCtxt;
27744 return (0);
27745 }
27746
27747
27748 /**
27749 * xmlSchemaSetValidOptions:
27750 * @ctxt: a schema validation context
27751 * @options: a combination of xmlSchemaValidOption
27752 *
27753 * Sets the options to be used during the validation.
27754 *
27755 * Returns 0 in case of success, -1 in case of an
27756 * API error.
27757 */
27758 int
xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,int options)27759 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27760 int options)
27761
27762 {
27763 int i;
27764
27765 if (ctxt == NULL)
27766 return (-1);
27767 /*
27768 * WARNING: Change the start value if adding to the
27769 * xmlSchemaValidOption.
27770 * TODO: Is there an other, more easy to maintain,
27771 * way?
27772 */
27773 for (i = 1; i < (int) sizeof(int) * 8; i++) {
27774 if (options & 1<<i)
27775 return (-1);
27776 }
27777 ctxt->options = options;
27778 return (0);
27779 }
27780
27781 /**
27782 * xmlSchemaValidCtxtGetOptions:
27783 * @ctxt: a schema validation context
27784 *
27785 * Get the validation context options.
27786 *
27787 * Returns the option combination or -1 on error.
27788 */
27789 int
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)27790 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27791
27792 {
27793 if (ctxt == NULL)
27794 return (-1);
27795 else
27796 return (ctxt->options);
27797 }
27798
27799 static int
xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)27800 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27801 {
27802 xmlAttrPtr attr;
27803 int ret = 0;
27804 xmlSchemaNodeInfoPtr ielem = NULL;
27805 xmlNodePtr node, valRoot;
27806 const xmlChar *nsName;
27807
27808 /* DOC VAL TODO: Move this to the start function. */
27809 if (vctxt->validationRoot != NULL)
27810 valRoot = vctxt->validationRoot;
27811 else
27812 valRoot = xmlDocGetRootElement(vctxt->doc);
27813 if (valRoot == NULL) {
27814 /* VAL TODO: Error code? */
27815 VERROR(1, NULL, "The document has no document element");
27816 return (1);
27817 }
27818 vctxt->depth = -1;
27819 vctxt->validationRoot = valRoot;
27820 node = valRoot;
27821 while (node != NULL) {
27822 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27823 goto next_sibling;
27824 if (node->type == XML_ELEMENT_NODE) {
27825
27826 /*
27827 * Init the node-info.
27828 */
27829 vctxt->depth++;
27830 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27831 goto internal_error;
27832 ielem = vctxt->inode;
27833 ielem->node = node;
27834 ielem->nodeLine = node->line;
27835 ielem->localName = node->name;
27836 if (node->ns != NULL)
27837 ielem->nsName = node->ns->href;
27838 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27839 /*
27840 * Register attributes.
27841 * DOC VAL TODO: We do not register namespace declaration
27842 * attributes yet.
27843 */
27844 vctxt->nbAttrInfos = 0;
27845 if (node->properties != NULL) {
27846 attr = node->properties;
27847 do {
27848 if (attr->ns != NULL)
27849 nsName = attr->ns->href;
27850 else
27851 nsName = NULL;
27852 ret = xmlSchemaValidatorPushAttribute(vctxt,
27853 (xmlNodePtr) attr,
27854 /*
27855 * Note that we give it the line number of the
27856 * parent element.
27857 */
27858 ielem->nodeLine,
27859 attr->name, nsName, 0,
27860 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27861 if (ret == -1) {
27862 VERROR_INT("xmlSchemaDocWalk",
27863 "calling xmlSchemaValidatorPushAttribute()");
27864 goto internal_error;
27865 }
27866 attr = attr->next;
27867 } while (attr);
27868 }
27869 /*
27870 * Validate the element.
27871 */
27872 ret = xmlSchemaValidateElem(vctxt);
27873 if (ret != 0) {
27874 if (ret == -1) {
27875 VERROR_INT("xmlSchemaDocWalk",
27876 "calling xmlSchemaValidateElem()");
27877 goto internal_error;
27878 }
27879 /*
27880 * Don't stop validation; just skip the content
27881 * of this element.
27882 */
27883 goto leave_node;
27884 }
27885 if ((vctxt->skipDepth != -1) &&
27886 (vctxt->depth >= vctxt->skipDepth))
27887 goto leave_node;
27888 } else if ((node->type == XML_TEXT_NODE) ||
27889 (node->type == XML_CDATA_SECTION_NODE)) {
27890 /*
27891 * Process character content.
27892 */
27893 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27894 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27895 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27896 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27897 if (ret < 0) {
27898 VERROR_INT("xmlSchemaVDocWalk",
27899 "calling xmlSchemaVPushText()");
27900 goto internal_error;
27901 }
27902 /*
27903 * DOC VAL TODO: Should we skip further validation of the
27904 * element content here?
27905 */
27906 } else if ((node->type == XML_ENTITY_NODE) ||
27907 (node->type == XML_ENTITY_REF_NODE)) {
27908 /*
27909 * DOC VAL TODO: What to do with entities?
27910 */
27911 VERROR_INT("xmlSchemaVDocWalk",
27912 "there is at least one entity reference in the node-tree "
27913 "currently being validated. Processing of entities with "
27914 "this XML Schema processor is not supported (yet). Please "
27915 "substitute entities before validation.");
27916 goto internal_error;
27917 } else {
27918 goto leave_node;
27919 /*
27920 * DOC VAL TODO: XInclude nodes, etc.
27921 */
27922 }
27923 /*
27924 * Walk the doc.
27925 */
27926 if (node->children != NULL) {
27927 node = node->children;
27928 continue;
27929 }
27930 leave_node:
27931 if (node->type == XML_ELEMENT_NODE) {
27932 /*
27933 * Leaving the scope of an element.
27934 */
27935 if (node != vctxt->inode->node) {
27936 VERROR_INT("xmlSchemaVDocWalk",
27937 "element position mismatch");
27938 goto internal_error;
27939 }
27940 ret = xmlSchemaValidatorPopElem(vctxt);
27941 if (ret != 0) {
27942 if (ret < 0) {
27943 VERROR_INT("xmlSchemaVDocWalk",
27944 "calling xmlSchemaValidatorPopElem()");
27945 goto internal_error;
27946 }
27947 }
27948 if (node == valRoot)
27949 goto exit;
27950 }
27951 next_sibling:
27952 if (node->next != NULL)
27953 node = node->next;
27954 else {
27955 node = node->parent;
27956 goto leave_node;
27957 }
27958 }
27959
27960 exit:
27961 return (ret);
27962 internal_error:
27963 return (-1);
27964 }
27965
27966 static int
xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt)27967 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27968 /*
27969 * Some initialization.
27970 */
27971 vctxt->err = 0;
27972 vctxt->nberrors = 0;
27973 vctxt->depth = -1;
27974 vctxt->skipDepth = -1;
27975 vctxt->hasKeyrefs = 0;
27976 #ifdef ENABLE_IDC_NODE_TABLES_TEST
27977 vctxt->createIDCNodeTables = 1;
27978 #else
27979 vctxt->createIDCNodeTables = 0;
27980 #endif
27981 /*
27982 * Create a schema + parser if necessary.
27983 */
27984 if (vctxt->schema == NULL) {
27985 xmlSchemaParserCtxtPtr pctxt;
27986
27987 vctxt->xsiAssemble = 1;
27988 /*
27989 * If not schema was given then we will create a schema
27990 * dynamically using XSI schema locations.
27991 *
27992 * Create the schema parser context.
27993 */
27994 if ((vctxt->pctxt == NULL) &&
27995 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27996 return (-1);
27997 pctxt = vctxt->pctxt;
27998 pctxt->xsiAssemble = 1;
27999 /*
28000 * Create the schema.
28001 */
28002 vctxt->schema = xmlSchemaNewSchema(pctxt);
28003 if (vctxt->schema == NULL)
28004 return (-1);
28005 /*
28006 * Create the schema construction context.
28007 */
28008 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28009 if (pctxt->constructor == NULL)
28010 return(-1);
28011 pctxt->constructor->mainSchema = vctxt->schema;
28012 /*
28013 * Take ownership of the constructor to be able to free it.
28014 */
28015 pctxt->ownsConstructor = 1;
28016 }
28017 /*
28018 * Augment the IDC definitions for the main schema and all imported ones
28019 * NOTE: main schema if the first in the imported list
28020 */
28021 xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28022 vctxt);
28023
28024 return(0);
28025 }
28026
28027 static void
xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt)28028 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28029 if (vctxt->xsiAssemble) {
28030 if (vctxt->schema != NULL) {
28031 xmlSchemaFree(vctxt->schema);
28032 vctxt->schema = NULL;
28033 }
28034 }
28035 xmlSchemaClearValidCtxt(vctxt);
28036 }
28037
28038 static int
xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)28039 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28040 {
28041 int ret = 0;
28042
28043 if (xmlSchemaPreRun(vctxt) < 0)
28044 return(-1);
28045
28046 if (vctxt->doc != NULL) {
28047 /*
28048 * Tree validation.
28049 */
28050 ret = xmlSchemaVDocWalk(vctxt);
28051 #ifdef LIBXML_READER_ENABLED
28052 } else if (vctxt->reader != NULL) {
28053 /*
28054 * XML Reader validation.
28055 */
28056 #ifdef XML_SCHEMA_READER_ENABLED
28057 ret = xmlSchemaVReaderWalk(vctxt);
28058 #endif
28059 #endif
28060 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28061 /*
28062 * SAX validation.
28063 */
28064 ret = xmlParseDocument(vctxt->parserCtxt);
28065 } else {
28066 VERROR_INT("xmlSchemaVStart",
28067 "no instance to validate");
28068 ret = -1;
28069 }
28070
28071 xmlSchemaPostRun(vctxt);
28072 if (ret == 0)
28073 ret = vctxt->err;
28074 return (ret);
28075 }
28076
28077 /**
28078 * xmlSchemaValidateOneElement:
28079 * @ctxt: a schema validation context
28080 * @elem: an element node
28081 *
28082 * Validate a branch of a tree, starting with the given @elem.
28083 *
28084 * Returns 0 if the element and its subtree is valid, a positive error
28085 * code number otherwise and -1 in case of an internal or API error.
28086 */
28087 int
xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)28088 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28089 {
28090 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28091 return (-1);
28092
28093 if (ctxt->schema == NULL)
28094 return (-1);
28095
28096 ctxt->doc = elem->doc;
28097 ctxt->node = elem;
28098 ctxt->validationRoot = elem;
28099 return(xmlSchemaVStart(ctxt));
28100 }
28101
28102 /**
28103 * xmlSchemaValidateDoc:
28104 * @ctxt: a schema validation context
28105 * @doc: a parsed document tree
28106 *
28107 * Validate a document tree in memory.
28108 *
28109 * Returns 0 if the document is schemas valid, a positive error code
28110 * number otherwise and -1 in case of internal or API error.
28111 */
28112 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)28113 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28114 {
28115 if ((ctxt == NULL) || (doc == NULL))
28116 return (-1);
28117
28118 ctxt->doc = doc;
28119 ctxt->node = xmlDocGetRootElement(doc);
28120 if (ctxt->node == NULL) {
28121 xmlSchemaCustomErr(ACTXT_CAST ctxt,
28122 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28123 (xmlNodePtr) doc, NULL,
28124 "The document has no document element", NULL, NULL);
28125 return (ctxt->err);
28126 }
28127 ctxt->validationRoot = ctxt->node;
28128 return (xmlSchemaVStart(ctxt));
28129 }
28130
28131
28132 /************************************************************************
28133 * *
28134 * Function and data for SAX streaming API *
28135 * *
28136 ************************************************************************/
28137 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28138 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28139
28140 struct _xmlSchemaSplitSAXData {
28141 xmlSAXHandlerPtr user_sax;
28142 void *user_data;
28143 xmlSchemaValidCtxtPtr ctxt;
28144 xmlSAXHandlerPtr schemas_sax;
28145 };
28146
28147 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28148
28149 struct _xmlSchemaSAXPlug {
28150 unsigned int magic;
28151
28152 /* the original callbacks information */
28153 xmlSAXHandlerPtr *user_sax_ptr;
28154 xmlSAXHandlerPtr user_sax;
28155 void **user_data_ptr;
28156 void *user_data;
28157
28158 /* the block plugged back and validation information */
28159 xmlSAXHandler schemas_sax;
28160 xmlSchemaValidCtxtPtr ctxt;
28161 };
28162
28163 /* All those functions just bounces to the user provided SAX handlers */
28164 static void
internalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28165 internalSubsetSplit(void *ctx, const xmlChar *name,
28166 const xmlChar *ExternalID, const xmlChar *SystemID)
28167 {
28168 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28169 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28170 (ctxt->user_sax->internalSubset != NULL))
28171 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28172 SystemID);
28173 }
28174
28175 static int
isStandaloneSplit(void * ctx)28176 isStandaloneSplit(void *ctx)
28177 {
28178 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28179 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28180 (ctxt->user_sax->isStandalone != NULL))
28181 return(ctxt->user_sax->isStandalone(ctxt->user_data));
28182 return(0);
28183 }
28184
28185 static int
hasInternalSubsetSplit(void * ctx)28186 hasInternalSubsetSplit(void *ctx)
28187 {
28188 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28189 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28190 (ctxt->user_sax->hasInternalSubset != NULL))
28191 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28192 return(0);
28193 }
28194
28195 static int
hasExternalSubsetSplit(void * ctx)28196 hasExternalSubsetSplit(void *ctx)
28197 {
28198 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28199 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28200 (ctxt->user_sax->hasExternalSubset != NULL))
28201 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28202 return(0);
28203 }
28204
28205 static void
externalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28206 externalSubsetSplit(void *ctx, const xmlChar *name,
28207 const xmlChar *ExternalID, const xmlChar *SystemID)
28208 {
28209 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28210 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28211 (ctxt->user_sax->externalSubset != NULL))
28212 ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28213 SystemID);
28214 }
28215
28216 static xmlParserInputPtr
resolveEntitySplit(void * ctx,const xmlChar * publicId,const xmlChar * systemId)28217 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28218 {
28219 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28220 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28221 (ctxt->user_sax->resolveEntity != NULL))
28222 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28223 systemId));
28224 return(NULL);
28225 }
28226
28227 static xmlEntityPtr
getEntitySplit(void * ctx,const xmlChar * name)28228 getEntitySplit(void *ctx, const xmlChar *name)
28229 {
28230 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28231 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28232 (ctxt->user_sax->getEntity != NULL))
28233 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28234 return(NULL);
28235 }
28236
28237 static xmlEntityPtr
getParameterEntitySplit(void * ctx,const xmlChar * name)28238 getParameterEntitySplit(void *ctx, const xmlChar *name)
28239 {
28240 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28241 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28242 (ctxt->user_sax->getParameterEntity != NULL))
28243 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28244 return(NULL);
28245 }
28246
28247
28248 static void
entityDeclSplit(void * ctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)28249 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28250 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28251 {
28252 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28253 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28254 (ctxt->user_sax->entityDecl != NULL))
28255 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28256 systemId, content);
28257 }
28258
28259 static void
attributeDeclSplit(void * ctx,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)28260 attributeDeclSplit(void *ctx, const xmlChar * elem,
28261 const xmlChar * name, int type, int def,
28262 const xmlChar * defaultValue, xmlEnumerationPtr tree)
28263 {
28264 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28265 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28266 (ctxt->user_sax->attributeDecl != NULL)) {
28267 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28268 def, defaultValue, tree);
28269 } else {
28270 xmlFreeEnumeration(tree);
28271 }
28272 }
28273
28274 static void
elementDeclSplit(void * ctx,const xmlChar * name,int type,xmlElementContentPtr content)28275 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28276 xmlElementContentPtr content)
28277 {
28278 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28279 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28280 (ctxt->user_sax->elementDecl != NULL))
28281 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28282 }
28283
28284 static void
notationDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)28285 notationDeclSplit(void *ctx, const xmlChar *name,
28286 const xmlChar *publicId, const xmlChar *systemId)
28287 {
28288 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28289 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28290 (ctxt->user_sax->notationDecl != NULL))
28291 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28292 systemId);
28293 }
28294
28295 static void
unparsedEntityDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)28296 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28297 const xmlChar *publicId, const xmlChar *systemId,
28298 const xmlChar *notationName)
28299 {
28300 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28301 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28302 (ctxt->user_sax->unparsedEntityDecl != NULL))
28303 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28304 systemId, notationName);
28305 }
28306
28307 static void
setDocumentLocatorSplit(void * ctx,xmlSAXLocatorPtr loc)28308 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28309 {
28310 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28311 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28312 (ctxt->user_sax->setDocumentLocator != NULL))
28313 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28314 }
28315
28316 static void
startDocumentSplit(void * ctx)28317 startDocumentSplit(void *ctx)
28318 {
28319 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28320 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28321 (ctxt->user_sax->startDocument != NULL))
28322 ctxt->user_sax->startDocument(ctxt->user_data);
28323 }
28324
28325 static void
endDocumentSplit(void * ctx)28326 endDocumentSplit(void *ctx)
28327 {
28328 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28329 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28330 (ctxt->user_sax->endDocument != NULL))
28331 ctxt->user_sax->endDocument(ctxt->user_data);
28332 }
28333
28334 static void
processingInstructionSplit(void * ctx,const xmlChar * target,const xmlChar * data)28335 processingInstructionSplit(void *ctx, const xmlChar *target,
28336 const xmlChar *data)
28337 {
28338 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28339 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28340 (ctxt->user_sax->processingInstruction != NULL))
28341 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28342 }
28343
28344 static void
commentSplit(void * ctx,const xmlChar * value)28345 commentSplit(void *ctx, const xmlChar *value)
28346 {
28347 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28348 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28349 (ctxt->user_sax->comment != NULL))
28350 ctxt->user_sax->comment(ctxt->user_data, value);
28351 }
28352
28353 /*
28354 * Varargs error callbacks to the user application, harder ...
28355 */
28356
28357 static void
warningSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28358 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28359 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28360 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28361 (ctxt->user_sax->warning != NULL)) {
28362 /* TODO */
28363 }
28364 }
28365 static void
errorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28366 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28367 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28368 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28369 (ctxt->user_sax->error != NULL)) {
28370 /* TODO */
28371 }
28372 }
28373 static void
fatalErrorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28374 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28375 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28376 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28377 (ctxt->user_sax->fatalError != NULL)) {
28378 /* TODO */
28379 }
28380 }
28381
28382 /*
28383 * Those are function where both the user handler and the schemas handler
28384 * need to be called.
28385 */
28386 static void
charactersSplit(void * ctx,const xmlChar * ch,int len)28387 charactersSplit(void *ctx, const xmlChar *ch, int len)
28388 {
28389 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28390 if (ctxt == NULL)
28391 return;
28392 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28393 ctxt->user_sax->characters(ctxt->user_data, ch, len);
28394 if (ctxt->ctxt != NULL)
28395 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28396 }
28397
28398 static void
ignorableWhitespaceSplit(void * ctx,const xmlChar * ch,int len)28399 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28400 {
28401 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28402 if (ctxt == NULL)
28403 return;
28404 if ((ctxt->user_sax != NULL) &&
28405 (ctxt->user_sax->ignorableWhitespace != NULL))
28406 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28407 if (ctxt->ctxt != NULL)
28408 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28409 }
28410
28411 static void
cdataBlockSplit(void * ctx,const xmlChar * value,int len)28412 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28413 {
28414 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28415 if (ctxt == NULL)
28416 return;
28417 if ((ctxt->user_sax != NULL) &&
28418 (ctxt->user_sax->cdataBlock != NULL))
28419 ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28420 if (ctxt->ctxt != NULL)
28421 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28422 }
28423
28424 static void
referenceSplit(void * ctx,const xmlChar * name)28425 referenceSplit(void *ctx, const xmlChar *name)
28426 {
28427 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28428 if (ctxt == NULL)
28429 return;
28430 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28431 (ctxt->user_sax->reference != NULL))
28432 ctxt->user_sax->reference(ctxt->user_data, name);
28433 if (ctxt->ctxt != NULL)
28434 xmlSchemaSAXHandleReference(ctxt->user_data, name);
28435 }
28436
28437 static void
startElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI,int nb_namespaces,const xmlChar ** namespaces,int nb_attributes,int nb_defaulted,const xmlChar ** attributes)28438 startElementNsSplit(void *ctx, const xmlChar * localname,
28439 const xmlChar * prefix, const xmlChar * URI,
28440 int nb_namespaces, const xmlChar ** namespaces,
28441 int nb_attributes, int nb_defaulted,
28442 const xmlChar ** attributes) {
28443 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28444 if (ctxt == NULL)
28445 return;
28446 if ((ctxt->user_sax != NULL) &&
28447 (ctxt->user_sax->startElementNs != NULL))
28448 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28449 URI, nb_namespaces, namespaces,
28450 nb_attributes, nb_defaulted,
28451 attributes);
28452 if (ctxt->ctxt != NULL)
28453 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28454 URI, nb_namespaces, namespaces,
28455 nb_attributes, nb_defaulted,
28456 attributes);
28457 }
28458
28459 static void
endElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)28460 endElementNsSplit(void *ctx, const xmlChar * localname,
28461 const xmlChar * prefix, const xmlChar * URI) {
28462 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28463 if (ctxt == NULL)
28464 return;
28465 if ((ctxt->user_sax != NULL) &&
28466 (ctxt->user_sax->endElementNs != NULL))
28467 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28468 if (ctxt->ctxt != NULL)
28469 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28470 }
28471
28472 /**
28473 * xmlSchemaSAXPlug:
28474 * @ctxt: a schema validation context
28475 * @sax: a pointer to the original xmlSAXHandlerPtr
28476 * @user_data: a pointer to the original SAX user data pointer
28477 *
28478 * Plug a SAX based validation layer in a SAX parsing event flow.
28479 * The original @saxptr and @dataptr data are replaced by new pointers
28480 * but the calls to the original will be maintained.
28481 *
28482 * Returns a pointer to a data structure needed to unplug the validation layer
28483 * or NULL in case of errors.
28484 */
28485 xmlSchemaSAXPlugPtr
xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,xmlSAXHandlerPtr * sax,void ** user_data)28486 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28487 xmlSAXHandlerPtr *sax, void **user_data)
28488 {
28489 xmlSchemaSAXPlugPtr ret;
28490 xmlSAXHandlerPtr old_sax;
28491
28492 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28493 return(NULL);
28494
28495 /*
28496 * We only allow to plug into SAX2 event streams
28497 */
28498 old_sax = *sax;
28499 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28500 return(NULL);
28501 if ((old_sax != NULL) &&
28502 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28503 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28504 return(NULL);
28505
28506 /*
28507 * everything seems right allocate the local data needed for that layer
28508 */
28509 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28510 if (ret == NULL) {
28511 return(NULL);
28512 }
28513 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28514 ret->magic = XML_SAX_PLUG_MAGIC;
28515 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28516 ret->ctxt = ctxt;
28517 ret->user_sax_ptr = sax;
28518 ret->user_sax = old_sax;
28519 if (old_sax == NULL) {
28520 /*
28521 * go direct, no need for the split block and functions.
28522 */
28523 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28524 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28525 /*
28526 * Note that we use the same text-function for both, to prevent
28527 * the parser from testing for ignorable whitespace.
28528 */
28529 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28530 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28531
28532 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28533 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28534
28535 ret->user_data = ctxt;
28536 *user_data = ctxt;
28537 } else {
28538 /*
28539 * for each callback unused by Schemas initialize it to the Split
28540 * routine only if non NULL in the user block, this can speed up
28541 * things at the SAX level.
28542 */
28543 if (old_sax->internalSubset != NULL)
28544 ret->schemas_sax.internalSubset = internalSubsetSplit;
28545 if (old_sax->isStandalone != NULL)
28546 ret->schemas_sax.isStandalone = isStandaloneSplit;
28547 if (old_sax->hasInternalSubset != NULL)
28548 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28549 if (old_sax->hasExternalSubset != NULL)
28550 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28551 if (old_sax->resolveEntity != NULL)
28552 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28553 if (old_sax->getEntity != NULL)
28554 ret->schemas_sax.getEntity = getEntitySplit;
28555 if (old_sax->entityDecl != NULL)
28556 ret->schemas_sax.entityDecl = entityDeclSplit;
28557 if (old_sax->notationDecl != NULL)
28558 ret->schemas_sax.notationDecl = notationDeclSplit;
28559 if (old_sax->attributeDecl != NULL)
28560 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28561 if (old_sax->elementDecl != NULL)
28562 ret->schemas_sax.elementDecl = elementDeclSplit;
28563 if (old_sax->unparsedEntityDecl != NULL)
28564 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28565 if (old_sax->setDocumentLocator != NULL)
28566 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28567 if (old_sax->startDocument != NULL)
28568 ret->schemas_sax.startDocument = startDocumentSplit;
28569 if (old_sax->endDocument != NULL)
28570 ret->schemas_sax.endDocument = endDocumentSplit;
28571 if (old_sax->processingInstruction != NULL)
28572 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28573 if (old_sax->comment != NULL)
28574 ret->schemas_sax.comment = commentSplit;
28575 if (old_sax->warning != NULL)
28576 ret->schemas_sax.warning = warningSplit;
28577 if (old_sax->error != NULL)
28578 ret->schemas_sax.error = errorSplit;
28579 if (old_sax->fatalError != NULL)
28580 ret->schemas_sax.fatalError = fatalErrorSplit;
28581 if (old_sax->getParameterEntity != NULL)
28582 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28583 if (old_sax->externalSubset != NULL)
28584 ret->schemas_sax.externalSubset = externalSubsetSplit;
28585
28586 /*
28587 * the 6 schemas callback have to go to the splitter functions
28588 * Note that we use the same text-function for ignorableWhitespace
28589 * if possible, to prevent the parser from testing for ignorable
28590 * whitespace.
28591 */
28592 ret->schemas_sax.characters = charactersSplit;
28593 if ((old_sax->ignorableWhitespace != NULL) &&
28594 (old_sax->ignorableWhitespace != old_sax->characters))
28595 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28596 else
28597 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28598 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28599 ret->schemas_sax.reference = referenceSplit;
28600 ret->schemas_sax.startElementNs = startElementNsSplit;
28601 ret->schemas_sax.endElementNs = endElementNsSplit;
28602
28603 ret->user_data_ptr = user_data;
28604 ret->user_data = *user_data;
28605 *user_data = ret;
28606 }
28607
28608 /*
28609 * plug the pointers back.
28610 */
28611 *sax = &(ret->schemas_sax);
28612 ctxt->sax = *sax;
28613 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28614 xmlSchemaPreRun(ctxt);
28615 return(ret);
28616 }
28617
28618 /**
28619 * xmlSchemaSAXUnplug:
28620 * @plug: a data structure returned by xmlSchemaSAXPlug
28621 *
28622 * Unplug a SAX based validation layer in a SAX parsing event flow.
28623 * The original pointers used in the call are restored.
28624 *
28625 * Returns 0 in case of success and -1 in case of failure.
28626 */
28627 int
xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)28628 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28629 {
28630 xmlSAXHandlerPtr *sax;
28631 void **user_data;
28632
28633 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28634 return(-1);
28635 plug->magic = 0;
28636
28637 xmlSchemaPostRun(plug->ctxt);
28638 /* restore the data */
28639 sax = plug->user_sax_ptr;
28640 *sax = plug->user_sax;
28641 if (plug->user_sax != NULL) {
28642 user_data = plug->user_data_ptr;
28643 *user_data = plug->user_data;
28644 }
28645
28646 /* free and return */
28647 xmlFree(plug);
28648 return(0);
28649 }
28650
28651 /**
28652 * xmlSchemaValidateSetLocator:
28653 * @vctxt: a schema validation context
28654 * @f: the locator function pointer
28655 * @ctxt: the locator context
28656 *
28657 * Allows to set a locator function to the validation context,
28658 * which will be used to provide file and line information since
28659 * those are not provided as part of the SAX validation flow
28660 * Setting @f to NULL disable the locator.
28661 */
28662
28663 void
xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,xmlSchemaValidityLocatorFunc f,void * ctxt)28664 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28665 xmlSchemaValidityLocatorFunc f,
28666 void *ctxt)
28667 {
28668 if (vctxt == NULL) return;
28669 vctxt->locFunc = f;
28670 vctxt->locCtxt = ctxt;
28671 }
28672
28673 /**
28674 * xmlSchemaValidateStreamLocator:
28675 * @ctx: the xmlTextReaderPtr used
28676 * @file: returned file information
28677 * @line: returned line information
28678 *
28679 * Internal locator function for the readers
28680 *
28681 * Returns 0 in case the Schema validation could be (de)activated and
28682 * -1 in case of error.
28683 */
28684 static int
xmlSchemaValidateStreamLocator(void * ctx,const char ** file,unsigned long * line)28685 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28686 unsigned long *line) {
28687 xmlParserCtxtPtr ctxt;
28688
28689 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28690 return(-1);
28691
28692 if (file != NULL)
28693 *file = NULL;
28694 if (line != NULL)
28695 *line = 0;
28696
28697 ctxt = (xmlParserCtxtPtr) ctx;
28698 if (ctxt->input != NULL) {
28699 if (file != NULL)
28700 *file = ctxt->input->filename;
28701 if (line != NULL)
28702 *line = ctxt->input->line;
28703 return(0);
28704 }
28705 return(-1);
28706 }
28707
28708 /**
28709 * xmlSchemaValidateStreamInternal:
28710 * @ctxt: a schema validation context
28711 * @pctxt: a parser context
28712 *
28713 * Returns 0 if the document is schemas valid, a positive error code
28714 * number otherwise and -1 in case of internal or API error.
28715 */
28716 static int
xmlSchemaValidateStreamInternal(xmlSchemaValidCtxtPtr ctxt,xmlParserCtxtPtr pctxt)28717 xmlSchemaValidateStreamInternal(xmlSchemaValidCtxtPtr ctxt,
28718 xmlParserCtxtPtr pctxt) {
28719 xmlSchemaSAXPlugPtr plug = NULL;
28720 int ret;
28721
28722 pctxt->linenumbers = 1;
28723 xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
28724
28725 ctxt->parserCtxt = pctxt;
28726 ctxt->input = pctxt->input->buf;
28727
28728 /*
28729 * Plug the validation and launch the parsing
28730 */
28731 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28732 if (plug == NULL) {
28733 ret = -1;
28734 goto done;
28735 }
28736 ctxt->input = pctxt->input->buf;
28737 ctxt->sax = pctxt->sax;
28738 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28739 ret = xmlSchemaVStart(ctxt);
28740
28741 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28742 ret = ctxt->parserCtxt->errNo;
28743 if (ret == 0)
28744 ret = 1;
28745 }
28746
28747 done:
28748 ctxt->parserCtxt = NULL;
28749 ctxt->sax = NULL;
28750 ctxt->input = NULL;
28751 if (plug != NULL) {
28752 xmlSchemaSAXUnplug(plug);
28753 }
28754 return (ret);
28755 }
28756
28757 /**
28758 * xmlSchemaValidateStream:
28759 * @ctxt: a schema validation context
28760 * @input: the input to use for reading the data
28761 * @enc: an optional encoding information
28762 * @sax: a SAX handler for the resulting events
28763 * @user_data: the context to provide to the SAX handler.
28764 *
28765 * Validate an input based on a flow of SAX event from the parser
28766 * and forward the events to the @sax handler with the provided @user_data
28767 * the user provided @sax handler must be a SAX2 one.
28768 *
28769 * Returns 0 if the document is schemas valid, a positive error code
28770 * number otherwise and -1 in case of internal or API error.
28771 */
28772 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,xmlSAXHandlerPtr sax,void * user_data)28773 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28774 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28775 xmlSAXHandlerPtr sax, void *user_data)
28776 {
28777 xmlParserCtxtPtr pctxt = NULL;
28778 xmlParserInputPtr inputStream = NULL;
28779 int ret;
28780
28781 if ((ctxt == NULL) || (input == NULL))
28782 return (-1);
28783
28784 /*
28785 * prepare the parser
28786 */
28787 if (sax != NULL) {
28788 pctxt = xmlNewSAXParserCtxt(sax, user_data);
28789 if (pctxt == NULL)
28790 return (-1);
28791 } else {
28792 pctxt = xmlNewParserCtxt();
28793 if (pctxt == NULL)
28794 return (-1);
28795 /* We really want pctxt->sax to be NULL here. */
28796 xmlFree(pctxt->sax);
28797 pctxt->sax = NULL;
28798 }
28799 #if 0
28800 if (options)
28801 xmlCtxtUseOptions(pctxt, options);
28802 #endif
28803
28804 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28805 if (inputStream == NULL) {
28806 ret = -1;
28807 goto done;
28808 }
28809 if (inputPush(pctxt, inputStream) < 0) {
28810 xmlFreeInputStream(inputStream);
28811 ret = -1;
28812 goto done;
28813 }
28814
28815 ctxt->enc = enc;
28816
28817 ret = xmlSchemaValidateStreamInternal(ctxt, pctxt);
28818
28819 done:
28820 /* cleanup */
28821 if (pctxt != NULL) {
28822 xmlFreeParserCtxt(pctxt);
28823 }
28824 return (ret);
28825 }
28826
28827 /**
28828 * xmlSchemaValidateFile:
28829 * @ctxt: a schema validation context
28830 * @filename: the URI of the instance
28831 * @options: a future set of options, currently unused
28832 *
28833 * Do a schemas validation of the given resource, it will use the
28834 * SAX streamable validation internally.
28835 *
28836 * Returns 0 if the document is valid, a positive error code
28837 * number otherwise and -1 in case of an internal or API error.
28838 */
28839 int
xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,const char * filename,int options ATTRIBUTE_UNUSED)28840 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28841 const char * filename,
28842 int options ATTRIBUTE_UNUSED)
28843 {
28844 int ret;
28845 xmlParserCtxtPtr pctxt = NULL;
28846
28847 if ((ctxt == NULL) || (filename == NULL))
28848 return (-1);
28849
28850 pctxt = xmlCreateURLParserCtxt(filename, 0);
28851 if (pctxt == NULL)
28852 return (-1);
28853 /* We really want pctxt->sax to be NULL here. */
28854 xmlFree(pctxt->sax);
28855 pctxt->sax = NULL;
28856 ret = xmlSchemaValidateStreamInternal(ctxt, pctxt);
28857 xmlFreeParserCtxt(pctxt);
28858 return (ret);
28859 }
28860
28861 /**
28862 * xmlSchemaValidCtxtGetParserCtxt:
28863 * @ctxt: a schema validation context
28864 *
28865 * allow access to the parser context of the schema validation context
28866 *
28867 * Returns the parser context of the schema validation context or NULL
28868 * in case of error.
28869 */
28870 xmlParserCtxtPtr
xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)28871 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28872 {
28873 if (ctxt == NULL)
28874 return(NULL);
28875 return (ctxt->parserCtxt);
28876 }
28877
28878 #endif /* LIBXML_SCHEMAS_ENABLED */
28879