1 /*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
10 /*
11 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
15 * - if we don't intend to use the schema for schemas, we
16 * need to validate all schema attributes (ref, type, name)
17 * against their types.
18 * - Eliminate item creation for: ??
19 *
20 * URGENT TODO:
21 * - For xsi-driven schema acquisition, augment the IDCs after every
22 * acquisition episode (xmlSchemaAugmentIDC).
23 *
24 * NOTES:
25 * - Eliminated item creation for: <restriction>, <extension>,
26 * <simpleContent>, <complexContent>, <list>, <union>
27 *
28 * PROBLEMS:
29 * - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30 * IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31 * XPath will have trouble to resolve to this namespace, since not known.
32 *
33 *
34 * CONSTRAINTS:
35 *
36 * Schema Component Constraint:
37 * All Group Limited (cos-all-limited)
38 * Status: complete
39 * (1.2)
40 * In xmlSchemaGroupDefReferenceTermFixup() and
41 * (2)
42 * In xmlSchemaParseModelGroup()
43 * TODO: Actually this should go to component-level checks,
44 * but is done here due to performance. Move it to an other layer
45 * is schema construction via an API is implemented.
46 */
47
48 /* To avoid EBCDIC trouble when parsing on zOS */
49 #if defined(__MVS__)
50 #pragma convert("ISO8859-1")
51 #endif
52
53 #define IN_LIBXML
54 #include "libxml.h"
55
56 #ifdef LIBXML_SCHEMAS_ENABLED
57
58 #include <string.h>
59 #include <libxml/xmlmemory.h>
60 #include <libxml/parser.h>
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 /* #define DEBUG 1 */
80
81 /* #define DEBUG_CONTENT 1 */
82
83 /* #define DEBUG_TYPE 1 */
84
85 /* #define DEBUG_CONTENT_REGEXP 1 */
86
87 /* #define DEBUG_AUTOMATA 1 */
88
89 /* #define DEBUG_IDC */
90
91 /* #define DEBUG_IDC_NODE_TABLE */
92
93 /* #define WXS_ELEM_DECL_CONS_ENABLED */
94
95 #ifdef DEBUG_IDC
96 #ifndef DEBUG_IDC_NODE_TABLE
97 #define DEBUG_IDC_NODE_TABLE
98 #endif
99 #endif
100
101 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
102
103 #define ENABLE_REDEFINE
104
105 /* #define ENABLE_NAMED_LOCALS */
106
107 /* #define ENABLE_IDC_NODE_TABLES_TEST */
108
109 #define DUMP_CONTENT_MODEL
110
111 #ifdef LIBXML_READER_ENABLED
112 /* #define XML_SCHEMA_READER_ENABLED */
113 #endif
114
115 #define UNBOUNDED (1 << 30)
116 #define TODO \
117 xmlGenericError(xmlGenericErrorContext, \
118 "Unimplemented block at %s:%d\n", \
119 __FILE__, __LINE__);
120
121 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
122
123 /*
124 * The XML Schemas namespaces
125 */
126 static const xmlChar *xmlSchemaNs = (const xmlChar *)
127 "http://www.w3.org/2001/XMLSchema";
128
129 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
130 "http://www.w3.org/2001/XMLSchema-instance";
131
132 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
133 "http://www.w3.org/2000/xmlns/";
134
135 /*
136 * Come casting macros.
137 */
138 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
139 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
140 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
141 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
142 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
143 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
144 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
145 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
146 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
147 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
148 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
149 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
150 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
151 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
152 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
153 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
154 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
155
156 /*
157 * Macros to query common properties of components.
158 */
159 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
160
161 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
162 /*
163 * Macros for element declarations.
164 */
165 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
166
167 #define WXS_SUBST_HEAD(item) (item)->refDecl
168 /*
169 * Macros for attribute declarations.
170 */
171 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
172 /*
173 * Macros for attribute uses.
174 */
175 #define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
176
177 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
178
179 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
180
181 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
182 /*
183 * Macros for attribute groups.
184 */
185 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
186 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
187 /*
188 * Macros for particles.
189 */
190 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
191
192 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
193
194 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
195
196 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
197 /*
198 * Macros for model groups definitions.
199 */
200 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
201 /*
202 * Macros for model groups.
203 */
204 #define WXS_IS_MODEL_GROUP(i) \
205 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
206 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
207 ((i)->type == XML_SCHEMA_TYPE_ALL))
208
209 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
210 /*
211 * Macros for schema buckets.
212 */
213 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
214 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
215
216 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
217 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
218
219 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
220
221 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
222 /*
223 * Macros for complex/simple types.
224 */
225 #define WXS_IS_ANYTYPE(i) \
226 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
227 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
228
229 #define WXS_IS_COMPLEX(i) \
230 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
231 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
232
233 #define WXS_IS_SIMPLE(item) \
234 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
235 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
236 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
237
238 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
239 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
240 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
241
242 #define WXS_IS_RESTRICTION(t) \
243 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
244
245 #define WXS_IS_EXTENSION(t) \
246 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
247
248 #define WXS_IS_TYPE_NOT_FIXED(i) \
249 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
250 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
251
252 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
253 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
254 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
255
256 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
257
258 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
259 /*
260 * Macros for exclusively for complex types.
261 */
262 #define WXS_HAS_COMPLEX_CONTENT(item) \
263 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
264 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
265 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
266
267 #define WXS_HAS_SIMPLE_CONTENT(item) \
268 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
269 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
270
271 #define WXS_HAS_MIXED_CONTENT(item) \
272 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
273
274 #define WXS_EMPTIABLE(t) \
275 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
276
277 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
278
279 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
280
281 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
282 /*
283 * Macros for exclusively for simple types.
284 */
285 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
286
287 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
288
289 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
290
291 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
292 /*
293 * Misc parser context macros.
294 */
295 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
296
297 #define WXS_HAS_BUCKETS(ctx) \
298 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
299 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
300
301 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
302
303 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
304
305 #define WXS_SCHEMA(ctx) (ctx)->schema
306
307 #define WXS_ADD_LOCAL(ctx, item) \
308 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
309
310 #define WXS_ADD_GLOBAL(ctx, item) \
311 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
312
313 #define WXS_ADD_PENDING(ctx, item) \
314 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
315 /*
316 * xmlSchemaItemList macros.
317 */
318 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
319 /*
320 * Misc macros.
321 */
322 #define IS_SCHEMA(node, type) \
323 ((node != NULL) && (node->ns != NULL) && \
324 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
325 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
326
327 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
328
329 /*
330 * Since we put the default/fixed values into the dict, we can
331 * use pointer comparison for those values.
332 * REMOVED: (xmlStrEqual((v1), (v2)))
333 */
334 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
335
336 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
337
338 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
339
340 #define HFAILURE if (res == -1) goto exit_failure;
341
342 #define HERROR if (res != 0) goto exit_error;
343
344 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
345 /*
346 * Some flags used for various schema constraints.
347 */
348 #define SUBSET_RESTRICTION 1<<0
349 #define SUBSET_EXTENSION 1<<1
350 #define SUBSET_SUBSTITUTION 1<<2
351 #define SUBSET_LIST 1<<3
352 #define SUBSET_UNION 1<<4
353
354 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
355 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
356
357 typedef struct _xmlSchemaItemList xmlSchemaItemList;
358 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
359 struct _xmlSchemaItemList {
360 void **items; /* used for dynamic addition of schemata */
361 int nbItems; /* used for dynamic addition of schemata */
362 int sizeItems; /* used for dynamic addition of schemata */
363 };
364
365 #define XML_SCHEMA_CTXT_PARSER 1
366 #define XML_SCHEMA_CTXT_VALIDATOR 2
367
368 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
369 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
370 struct _xmlSchemaAbstractCtxt {
371 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
372 void *dummy; /* Fix alignment issues */
373 };
374
375 typedef struct _xmlSchemaBucket xmlSchemaBucket;
376 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
377
378 #define XML_SCHEMA_SCHEMA_MAIN 0
379 #define XML_SCHEMA_SCHEMA_IMPORT 1
380 #define XML_SCHEMA_SCHEMA_INCLUDE 2
381 #define XML_SCHEMA_SCHEMA_REDEFINE 3
382
383 /**
384 * xmlSchemaSchemaRelation:
385 *
386 * Used to create a graph of schema relationships.
387 */
388 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
389 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
390 struct _xmlSchemaSchemaRelation {
391 xmlSchemaSchemaRelationPtr next;
392 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
393 const xmlChar *importNamespace;
394 xmlSchemaBucketPtr bucket;
395 };
396
397 #define XML_SCHEMA_BUCKET_MARKED 1<<0
398 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
399
400 struct _xmlSchemaBucket {
401 int type;
402 int flags;
403 const xmlChar *schemaLocation;
404 const xmlChar *origTargetNamespace;
405 const xmlChar *targetNamespace;
406 xmlDocPtr doc;
407 xmlSchemaSchemaRelationPtr relations;
408 int located;
409 int parsed;
410 int imported;
411 int preserveDoc;
412 xmlSchemaItemListPtr globals; /* Global components. */
413 xmlSchemaItemListPtr locals; /* Local components. */
414 };
415
416 /**
417 * xmlSchemaImport:
418 * (extends xmlSchemaBucket)
419 *
420 * Reflects a schema. Holds some information
421 * about the schema and its toplevel components. Duplicate
422 * toplevel components are not checked at this level.
423 */
424 typedef struct _xmlSchemaImport xmlSchemaImport;
425 typedef xmlSchemaImport *xmlSchemaImportPtr;
426 struct _xmlSchemaImport {
427 int type; /* Main OR import OR include. */
428 int flags;
429 const xmlChar *schemaLocation; /* The URI of the schema document. */
430 /* For chameleon includes, @origTargetNamespace will be NULL */
431 const xmlChar *origTargetNamespace;
432 /*
433 * For chameleon includes, @targetNamespace will be the
434 * targetNamespace of the including schema.
435 */
436 const xmlChar *targetNamespace;
437 xmlDocPtr doc; /* The schema node-tree. */
438 /* @relations will hold any included/imported/redefined schemas. */
439 xmlSchemaSchemaRelationPtr relations;
440 int located;
441 int parsed;
442 int imported;
443 int preserveDoc;
444 xmlSchemaItemListPtr globals;
445 xmlSchemaItemListPtr locals;
446 /* The imported schema. */
447 xmlSchemaPtr schema;
448 };
449
450 /*
451 * (extends xmlSchemaBucket)
452 */
453 typedef struct _xmlSchemaInclude xmlSchemaInclude;
454 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
455 struct _xmlSchemaInclude {
456 int type;
457 int flags;
458 const xmlChar *schemaLocation;
459 const xmlChar *origTargetNamespace;
460 const xmlChar *targetNamespace;
461 xmlDocPtr doc;
462 xmlSchemaSchemaRelationPtr relations;
463 int located;
464 int parsed;
465 int imported;
466 int preserveDoc;
467 xmlSchemaItemListPtr globals; /* Global components. */
468 xmlSchemaItemListPtr locals; /* Local components. */
469
470 /* The owning main or import schema bucket. */
471 xmlSchemaImportPtr ownerImport;
472 };
473
474 /**
475 * xmlSchemaBasicItem:
476 *
477 * The abstract base type for schema components.
478 */
479 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
480 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
481 struct _xmlSchemaBasicItem {
482 xmlSchemaTypeType type;
483 void *dummy; /* Fix alignment issues */
484 };
485
486 /**
487 * xmlSchemaAnnotItem:
488 *
489 * The abstract base type for annotated schema components.
490 * (Extends xmlSchemaBasicItem)
491 */
492 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
493 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
494 struct _xmlSchemaAnnotItem {
495 xmlSchemaTypeType type;
496 xmlSchemaAnnotPtr annot;
497 };
498
499 /**
500 * xmlSchemaTreeItem:
501 *
502 * The abstract base type for tree-like structured schema components.
503 * (Extends xmlSchemaAnnotItem)
504 */
505 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
506 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
507 struct _xmlSchemaTreeItem {
508 xmlSchemaTypeType type;
509 xmlSchemaAnnotPtr annot;
510 xmlSchemaTreeItemPtr next;
511 xmlSchemaTreeItemPtr children;
512 };
513
514
515 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
516 /**
517 * xmlSchemaAttributeUsePtr:
518 *
519 * The abstract base type for tree-like structured schema components.
520 * (Extends xmlSchemaTreeItem)
521 */
522 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
523 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
524 struct _xmlSchemaAttributeUse {
525 xmlSchemaTypeType type;
526 xmlSchemaAnnotPtr annot;
527 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
528 /*
529 * The attr. decl. OR a QName-ref. to an attr. decl. OR
530 * a QName-ref. to an attribute group definition.
531 */
532 xmlSchemaAttributePtr attrDecl;
533
534 int flags;
535 xmlNodePtr node;
536 int occurs; /* required, optional */
537 const xmlChar * defValue;
538 xmlSchemaValPtr defVal;
539 };
540
541 /**
542 * xmlSchemaAttributeUseProhibPtr:
543 *
544 * A helper component to reflect attribute prohibitions.
545 * (Extends xmlSchemaBasicItem)
546 */
547 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
548 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
549 struct _xmlSchemaAttributeUseProhib {
550 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
551 xmlNodePtr node;
552 const xmlChar *name;
553 const xmlChar *targetNamespace;
554 int isRef;
555 };
556
557 /**
558 * xmlSchemaRedef:
559 */
560 typedef struct _xmlSchemaRedef xmlSchemaRedef;
561 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
562 struct _xmlSchemaRedef {
563 xmlSchemaRedefPtr next;
564 xmlSchemaBasicItemPtr item; /* The redefining component. */
565 xmlSchemaBasicItemPtr reference; /* The referencing component. */
566 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
567 const xmlChar *refName; /* The name of the to-be-redefined component. */
568 const xmlChar *refTargetNs; /* The target namespace of the
569 to-be-redefined comp. */
570 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
571 };
572
573 /**
574 * xmlSchemaConstructionCtxt:
575 */
576 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
577 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
578 struct _xmlSchemaConstructionCtxt {
579 xmlSchemaPtr mainSchema; /* The main schema. */
580 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
581 xmlDictPtr dict;
582 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
583 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
584 xmlSchemaBucketPtr bucket; /* The current schema bucket */
585 xmlSchemaItemListPtr pending; /* All Components of all schemas that
586 need to be fixed. */
587 xmlHashTablePtr substGroups;
588 xmlSchemaRedefPtr redefs;
589 xmlSchemaRedefPtr lastRedef;
590 };
591
592 #define XML_SCHEMAS_PARSE_ERROR 1
593 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
594
595 struct _xmlSchemaParserCtxt {
596 int type;
597 void *errCtxt; /* user specific error context */
598 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
599 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
600 int err;
601 int nberrors;
602 xmlStructuredErrorFunc serror;
603
604 xmlSchemaConstructionCtxtPtr constructor;
605 int ownsConstructor; /* TODO: Move this to parser *flags*. */
606
607 /* xmlSchemaPtr topschema; */
608 /* xmlHashTablePtr namespaces; */
609
610 xmlSchemaPtr schema; /* The main schema in use */
611 int counter;
612
613 const xmlChar *URL;
614 xmlDocPtr doc;
615 int preserve; /* Whether the doc should be freed */
616
617 const char *buffer;
618 int size;
619
620 /*
621 * Used to build complex element content models
622 */
623 xmlAutomataPtr am;
624 xmlAutomataStatePtr start;
625 xmlAutomataStatePtr end;
626 xmlAutomataStatePtr state;
627
628 xmlDictPtr dict; /* dictionary for interned string names */
629 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
630 int options;
631 xmlSchemaValidCtxtPtr vctxt;
632 int isS4S;
633 int isRedefine;
634 int xsiAssemble;
635 int stop; /* If the parser should stop; i.e. a critical error. */
636 const xmlChar *targetNamespace;
637 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
638
639 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
640 int redefCounter; /* Used for redefinitions. */
641 xmlSchemaItemListPtr attrProhibs;
642 };
643
644 /**
645 * xmlSchemaQNameRef:
646 *
647 * A component reference item (not a schema component)
648 * (Extends xmlSchemaBasicItem)
649 */
650 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
651 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
652 struct _xmlSchemaQNameRef {
653 xmlSchemaTypeType type;
654 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
655 xmlSchemaTypeType itemType;
656 const xmlChar *name;
657 const xmlChar *targetNamespace;
658 xmlNodePtr node;
659 };
660
661 /**
662 * xmlSchemaParticle:
663 *
664 * A particle component.
665 * (Extends xmlSchemaTreeItem)
666 */
667 typedef struct _xmlSchemaParticle xmlSchemaParticle;
668 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
669 struct _xmlSchemaParticle {
670 xmlSchemaTypeType type;
671 xmlSchemaAnnotPtr annot;
672 xmlSchemaTreeItemPtr next; /* next particle */
673 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
674 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
675 etc.) */
676 int minOccurs;
677 int maxOccurs;
678 xmlNodePtr node;
679 };
680
681 /**
682 * xmlSchemaModelGroup:
683 *
684 * A model group component.
685 * (Extends xmlSchemaTreeItem)
686 */
687 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
688 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
689 struct _xmlSchemaModelGroup {
690 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
691 xmlSchemaAnnotPtr annot;
692 xmlSchemaTreeItemPtr next; /* not used */
693 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
694 xmlNodePtr node;
695 };
696
697 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
698 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
699 /**
700 * xmlSchemaModelGroupDef:
701 *
702 * A model group definition component.
703 * (Extends xmlSchemaTreeItem)
704 */
705 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
706 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
707 struct _xmlSchemaModelGroupDef {
708 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
709 xmlSchemaAnnotPtr annot;
710 xmlSchemaTreeItemPtr next; /* not used */
711 xmlSchemaTreeItemPtr children; /* the "model group" */
712 const xmlChar *name;
713 const xmlChar *targetNamespace;
714 xmlNodePtr node;
715 int flags;
716 };
717
718 typedef struct _xmlSchemaIDC xmlSchemaIDC;
719 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
720
721 /**
722 * xmlSchemaIDCSelect:
723 *
724 * The identity-constraint "field" and "selector" item, holding the
725 * XPath expression.
726 */
727 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
728 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
729 struct _xmlSchemaIDCSelect {
730 xmlSchemaIDCSelectPtr next;
731 xmlSchemaIDCPtr idc;
732 int index; /* an index position if significant for IDC key-sequences */
733 const xmlChar *xpath; /* the XPath expression */
734 void *xpathComp; /* the compiled XPath expression */
735 };
736
737 /**
738 * xmlSchemaIDC:
739 *
740 * The identity-constraint definition component.
741 * (Extends xmlSchemaAnnotItem)
742 */
743
744 struct _xmlSchemaIDC {
745 xmlSchemaTypeType type;
746 xmlSchemaAnnotPtr annot;
747 xmlSchemaIDCPtr next;
748 xmlNodePtr node;
749 const xmlChar *name;
750 const xmlChar *targetNamespace;
751 xmlSchemaIDCSelectPtr selector;
752 xmlSchemaIDCSelectPtr fields;
753 int nbFields;
754 xmlSchemaQNameRefPtr ref;
755 };
756
757 /**
758 * xmlSchemaIDCAug:
759 *
760 * The augmented IDC information used for validation.
761 */
762 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
763 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
764 struct _xmlSchemaIDCAug {
765 xmlSchemaIDCAugPtr next; /* next in a list */
766 xmlSchemaIDCPtr def; /* the IDC definition */
767 int keyrefDepth; /* the lowest tree level to which IDC
768 tables need to be bubbled upwards */
769 };
770
771 /**
772 * xmlSchemaPSVIIDCKeySequence:
773 *
774 * The key sequence of a node table item.
775 */
776 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
777 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
778 struct _xmlSchemaPSVIIDCKey {
779 xmlSchemaTypePtr type;
780 xmlSchemaValPtr val;
781 };
782
783 /**
784 * xmlSchemaPSVIIDCNode:
785 *
786 * The node table item of a node table.
787 */
788 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
789 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
790 struct _xmlSchemaPSVIIDCNode {
791 xmlNodePtr node;
792 xmlSchemaPSVIIDCKeyPtr *keys;
793 int nodeLine;
794 int nodeQNameID;
795
796 };
797
798 /**
799 * xmlSchemaPSVIIDCBinding:
800 *
801 * The identity-constraint binding item of the [identity-constraint table].
802 */
803 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
804 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
805 struct _xmlSchemaPSVIIDCBinding {
806 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
807 xmlSchemaIDCPtr definition; /* the IDC definition */
808 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
809 int nbNodes; /* number of entries in the node table */
810 int sizeNodes; /* size of the node table */
811 xmlSchemaItemListPtr dupls;
812 };
813
814
815 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
816 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
817
818 #define XPATH_STATE_OBJ_MATCHES -2
819 #define XPATH_STATE_OBJ_BLOCKED -3
820
821 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
822 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
823
824 /**
825 * xmlSchemaIDCStateObj:
826 *
827 * The state object used to evaluate XPath expressions.
828 */
829 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
830 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
831 struct _xmlSchemaIDCStateObj {
832 int type;
833 xmlSchemaIDCStateObjPtr next; /* next if in a list */
834 int depth; /* depth of creation */
835 int *history; /* list of (depth, state-id) tuples */
836 int nbHistory;
837 int sizeHistory;
838 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
839 matcher */
840 xmlSchemaIDCSelectPtr sel;
841 void *xpathCtxt;
842 };
843
844 #define IDC_MATCHER 0
845
846 /**
847 * xmlSchemaIDCMatcher:
848 *
849 * Used to evaluate IDC selectors (and fields).
850 */
851 struct _xmlSchemaIDCMatcher {
852 int type;
853 int depth; /* the tree depth at creation time */
854 xmlSchemaIDCMatcherPtr next; /* next in the list */
855 xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
856 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
857 int idcType;
858 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
859 elements */
860 int sizeKeySeqs;
861 xmlSchemaItemListPtr targets; /* list of target-node
862 (xmlSchemaPSVIIDCNodePtr) entries */
863 xmlHashTablePtr htab;
864 };
865
866 /*
867 * Element info flags.
868 */
869 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
870 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
871 #define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
872 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
873
874 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
875 #define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
876 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
877
878 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
879 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
880 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
881 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
882
883 /**
884 * xmlSchemaNodeInfo:
885 *
886 * Holds information of an element node.
887 */
888 struct _xmlSchemaNodeInfo {
889 int nodeType;
890 xmlNodePtr node;
891 int nodeLine;
892 const xmlChar *localName;
893 const xmlChar *nsName;
894 const xmlChar *value;
895 xmlSchemaValPtr val; /* the pre-computed value if any */
896 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
897
898 int flags; /* combination of node info flags */
899
900 int valNeeded;
901 int normVal;
902
903 xmlSchemaElementPtr decl; /* the element/attribute declaration */
904 int depth;
905 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
906 for the scope element*/
907 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
908 element */
909 xmlRegExecCtxtPtr regexCtxt;
910
911 const xmlChar **nsBindings; /* Namespace bindings on this element */
912 int nbNsBindings;
913 int sizeNsBindings;
914
915 int hasKeyrefs;
916 int appliedXPath; /* Indicates that an XPath has been applied. */
917 };
918
919 #define XML_SCHEMAS_ATTR_UNKNOWN 1
920 #define XML_SCHEMAS_ATTR_ASSESSED 2
921 #define XML_SCHEMAS_ATTR_PROHIBITED 3
922 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
923 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
924 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
925 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
926 #define XML_SCHEMAS_ATTR_DEFAULT 8
927 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
928 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
929 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
930 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
931 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
932 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
933 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
934 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
935 #define XML_SCHEMAS_ATTR_META 17
936 /*
937 * @metaType values of xmlSchemaAttrInfo.
938 */
939 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
940 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
941 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
942 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
943 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
944
945 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
946 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
947 struct _xmlSchemaAttrInfo {
948 int nodeType;
949 xmlNodePtr node;
950 int nodeLine;
951 const xmlChar *localName;
952 const xmlChar *nsName;
953 const xmlChar *value;
954 xmlSchemaValPtr val; /* the pre-computed value if any */
955 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
956 int flags; /* combination of node info flags */
957
958 xmlSchemaAttributePtr decl; /* the attribute declaration */
959 xmlSchemaAttributeUsePtr use; /* the attribute use */
960 int state;
961 int metaType;
962 const xmlChar *vcValue; /* the value constraint value */
963 xmlSchemaNodeInfoPtr parent;
964 };
965
966
967 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
968 /**
969 * xmlSchemaValidCtxt:
970 *
971 * A Schemas validation context
972 */
973 struct _xmlSchemaValidCtxt {
974 int type;
975 void *errCtxt; /* user specific data block */
976 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
977 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
978 xmlStructuredErrorFunc serror;
979
980 xmlSchemaPtr schema; /* The schema in use */
981 xmlDocPtr doc;
982 xmlParserInputBufferPtr input;
983 xmlCharEncoding enc;
984 xmlSAXHandlerPtr sax;
985 xmlParserCtxtPtr parserCtxt;
986 void *user_data; /* TODO: What is this for? */
987 char *filename;
988
989 int err;
990 int nberrors;
991
992 xmlNodePtr node;
993 xmlNodePtr cur;
994 /* xmlSchemaTypePtr type; */
995
996 xmlRegExecCtxtPtr regexp;
997 xmlSchemaValPtr value;
998
999 int valueWS;
1000 int options;
1001 xmlNodePtr validationRoot;
1002 xmlSchemaParserCtxtPtr pctxt;
1003 int xsiAssemble;
1004
1005 int depth;
1006 xmlSchemaNodeInfoPtr *elemInfos; /* array of element information */
1007 int sizeElemInfos;
1008 xmlSchemaNodeInfoPtr inode; /* the current element information */
1009
1010 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC information */
1011
1012 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1013 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1014 xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1015
1016 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1017 int nbIdcNodes;
1018 int sizeIdcNodes;
1019
1020 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1021 int nbIdcKeys;
1022 int sizeIdcKeys;
1023
1024 int flags;
1025
1026 xmlDictPtr dict;
1027
1028 #ifdef LIBXML_READER_ENABLED
1029 xmlTextReaderPtr reader;
1030 #endif
1031
1032 xmlSchemaAttrInfoPtr *attrInfos;
1033 int nbAttrInfos;
1034 int sizeAttrInfos;
1035
1036 int skipDepth;
1037 xmlSchemaItemListPtr nodeQNames;
1038 int hasKeyrefs;
1039 int createIDCNodeTables;
1040 int psviExposeIDCNodeTables;
1041
1042 /* Locator for error reporting in streaming mode */
1043 xmlSchemaValidityLocatorFunc locFunc;
1044 void *locCtxt;
1045 };
1046
1047 /**
1048 * xmlSchemaSubstGroup:
1049 *
1050 *
1051 */
1052 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1053 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1054 struct _xmlSchemaSubstGroup {
1055 xmlSchemaElementPtr head;
1056 xmlSchemaItemListPtr members;
1057 };
1058
1059 /**
1060 * xmlIDCHashEntry:
1061 *
1062 * an entry in hash tables to quickly look up keys/uniques
1063 */
1064 typedef struct _xmlIDCHashEntry xmlIDCHashEntry;
1065 typedef xmlIDCHashEntry *xmlIDCHashEntryPtr;
1066 struct _xmlIDCHashEntry {
1067 xmlIDCHashEntryPtr next; /* next item with same hash */
1068 int index; /* index into associated item list */
1069 };
1070
1071 /************************************************************************
1072 * *
1073 * Some predeclarations *
1074 * *
1075 ************************************************************************/
1076
1077 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1078 xmlSchemaPtr schema,
1079 xmlNodePtr node);
1080 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1081 xmlSchemaPtr schema,
1082 xmlNodePtr node);
1083 static int
1084 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1085 xmlSchemaAbstractCtxtPtr ctxt);
1086 static const xmlChar *
1087 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1088 static int
1089 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1090 xmlNodePtr node);
1091 static int
1092 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1093 xmlSchemaParserCtxtPtr ctxt);
1094 static void
1095 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1096 static xmlSchemaWhitespaceValueType
1097 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1098 static xmlSchemaTreeItemPtr
1099 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1100 xmlNodePtr node, xmlSchemaTypeType type,
1101 int withParticle);
1102 static const xmlChar *
1103 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1104 static xmlSchemaTypeLinkPtr
1105 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1106 static void
1107 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1108 const char *funcName,
1109 const char *message) LIBXML_ATTR_FORMAT(3,0);
1110 static int
1111 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1112 xmlSchemaTypePtr type,
1113 xmlSchemaTypePtr baseType,
1114 int subset);
1115 static void
1116 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1117 xmlSchemaParserCtxtPtr ctxt);
1118 static void
1119 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1120 static xmlSchemaQNameRefPtr
1121 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1122 xmlSchemaPtr schema,
1123 xmlNodePtr node);
1124
1125 /************************************************************************
1126 * *
1127 * Helper functions *
1128 * *
1129 ************************************************************************/
1130
1131 /**
1132 * xmlSchemaItemTypeToStr:
1133 * @type: the type of the schema item
1134 *
1135 * Returns the component name of a schema item.
1136 */
1137 static const xmlChar *
xmlSchemaItemTypeToStr(xmlSchemaTypeType type)1138 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1139 {
1140 switch (type) {
1141 case XML_SCHEMA_TYPE_BASIC:
1142 return(BAD_CAST "simple type definition");
1143 case XML_SCHEMA_TYPE_SIMPLE:
1144 return(BAD_CAST "simple type definition");
1145 case XML_SCHEMA_TYPE_COMPLEX:
1146 return(BAD_CAST "complex type definition");
1147 case XML_SCHEMA_TYPE_ELEMENT:
1148 return(BAD_CAST "element declaration");
1149 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1150 return(BAD_CAST "attribute use");
1151 case XML_SCHEMA_TYPE_ATTRIBUTE:
1152 return(BAD_CAST "attribute declaration");
1153 case XML_SCHEMA_TYPE_GROUP:
1154 return(BAD_CAST "model group definition");
1155 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1156 return(BAD_CAST "attribute group definition");
1157 case XML_SCHEMA_TYPE_NOTATION:
1158 return(BAD_CAST "notation declaration");
1159 case XML_SCHEMA_TYPE_SEQUENCE:
1160 return(BAD_CAST "model group (sequence)");
1161 case XML_SCHEMA_TYPE_CHOICE:
1162 return(BAD_CAST "model group (choice)");
1163 case XML_SCHEMA_TYPE_ALL:
1164 return(BAD_CAST "model group (all)");
1165 case XML_SCHEMA_TYPE_PARTICLE:
1166 return(BAD_CAST "particle");
1167 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1168 return(BAD_CAST "unique identity-constraint");
1169 /* return(BAD_CAST "IDC (unique)"); */
1170 case XML_SCHEMA_TYPE_IDC_KEY:
1171 return(BAD_CAST "key identity-constraint");
1172 /* return(BAD_CAST "IDC (key)"); */
1173 case XML_SCHEMA_TYPE_IDC_KEYREF:
1174 return(BAD_CAST "keyref identity-constraint");
1175 /* return(BAD_CAST "IDC (keyref)"); */
1176 case XML_SCHEMA_TYPE_ANY:
1177 return(BAD_CAST "wildcard (any)");
1178 case XML_SCHEMA_EXTRA_QNAMEREF:
1179 return(BAD_CAST "[helper component] QName reference");
1180 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1181 return(BAD_CAST "[helper component] attribute use prohibition");
1182 default:
1183 return(BAD_CAST "Not a schema component");
1184 }
1185 }
1186
1187 /**
1188 * xmlSchemaGetComponentTypeStr:
1189 * @type: the type of the schema item
1190 *
1191 * Returns the component name of a schema item.
1192 */
1193 static const xmlChar *
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)1194 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1195 {
1196 switch (item->type) {
1197 case XML_SCHEMA_TYPE_BASIC:
1198 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1199 return(BAD_CAST "complex type definition");
1200 else
1201 return(BAD_CAST "simple type definition");
1202 default:
1203 return(xmlSchemaItemTypeToStr(item->type));
1204 }
1205 }
1206
1207 /**
1208 * xmlSchemaGetComponentNode:
1209 * @item: a schema component
1210 *
1211 * Returns node associated with the schema component.
1212 * NOTE that such a node need not be available; plus, a component's
1213 * node need not to reflect the component directly, since there is no
1214 * one-to-one relationship between the XML Schema representation and
1215 * the component representation.
1216 */
1217 static xmlNodePtr
xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)1218 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1219 {
1220 switch (item->type) {
1221 case XML_SCHEMA_TYPE_ELEMENT:
1222 return (((xmlSchemaElementPtr) item)->node);
1223 case XML_SCHEMA_TYPE_ATTRIBUTE:
1224 return (((xmlSchemaAttributePtr) item)->node);
1225 case XML_SCHEMA_TYPE_COMPLEX:
1226 case XML_SCHEMA_TYPE_SIMPLE:
1227 return (((xmlSchemaTypePtr) item)->node);
1228 case XML_SCHEMA_TYPE_ANY:
1229 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1230 return (((xmlSchemaWildcardPtr) item)->node);
1231 case XML_SCHEMA_TYPE_PARTICLE:
1232 return (((xmlSchemaParticlePtr) item)->node);
1233 case XML_SCHEMA_TYPE_SEQUENCE:
1234 case XML_SCHEMA_TYPE_CHOICE:
1235 case XML_SCHEMA_TYPE_ALL:
1236 return (((xmlSchemaModelGroupPtr) item)->node);
1237 case XML_SCHEMA_TYPE_GROUP:
1238 return (((xmlSchemaModelGroupDefPtr) item)->node);
1239 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1240 return (((xmlSchemaAttributeGroupPtr) item)->node);
1241 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1242 case XML_SCHEMA_TYPE_IDC_KEY:
1243 case XML_SCHEMA_TYPE_IDC_KEYREF:
1244 return (((xmlSchemaIDCPtr) item)->node);
1245 case XML_SCHEMA_EXTRA_QNAMEREF:
1246 return(((xmlSchemaQNameRefPtr) item)->node);
1247 /* TODO: What to do with NOTATIONs?
1248 case XML_SCHEMA_TYPE_NOTATION:
1249 return (((xmlSchemaNotationPtr) item)->node);
1250 */
1251 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1252 return (((xmlSchemaAttributeUsePtr) item)->node);
1253 default:
1254 return (NULL);
1255 }
1256 }
1257
1258 #if 0
1259 /**
1260 * xmlSchemaGetNextComponent:
1261 * @item: a schema component
1262 *
1263 * Returns the next sibling of the schema component.
1264 */
1265 static xmlSchemaBasicItemPtr
1266 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1267 {
1268 switch (item->type) {
1269 case XML_SCHEMA_TYPE_ELEMENT:
1270 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1271 case XML_SCHEMA_TYPE_ATTRIBUTE:
1272 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1273 case XML_SCHEMA_TYPE_COMPLEX:
1274 case XML_SCHEMA_TYPE_SIMPLE:
1275 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1276 case XML_SCHEMA_TYPE_ANY:
1277 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1278 return (NULL);
1279 case XML_SCHEMA_TYPE_PARTICLE:
1280 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1281 case XML_SCHEMA_TYPE_SEQUENCE:
1282 case XML_SCHEMA_TYPE_CHOICE:
1283 case XML_SCHEMA_TYPE_ALL:
1284 return (NULL);
1285 case XML_SCHEMA_TYPE_GROUP:
1286 return (NULL);
1287 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1288 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1289 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1290 case XML_SCHEMA_TYPE_IDC_KEY:
1291 case XML_SCHEMA_TYPE_IDC_KEYREF:
1292 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1293 default:
1294 return (NULL);
1295 }
1296 }
1297 #endif
1298
1299
1300 /**
1301 * xmlSchemaFormatQName:
1302 * @buf: the string buffer
1303 * @namespaceName: the namespace name
1304 * @localName: the local name
1305 *
1306 * Returns the given QName in the format "{namespaceName}localName" or
1307 * just "localName" if @namespaceName is NULL.
1308 *
1309 * Returns the localName if @namespaceName is NULL, a formatted
1310 * string otherwise.
1311 */
1312 static const xmlChar*
xmlSchemaFormatQName(xmlChar ** buf,const xmlChar * namespaceName,const xmlChar * localName)1313 xmlSchemaFormatQName(xmlChar **buf,
1314 const xmlChar *namespaceName,
1315 const xmlChar *localName)
1316 {
1317 FREE_AND_NULL(*buf)
1318 if (namespaceName != NULL) {
1319 *buf = xmlStrdup(BAD_CAST "{");
1320 *buf = xmlStrcat(*buf, namespaceName);
1321 *buf = xmlStrcat(*buf, BAD_CAST "}");
1322 }
1323 if (localName != NULL) {
1324 if (namespaceName == NULL)
1325 return(localName);
1326 *buf = xmlStrcat(*buf, localName);
1327 } else {
1328 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1329 }
1330 return ((const xmlChar *) *buf);
1331 }
1332
1333 static const xmlChar*
xmlSchemaFormatQNameNs(xmlChar ** buf,xmlNsPtr ns,const xmlChar * localName)1334 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1335 {
1336 if (ns != NULL)
1337 return (xmlSchemaFormatQName(buf, ns->href, localName));
1338 else
1339 return (xmlSchemaFormatQName(buf, NULL, localName));
1340 }
1341
1342 static const xmlChar *
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)1343 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1344 {
1345 if (item == NULL) {
1346 return (NULL);
1347 }
1348 switch (item->type) {
1349 case XML_SCHEMA_TYPE_ELEMENT:
1350 return (((xmlSchemaElementPtr) item)->name);
1351 case XML_SCHEMA_TYPE_ATTRIBUTE:
1352 return (((xmlSchemaAttributePtr) item)->name);
1353 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1354 return (((xmlSchemaAttributeGroupPtr) item)->name);
1355 case XML_SCHEMA_TYPE_BASIC:
1356 case XML_SCHEMA_TYPE_SIMPLE:
1357 case XML_SCHEMA_TYPE_COMPLEX:
1358 return (((xmlSchemaTypePtr) item)->name);
1359 case XML_SCHEMA_TYPE_GROUP:
1360 return (((xmlSchemaModelGroupDefPtr) item)->name);
1361 case XML_SCHEMA_TYPE_IDC_KEY:
1362 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1363 case XML_SCHEMA_TYPE_IDC_KEYREF:
1364 return (((xmlSchemaIDCPtr) item)->name);
1365 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1366 if (WXS_ATTRUSE_DECL(item) != NULL) {
1367 return(xmlSchemaGetComponentName(
1368 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1369 } else
1370 return(NULL);
1371 case XML_SCHEMA_EXTRA_QNAMEREF:
1372 return (((xmlSchemaQNameRefPtr) item)->name);
1373 case XML_SCHEMA_TYPE_NOTATION:
1374 return (((xmlSchemaNotationPtr) item)->name);
1375 default:
1376 /*
1377 * Other components cannot have names.
1378 */
1379 break;
1380 }
1381 return (NULL);
1382 }
1383
1384 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1385 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1386 /*
1387 static const xmlChar *
1388 xmlSchemaGetQNameRefName(void *ref)
1389 {
1390 return(((xmlSchemaQNameRefPtr) ref)->name);
1391 }
1392
1393 static const xmlChar *
1394 xmlSchemaGetQNameRefTargetNs(void *ref)
1395 {
1396 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1397 }
1398 */
1399
1400 static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)1401 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1402 {
1403 if (item == NULL) {
1404 return (NULL);
1405 }
1406 switch (item->type) {
1407 case XML_SCHEMA_TYPE_ELEMENT:
1408 return (((xmlSchemaElementPtr) item)->targetNamespace);
1409 case XML_SCHEMA_TYPE_ATTRIBUTE:
1410 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1411 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1412 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1413 case XML_SCHEMA_TYPE_BASIC:
1414 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1415 case XML_SCHEMA_TYPE_SIMPLE:
1416 case XML_SCHEMA_TYPE_COMPLEX:
1417 return (((xmlSchemaTypePtr) item)->targetNamespace);
1418 case XML_SCHEMA_TYPE_GROUP:
1419 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1420 case XML_SCHEMA_TYPE_IDC_KEY:
1421 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1422 case XML_SCHEMA_TYPE_IDC_KEYREF:
1423 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1424 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1425 if (WXS_ATTRUSE_DECL(item) != NULL) {
1426 return(xmlSchemaGetComponentTargetNs(
1427 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1428 }
1429 /* TODO: Will returning NULL break something? */
1430 break;
1431 case XML_SCHEMA_EXTRA_QNAMEREF:
1432 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1433 case XML_SCHEMA_TYPE_NOTATION:
1434 return (((xmlSchemaNotationPtr) item)->targetNamespace);
1435 default:
1436 /*
1437 * Other components cannot have names.
1438 */
1439 break;
1440 }
1441 return (NULL);
1442 }
1443
1444 static const xmlChar*
xmlSchemaGetComponentQName(xmlChar ** buf,void * item)1445 xmlSchemaGetComponentQName(xmlChar **buf,
1446 void *item)
1447 {
1448 return (xmlSchemaFormatQName(buf,
1449 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1450 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1451 }
1452
1453 static const xmlChar*
xmlSchemaGetComponentDesignation(xmlChar ** buf,void * item)1454 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1455 {
1456 xmlChar *str = NULL;
1457
1458 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1459 *buf = xmlStrcat(*buf, BAD_CAST " '");
1460 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1461 (xmlSchemaBasicItemPtr) item));
1462 *buf = xmlStrcat(*buf, BAD_CAST "'");
1463 FREE_AND_NULL(str);
1464 return(*buf);
1465 }
1466
1467 static const xmlChar*
xmlSchemaGetIDCDesignation(xmlChar ** buf,xmlSchemaIDCPtr idc)1468 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1469 {
1470 return(xmlSchemaGetComponentDesignation(buf, idc));
1471 }
1472
1473 /**
1474 * xmlSchemaWildcardPCToString:
1475 * @pc: the type of processContents
1476 *
1477 * Returns a string representation of the type of
1478 * processContents.
1479 */
1480 static const xmlChar *
xmlSchemaWildcardPCToString(int pc)1481 xmlSchemaWildcardPCToString(int pc)
1482 {
1483 switch (pc) {
1484 case XML_SCHEMAS_ANY_SKIP:
1485 return (BAD_CAST "skip");
1486 case XML_SCHEMAS_ANY_LAX:
1487 return (BAD_CAST "lax");
1488 case XML_SCHEMAS_ANY_STRICT:
1489 return (BAD_CAST "strict");
1490 default:
1491 return (BAD_CAST "invalid process contents");
1492 }
1493 }
1494
1495 /**
1496 * xmlSchemaGetCanonValueWhtspExt:
1497 * @val: the precomputed value
1498 * @retValue: the returned value
1499 * @ws: the whitespace type of the value
1500 * @for_hash: non-zero if this is supposed to generate a string for hashing
1501 *
1502 * Get a the canonical representation of the value.
1503 * The caller has to free the returned retValue.
1504 *
1505 * Returns 0 if the value could be built and -1 in case of
1506 * API errors or if the value type is not supported yet.
1507 */
1508 static int
xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue,int for_hash)1509 xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
1510 xmlSchemaWhitespaceValueType ws,
1511 xmlChar **retValue,
1512 int for_hash)
1513 {
1514 int list;
1515 xmlSchemaValType valType;
1516 const xmlChar *value, *value2 = NULL;
1517
1518
1519 if ((retValue == NULL) || (val == NULL))
1520 return (-1);
1521 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1522 *retValue = NULL;
1523 do {
1524 value = NULL;
1525 valType = xmlSchemaGetValType(val);
1526 switch (valType) {
1527 case XML_SCHEMAS_STRING:
1528 case XML_SCHEMAS_NORMSTRING:
1529 case XML_SCHEMAS_ANYSIMPLETYPE:
1530 value = xmlSchemaValueGetAsString(val);
1531 if (value != NULL) {
1532 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1533 value2 = xmlSchemaCollapseString(value);
1534 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1535 value2 = xmlSchemaWhiteSpaceReplace(value);
1536 if (value2 != NULL)
1537 value = value2;
1538 }
1539 break;
1540 default:
1541 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1542 if (value2 != NULL)
1543 xmlFree((xmlChar *) value2);
1544 goto internal_error;
1545 }
1546 if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
1547 /* We can mostly use the canonical value for hashing,
1548 except in the case of decimal. There the canonical
1549 representation requires a trailing '.0' even for
1550 non-fractional numbers, but for the derived integer
1551 types it forbids any decimal point. Nevertheless they
1552 compare equal if the value is equal. We need to generate
1553 the same hash value for this to work, and it's easiest
1554 to just cut off the useless '.0' suffix for the
1555 decimal type. */
1556 int len = xmlStrlen(value2);
1557 if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
1558 ((xmlChar*)value2)[len-2] = 0;
1559 }
1560 value = value2;
1561 }
1562 if (*retValue == NULL)
1563 if (value == NULL) {
1564 if (! list)
1565 *retValue = xmlStrdup(BAD_CAST "");
1566 } else
1567 *retValue = xmlStrdup(value);
1568 else if (value != NULL) {
1569 /* List. */
1570 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1571 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1572 }
1573 FREE_AND_NULL(value2)
1574 val = xmlSchemaValueGetNext(val);
1575 } while (val != NULL);
1576
1577 return (0);
1578 internal_error:
1579 if (*retValue != NULL)
1580 xmlFree((xmlChar *) (*retValue));
1581 if (value2 != NULL)
1582 xmlFree((xmlChar *) value2);
1583 return (-1);
1584 }
1585
1586 static int
xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue)1587 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1588 xmlSchemaWhitespaceValueType ws,
1589 xmlChar **retValue)
1590 {
1591 return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
1592 }
1593
1594 static int
xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,xmlChar ** retValue)1595 xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
1596 xmlChar **retValue)
1597 {
1598 return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
1599 retValue, 1);
1600 }
1601
1602 /**
1603 * xmlSchemaFormatItemForReport:
1604 * @buf: the string buffer
1605 * @itemDes: the designation of the item
1606 * @itemName: the name of the item
1607 * @item: the item as an object
1608 * @itemNode: the node of the item
1609 * @local: the local name
1610 * @parsing: if the function is used during the parse
1611 *
1612 * Returns a representation of the given item used
1613 * for error reports.
1614 *
1615 * The following order is used to build the resulting
1616 * designation if the arguments are not NULL:
1617 * 1a. If itemDes not NULL -> itemDes
1618 * 1b. If (itemDes not NULL) and (itemName not NULL)
1619 * -> itemDes + itemName
1620 * 2. If the preceding was NULL and (item not NULL) -> item
1621 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1622 *
1623 * If the itemNode is an attribute node, the name of the attribute
1624 * will be appended to the result.
1625 *
1626 * Returns the formatted string and sets @buf to the resulting value.
1627 */
1628 static xmlChar*
xmlSchemaFormatItemForReport(xmlChar ** buf,const xmlChar * itemDes,xmlSchemaBasicItemPtr item,xmlNodePtr itemNode)1629 xmlSchemaFormatItemForReport(xmlChar **buf,
1630 const xmlChar *itemDes,
1631 xmlSchemaBasicItemPtr item,
1632 xmlNodePtr itemNode)
1633 {
1634 xmlChar *str = NULL;
1635 int named = 1;
1636
1637 if (*buf != NULL) {
1638 xmlFree(*buf);
1639 *buf = NULL;
1640 }
1641
1642 if (itemDes != NULL) {
1643 *buf = xmlStrdup(itemDes);
1644 } else if (item != NULL) {
1645 switch (item->type) {
1646 case XML_SCHEMA_TYPE_BASIC: {
1647 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1648
1649 if (WXS_IS_ATOMIC(type))
1650 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1651 else if (WXS_IS_LIST(type))
1652 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1653 else if (WXS_IS_UNION(type))
1654 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1655 else
1656 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1657 *buf = xmlStrcat(*buf, type->name);
1658 *buf = xmlStrcat(*buf, BAD_CAST "'");
1659 }
1660 break;
1661 case XML_SCHEMA_TYPE_SIMPLE: {
1662 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1663
1664 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1665 *buf = xmlStrdup(BAD_CAST"");
1666 } else {
1667 *buf = xmlStrdup(BAD_CAST "local ");
1668 }
1669 if (WXS_IS_ATOMIC(type))
1670 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1671 else if (WXS_IS_LIST(type))
1672 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1673 else if (WXS_IS_UNION(type))
1674 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1675 else
1676 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1677 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1678 *buf = xmlStrcat(*buf, BAD_CAST " '");
1679 *buf = xmlStrcat(*buf, type->name);
1680 *buf = xmlStrcat(*buf, BAD_CAST "'");
1681 }
1682 }
1683 break;
1684 case XML_SCHEMA_TYPE_COMPLEX: {
1685 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1686
1687 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1688 *buf = xmlStrdup(BAD_CAST "");
1689 else
1690 *buf = xmlStrdup(BAD_CAST "local ");
1691 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1692 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1693 *buf = xmlStrcat(*buf, BAD_CAST " '");
1694 *buf = xmlStrcat(*buf, type->name);
1695 *buf = xmlStrcat(*buf, BAD_CAST "'");
1696 }
1697 }
1698 break;
1699 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1700 xmlSchemaAttributeUsePtr ause;
1701
1702 ause = WXS_ATTR_USE_CAST item;
1703 *buf = xmlStrdup(BAD_CAST "attribute use ");
1704 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1705 *buf = xmlStrcat(*buf, BAD_CAST "'");
1706 *buf = xmlStrcat(*buf,
1707 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1708 FREE_AND_NULL(str)
1709 *buf = xmlStrcat(*buf, BAD_CAST "'");
1710 } else {
1711 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1712 }
1713 }
1714 break;
1715 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1716 xmlSchemaAttributePtr attr;
1717
1718 attr = (xmlSchemaAttributePtr) item;
1719 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1720 *buf = xmlStrcat(*buf, BAD_CAST " '");
1721 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1722 attr->targetNamespace, attr->name));
1723 FREE_AND_NULL(str)
1724 *buf = xmlStrcat(*buf, BAD_CAST "'");
1725 }
1726 break;
1727 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1728 xmlSchemaGetComponentDesignation(buf, item);
1729 break;
1730 case XML_SCHEMA_TYPE_ELEMENT: {
1731 xmlSchemaElementPtr elem;
1732
1733 elem = (xmlSchemaElementPtr) item;
1734 *buf = xmlStrdup(BAD_CAST "element decl.");
1735 *buf = xmlStrcat(*buf, BAD_CAST " '");
1736 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1737 elem->targetNamespace, elem->name));
1738 *buf = xmlStrcat(*buf, BAD_CAST "'");
1739 }
1740 break;
1741 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1742 case XML_SCHEMA_TYPE_IDC_KEY:
1743 case XML_SCHEMA_TYPE_IDC_KEYREF:
1744 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1745 *buf = xmlStrdup(BAD_CAST "unique '");
1746 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1747 *buf = xmlStrdup(BAD_CAST "key '");
1748 else
1749 *buf = xmlStrdup(BAD_CAST "keyRef '");
1750 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1751 *buf = xmlStrcat(*buf, BAD_CAST "'");
1752 break;
1753 case XML_SCHEMA_TYPE_ANY:
1754 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1755 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1756 ((xmlSchemaWildcardPtr) item)->processContents));
1757 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1758 break;
1759 case XML_SCHEMA_FACET_MININCLUSIVE:
1760 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1761 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1762 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1763 case XML_SCHEMA_FACET_TOTALDIGITS:
1764 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1765 case XML_SCHEMA_FACET_PATTERN:
1766 case XML_SCHEMA_FACET_ENUMERATION:
1767 case XML_SCHEMA_FACET_WHITESPACE:
1768 case XML_SCHEMA_FACET_LENGTH:
1769 case XML_SCHEMA_FACET_MAXLENGTH:
1770 case XML_SCHEMA_FACET_MINLENGTH:
1771 *buf = xmlStrdup(BAD_CAST "facet '");
1772 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1773 *buf = xmlStrcat(*buf, BAD_CAST "'");
1774 break;
1775 case XML_SCHEMA_TYPE_GROUP: {
1776 *buf = xmlStrdup(BAD_CAST "model group def.");
1777 *buf = xmlStrcat(*buf, BAD_CAST " '");
1778 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1779 *buf = xmlStrcat(*buf, BAD_CAST "'");
1780 FREE_AND_NULL(str)
1781 }
1782 break;
1783 case XML_SCHEMA_TYPE_SEQUENCE:
1784 case XML_SCHEMA_TYPE_CHOICE:
1785 case XML_SCHEMA_TYPE_ALL:
1786 case XML_SCHEMA_TYPE_PARTICLE:
1787 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1788 break;
1789 case XML_SCHEMA_TYPE_NOTATION: {
1790 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1791 *buf = xmlStrcat(*buf, BAD_CAST " '");
1792 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1793 *buf = xmlStrcat(*buf, BAD_CAST "'");
1794 FREE_AND_NULL(str);
1795 }
1796 /* Falls through. */
1797 default:
1798 named = 0;
1799 }
1800 } else
1801 named = 0;
1802
1803 if ((named == 0) && (itemNode != NULL)) {
1804 xmlNodePtr elem;
1805
1806 if (itemNode->type == XML_ATTRIBUTE_NODE)
1807 elem = itemNode->parent;
1808 else
1809 elem = itemNode;
1810 *buf = xmlStrdup(BAD_CAST "Element '");
1811 if (elem->ns != NULL) {
1812 *buf = xmlStrcat(*buf,
1813 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1814 FREE_AND_NULL(str)
1815 } else
1816 *buf = xmlStrcat(*buf, elem->name);
1817 *buf = xmlStrcat(*buf, BAD_CAST "'");
1818
1819 }
1820 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1821 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1822 if (itemNode->ns != NULL) {
1823 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1824 itemNode->ns->href, itemNode->name));
1825 FREE_AND_NULL(str)
1826 } else
1827 *buf = xmlStrcat(*buf, itemNode->name);
1828 *buf = xmlStrcat(*buf, BAD_CAST "'");
1829 }
1830 FREE_AND_NULL(str)
1831
1832 return (xmlEscapeFormatString(buf));
1833 }
1834
1835 /**
1836 * xmlSchemaFormatFacetEnumSet:
1837 * @buf: the string buffer
1838 * @type: the type holding the enumeration facets
1839 *
1840 * Builds a string consisting of all enumeration elements.
1841 *
1842 * Returns a string of all enumeration elements.
1843 */
1844 static const xmlChar *
xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,xmlChar ** buf,xmlSchemaTypePtr type)1845 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1846 xmlChar **buf, xmlSchemaTypePtr type)
1847 {
1848 xmlSchemaFacetPtr facet;
1849 xmlSchemaWhitespaceValueType ws;
1850 xmlChar *value = NULL;
1851 int res, found = 0;
1852
1853 if (*buf != NULL)
1854 xmlFree(*buf);
1855 *buf = NULL;
1856
1857 do {
1858 /*
1859 * Use the whitespace type of the base type.
1860 */
1861 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1862 for (facet = type->facets; facet != NULL; facet = facet->next) {
1863 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1864 continue;
1865 found = 1;
1866 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1867 ws, &value);
1868 if (res == -1) {
1869 xmlSchemaInternalErr(actxt,
1870 "xmlSchemaFormatFacetEnumSet",
1871 "compute the canonical lexical representation");
1872 if (*buf != NULL)
1873 xmlFree(*buf);
1874 *buf = NULL;
1875 return (NULL);
1876 }
1877 if (*buf == NULL)
1878 *buf = xmlStrdup(BAD_CAST "'");
1879 else
1880 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1881 *buf = xmlStrcat(*buf, BAD_CAST value);
1882 *buf = xmlStrcat(*buf, BAD_CAST "'");
1883 if (value != NULL) {
1884 xmlFree((xmlChar *)value);
1885 value = NULL;
1886 }
1887 }
1888 /*
1889 * The enumeration facet of a type restricts the enumeration
1890 * facet of the ancestor type; i.e., such restricted enumerations
1891 * do not belong to the set of the given type. Thus we break
1892 * on the first found enumeration.
1893 */
1894 if (found)
1895 break;
1896 type = type->baseType;
1897 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1898
1899 return ((const xmlChar *) *buf);
1900 }
1901
1902 /************************************************************************
1903 * *
1904 * Error functions *
1905 * *
1906 ************************************************************************/
1907
1908 #if 0
1909 static void
1910 xmlSchemaErrMemory(const char *msg)
1911 {
1912 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1913 msg);
1914 }
1915 #endif
1916
1917 static void
xmlSchemaPSimpleErr(const char * msg)1918 xmlSchemaPSimpleErr(const char *msg)
1919 {
1920 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1921 msg);
1922 }
1923
1924 /**
1925 * xmlSchemaPErrMemory:
1926 * @node: a context node
1927 * @extra: extra information
1928 *
1929 * Handle an out of memory condition
1930 */
1931 static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,const char * extra,xmlNodePtr node)1932 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1933 const char *extra, xmlNodePtr node)
1934 {
1935 if (ctxt != NULL)
1936 ctxt->nberrors++;
1937 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1938 extra);
1939 }
1940
1941 /**
1942 * xmlSchemaPErr:
1943 * @ctxt: the parsing context
1944 * @node: the context node
1945 * @error: the error code
1946 * @msg: the error message
1947 * @str1: extra data
1948 * @str2: extra data
1949 *
1950 * Handle a parser error
1951 */
1952 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)1953 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1954 const char *msg, const xmlChar * str1, const xmlChar * str2)
1955 {
1956 xmlGenericErrorFunc channel = NULL;
1957 xmlStructuredErrorFunc schannel = NULL;
1958 void *data = NULL;
1959
1960 if (ctxt != NULL) {
1961 ctxt->nberrors++;
1962 ctxt->err = error;
1963 channel = ctxt->error;
1964 data = ctxt->errCtxt;
1965 schannel = ctxt->serror;
1966 }
1967 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1968 error, XML_ERR_ERROR, NULL, 0,
1969 (const char *) str1, (const char *) str2, NULL, 0, 0,
1970 msg, str1, str2);
1971 }
1972
1973 /**
1974 * xmlSchemaPErr2:
1975 * @ctxt: the parsing context
1976 * @node: the context node
1977 * @node: the current child
1978 * @error: the error code
1979 * @msg: the error message
1980 * @str1: extra data
1981 * @str2: extra data
1982 *
1983 * Handle a parser error
1984 */
1985 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)1986 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1987 xmlNodePtr child, int error,
1988 const char *msg, const xmlChar * str1, const xmlChar * str2)
1989 {
1990 if (child != NULL)
1991 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1992 else
1993 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1994 }
1995
1996
1997 /**
1998 * xmlSchemaPErrExt:
1999 * @ctxt: the parsing context
2000 * @node: the context node
2001 * @error: the error code
2002 * @strData1: extra data
2003 * @strData2: extra data
2004 * @strData3: extra data
2005 * @msg: the message
2006 * @str1: extra parameter for the message display
2007 * @str2: extra parameter for the message display
2008 * @str3: extra parameter for the message display
2009 * @str4: extra parameter for the message display
2010 * @str5: extra parameter for the message display
2011 *
2012 * Handle a parser error
2013 */
2014 static void LIBXML_ATTR_FORMAT(7,0)
xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,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)2015 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
2016 const xmlChar * strData1, const xmlChar * strData2,
2017 const xmlChar * strData3, const char *msg, const xmlChar * str1,
2018 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
2019 const xmlChar * str5)
2020 {
2021
2022 xmlGenericErrorFunc channel = NULL;
2023 xmlStructuredErrorFunc schannel = NULL;
2024 void *data = NULL;
2025
2026 if (ctxt != NULL) {
2027 ctxt->nberrors++;
2028 ctxt->err = error;
2029 channel = ctxt->error;
2030 data = ctxt->errCtxt;
2031 schannel = ctxt->serror;
2032 }
2033 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
2034 error, XML_ERR_ERROR, NULL, 0,
2035 (const char *) strData1, (const char *) strData2,
2036 (const char *) strData3, 0, 0, msg, str1, str2,
2037 str3, str4, str5);
2038 }
2039
2040 /************************************************************************
2041 * *
2042 * Allround error functions *
2043 * *
2044 ************************************************************************/
2045
2046 /**
2047 * xmlSchemaVTypeErrMemory:
2048 * @node: a context node
2049 * @extra: extra information
2050 *
2051 * Handle an out of memory condition
2052 */
2053 static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,const char * extra,xmlNodePtr node)2054 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2055 const char *extra, xmlNodePtr node)
2056 {
2057 if (ctxt != NULL) {
2058 ctxt->nberrors++;
2059 ctxt->err = XML_SCHEMAV_INTERNAL;
2060 }
2061 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2062 extra);
2063 }
2064
2065 static void LIBXML_ATTR_FORMAT(2,0)
xmlSchemaPSimpleInternalErr(xmlNodePtr node,const char * msg,const xmlChar * str)2066 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2067 const char *msg, const xmlChar *str)
2068 {
2069 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2070 msg, (const char *) str);
2071 }
2072
2073 #define WXS_ERROR_TYPE_ERROR 1
2074 #define WXS_ERROR_TYPE_WARNING 2
2075 /**
2076 * xmlSchemaErr4Line:
2077 * @ctxt: the validation context
2078 * @errorLevel: the error level
2079 * @error: the error code
2080 * @node: the context node
2081 * @line: the line number
2082 * @msg: the error message
2083 * @str1: extra data
2084 * @str2: extra data
2085 * @str3: extra data
2086 * @str4: extra data
2087 *
2088 * Handle a validation error
2089 */
2090 static void LIBXML_ATTR_FORMAT(6,0)
xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,xmlErrorLevel errorLevel,int error,xmlNodePtr node,int line,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2091 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2092 xmlErrorLevel errorLevel,
2093 int error, xmlNodePtr node, int line, const char *msg,
2094 const xmlChar *str1, const xmlChar *str2,
2095 const xmlChar *str3, const xmlChar *str4)
2096 {
2097 xmlStructuredErrorFunc schannel = NULL;
2098 xmlGenericErrorFunc channel = NULL;
2099 void *data = NULL;
2100
2101 if (ctxt != NULL) {
2102 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2103 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2104 const char *file = NULL;
2105 int col = 0;
2106 if (errorLevel != XML_ERR_WARNING) {
2107 vctxt->nberrors++;
2108 vctxt->err = error;
2109 channel = vctxt->error;
2110 } else {
2111 channel = vctxt->warning;
2112 }
2113 schannel = vctxt->serror;
2114 data = vctxt->errCtxt;
2115
2116 /*
2117 * Error node. If we specify a line number, then
2118 * do not channel any node to the error function.
2119 */
2120 if (line == 0) {
2121 if ((node == NULL) &&
2122 (vctxt->depth >= 0) &&
2123 (vctxt->inode != NULL)) {
2124 node = vctxt->inode->node;
2125 }
2126 /*
2127 * Get filename and line if no node-tree.
2128 */
2129 if ((node == NULL) &&
2130 (vctxt->parserCtxt != NULL) &&
2131 (vctxt->parserCtxt->input != NULL)) {
2132 file = vctxt->parserCtxt->input->filename;
2133 line = vctxt->parserCtxt->input->line;
2134 col = vctxt->parserCtxt->input->col;
2135 }
2136 } else {
2137 /*
2138 * Override the given node's (if any) position
2139 * and channel only the given line number.
2140 */
2141 node = NULL;
2142 /*
2143 * Get filename.
2144 */
2145 if (vctxt->doc != NULL)
2146 file = (const char *) vctxt->doc->URL;
2147 else if ((vctxt->parserCtxt != NULL) &&
2148 (vctxt->parserCtxt->input != NULL))
2149 file = vctxt->parserCtxt->input->filename;
2150 }
2151 if (vctxt->locFunc != NULL) {
2152 if ((file == NULL) || (line == 0)) {
2153 unsigned long l;
2154 const char *f;
2155 vctxt->locFunc(vctxt->locCtxt, &f, &l);
2156 if (file == NULL)
2157 file = f;
2158 if (line == 0)
2159 line = (int) l;
2160 }
2161 }
2162 if ((file == NULL) && (vctxt->filename != NULL))
2163 file = vctxt->filename;
2164
2165 __xmlRaiseError(schannel, channel, data, ctxt,
2166 node, XML_FROM_SCHEMASV,
2167 error, errorLevel, file, line,
2168 (const char *) str1, (const char *) str2,
2169 (const char *) str3, 0, col, msg, str1, str2, str3, str4);
2170
2171 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2172 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2173 if (errorLevel != XML_ERR_WARNING) {
2174 pctxt->nberrors++;
2175 pctxt->err = error;
2176 channel = pctxt->error;
2177 } else {
2178 channel = pctxt->warning;
2179 }
2180 schannel = pctxt->serror;
2181 data = pctxt->errCtxt;
2182 __xmlRaiseError(schannel, channel, data, ctxt,
2183 node, XML_FROM_SCHEMASP, error,
2184 errorLevel, NULL, 0,
2185 (const char *) str1, (const char *) str2,
2186 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2187 } else {
2188 TODO
2189 }
2190 }
2191 }
2192
2193 /**
2194 * xmlSchemaErr3:
2195 * @ctxt: the validation context
2196 * @node: the context node
2197 * @error: the error code
2198 * @msg: the error message
2199 * @str1: extra data
2200 * @str2: extra data
2201 * @str3: extra data
2202 *
2203 * Handle a validation error
2204 */
2205 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)2206 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2207 int error, xmlNodePtr node, const char *msg,
2208 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2209 {
2210 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2211 msg, str1, str2, str3, NULL);
2212 }
2213
2214 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)2215 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2216 int error, xmlNodePtr node, const char *msg,
2217 const xmlChar *str1, const xmlChar *str2,
2218 const xmlChar *str3, const xmlChar *str4)
2219 {
2220 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2221 msg, str1, str2, str3, str4);
2222 }
2223
2224 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2)2225 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2226 int error, xmlNodePtr node, const char *msg,
2227 const xmlChar *str1, const xmlChar *str2)
2228 {
2229 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2230 }
2231
2232 static xmlChar *
xmlSchemaFormatNodeForError(xmlChar ** msg,xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2233 xmlSchemaFormatNodeForError(xmlChar ** msg,
2234 xmlSchemaAbstractCtxtPtr actxt,
2235 xmlNodePtr node)
2236 {
2237 xmlChar *str = NULL;
2238
2239 *msg = NULL;
2240 if ((node != NULL) &&
2241 (node->type != XML_ELEMENT_NODE) &&
2242 (node->type != XML_ATTRIBUTE_NODE))
2243 {
2244 /*
2245 * Don't try to format other nodes than element and
2246 * attribute nodes.
2247 * Play safe and return an empty string.
2248 */
2249 *msg = xmlStrdup(BAD_CAST "");
2250 return(*msg);
2251 }
2252 if (node != NULL) {
2253 /*
2254 * Work on tree nodes.
2255 */
2256 if (node->type == XML_ATTRIBUTE_NODE) {
2257 xmlNodePtr elem = node->parent;
2258
2259 *msg = xmlStrdup(BAD_CAST "Element '");
2260 if (elem->ns != NULL)
2261 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2262 elem->ns->href, elem->name));
2263 else
2264 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2265 NULL, elem->name));
2266 FREE_AND_NULL(str);
2267 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2268 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2269 } else {
2270 *msg = xmlStrdup(BAD_CAST "Element '");
2271 }
2272 if (node->ns != NULL)
2273 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2274 node->ns->href, node->name));
2275 else
2276 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2277 NULL, node->name));
2278 FREE_AND_NULL(str);
2279 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2280 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2281 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2282 /*
2283 * Work on node infos.
2284 */
2285 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2286 xmlSchemaNodeInfoPtr ielem =
2287 vctxt->elemInfos[vctxt->depth];
2288
2289 *msg = xmlStrdup(BAD_CAST "Element '");
2290 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2291 ielem->nsName, ielem->localName));
2292 FREE_AND_NULL(str);
2293 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2294 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2295 } else {
2296 *msg = xmlStrdup(BAD_CAST "Element '");
2297 }
2298 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2299 vctxt->inode->nsName, vctxt->inode->localName));
2300 FREE_AND_NULL(str);
2301 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2302 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2303 /*
2304 * Hmm, no node while parsing?
2305 * Return an empty string, in case NULL will break something.
2306 */
2307 *msg = xmlStrdup(BAD_CAST "");
2308 } else {
2309 TODO
2310 return (NULL);
2311 }
2312
2313 /*
2314 * xmlSchemaFormatItemForReport() also returns an escaped format
2315 * string, so do this before calling it below (in the future).
2316 */
2317 xmlEscapeFormatString(msg);
2318
2319 /*
2320 * VAL TODO: The output of the given schema component is currently
2321 * disabled.
2322 */
2323 #if 0
2324 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2325 *msg = xmlStrcat(*msg, BAD_CAST " [");
2326 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2327 NULL, type, NULL, 0));
2328 FREE_AND_NULL(str)
2329 *msg = xmlStrcat(*msg, BAD_CAST "]");
2330 }
2331 #endif
2332 return (*msg);
2333 }
2334
2335 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message,const xmlChar * str1,const xmlChar * str2)2336 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2337 const char *funcName,
2338 const char *message,
2339 const xmlChar *str1,
2340 const xmlChar *str2)
2341 {
2342 xmlChar *msg = NULL;
2343
2344 if (actxt == NULL)
2345 return;
2346 msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2347 msg = xmlStrcat(msg, BAD_CAST message);
2348 msg = xmlStrcat(msg, BAD_CAST ".\n");
2349
2350 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2351 xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2352 (const char *) msg, (const xmlChar *) funcName, str1, str2);
2353 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2354 xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2355 (const char *) msg, (const xmlChar *) funcName, str1, str2);
2356
2357 FREE_AND_NULL(msg)
2358 }
2359
2360 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message)2361 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2362 const char *funcName,
2363 const char *message)
2364 {
2365 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2366 }
2367
2368 #if 0
2369 static void LIBXML_ATTR_FORMAT(3,0)
2370 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2371 const char *funcName,
2372 const char *message,
2373 const xmlChar *str1,
2374 const xmlChar *str2)
2375 {
2376 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2377 str1, str2);
2378 }
2379 #endif
2380
2381 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)2382 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2383 xmlParserErrors error,
2384 xmlNodePtr node,
2385 xmlSchemaBasicItemPtr item,
2386 const char *message,
2387 const xmlChar *str1, const xmlChar *str2,
2388 const xmlChar *str3, const xmlChar *str4)
2389 {
2390 xmlChar *msg = NULL;
2391
2392 if ((node == NULL) && (item != NULL) &&
2393 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2394 node = WXS_ITEM_NODE(item);
2395 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2396 msg = xmlStrcat(msg, BAD_CAST ": ");
2397 } else
2398 xmlSchemaFormatNodeForError(&msg, actxt, node);
2399 msg = xmlStrcat(msg, (const xmlChar *) message);
2400 msg = xmlStrcat(msg, BAD_CAST ".\n");
2401 xmlSchemaErr4(actxt, error, node,
2402 (const char *) msg, str1, str2, str3, str4);
2403 FREE_AND_NULL(msg)
2404 }
2405
2406 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)2407 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2408 xmlParserErrors error,
2409 xmlNodePtr node,
2410 xmlSchemaBasicItemPtr item,
2411 const char *message,
2412 const xmlChar *str1,
2413 const xmlChar *str2)
2414 {
2415 xmlSchemaCustomErr4(actxt, error, node, item,
2416 message, str1, str2, NULL, NULL);
2417 }
2418
2419
2420
2421 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)2422 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2423 xmlParserErrors error,
2424 xmlNodePtr node,
2425 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2426 const char *message,
2427 const xmlChar *str1,
2428 const xmlChar *str2,
2429 const xmlChar *str3)
2430 {
2431 xmlChar *msg = NULL;
2432
2433 xmlSchemaFormatNodeForError(&msg, actxt, node);
2434 msg = xmlStrcat(msg, (const xmlChar *) message);
2435 msg = xmlStrcat(msg, BAD_CAST ".\n");
2436
2437 /* URGENT TODO: Set the error code to something sane. */
2438 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2439 (const char *) msg, str1, str2, str3, NULL);
2440
2441 FREE_AND_NULL(msg)
2442 }
2443
2444
2445
2446 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)2447 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2448 xmlParserErrors error,
2449 xmlSchemaPSVIIDCNodePtr idcNode,
2450 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2451 const char *message,
2452 const xmlChar *str1,
2453 const xmlChar *str2)
2454 {
2455 xmlChar *msg = NULL, *qname = NULL;
2456
2457 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2458 msg = xmlStrcat(msg, (const xmlChar *) message);
2459 msg = xmlStrcat(msg, BAD_CAST ".\n");
2460 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2461 error, NULL, idcNode->nodeLine, (const char *) msg,
2462 xmlSchemaFormatQName(&qname,
2463 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2464 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2465 str1, str2, NULL);
2466 FREE_AND_NULL(qname);
2467 FREE_AND_NULL(msg);
2468 }
2469
2470 static int
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2471 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2472 xmlNodePtr node)
2473 {
2474 if (node != NULL)
2475 return (node->type);
2476 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2477 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2478 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2479 return (-1);
2480 }
2481
2482 static int
xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)2483 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2484 {
2485 switch (item->type) {
2486 case XML_SCHEMA_TYPE_COMPLEX:
2487 case XML_SCHEMA_TYPE_SIMPLE:
2488 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2489 return(1);
2490 break;
2491 case XML_SCHEMA_TYPE_GROUP:
2492 return (1);
2493 case XML_SCHEMA_TYPE_ELEMENT:
2494 if ( ((xmlSchemaElementPtr) item)->flags &
2495 XML_SCHEMAS_ELEM_GLOBAL)
2496 return(1);
2497 break;
2498 case XML_SCHEMA_TYPE_ATTRIBUTE:
2499 if ( ((xmlSchemaAttributePtr) item)->flags &
2500 XML_SCHEMAS_ATTR_GLOBAL)
2501 return(1);
2502 break;
2503 /* Note that attribute groups are always global. */
2504 default:
2505 return(1);
2506 }
2507 return (0);
2508 }
2509
2510 static void
xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,xmlSchemaTypePtr type,int displayValue)2511 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2512 xmlParserErrors error,
2513 xmlNodePtr node,
2514 const xmlChar *value,
2515 xmlSchemaTypePtr type,
2516 int displayValue)
2517 {
2518 xmlChar *msg = NULL;
2519
2520 xmlSchemaFormatNodeForError(&msg, actxt, node);
2521
2522 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2523 XML_ATTRIBUTE_NODE))
2524 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2525 else
2526 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2527 "value of ");
2528
2529 if (! xmlSchemaIsGlobalItem(type))
2530 msg = xmlStrcat(msg, BAD_CAST "the local ");
2531 else
2532 msg = xmlStrcat(msg, BAD_CAST "the ");
2533
2534 if (WXS_IS_ATOMIC(type))
2535 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2536 else if (WXS_IS_LIST(type))
2537 msg = xmlStrcat(msg, BAD_CAST "list type");
2538 else if (WXS_IS_UNION(type))
2539 msg = xmlStrcat(msg, BAD_CAST "union type");
2540
2541 if (xmlSchemaIsGlobalItem(type)) {
2542 xmlChar *str = NULL;
2543 msg = xmlStrcat(msg, BAD_CAST " '");
2544 if (type->builtInType != 0) {
2545 msg = xmlStrcat(msg, BAD_CAST "xs:");
2546 str = xmlStrdup(type->name);
2547 } else {
2548 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2549 if (!str)
2550 str = xmlStrdup(qName);
2551 }
2552 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2553 msg = xmlStrcat(msg, BAD_CAST "'");
2554 FREE_AND_NULL(str);
2555 }
2556 msg = xmlStrcat(msg, BAD_CAST ".\n");
2557 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2558 XML_ATTRIBUTE_NODE))
2559 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2560 else
2561 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2562 FREE_AND_NULL(msg)
2563 }
2564
2565 static const xmlChar *
xmlSchemaFormatErrorNodeQName(xmlChar ** str,xmlSchemaNodeInfoPtr ni,xmlNodePtr node)2566 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2567 xmlSchemaNodeInfoPtr ni,
2568 xmlNodePtr node)
2569 {
2570 if (node != NULL) {
2571 if (node->ns != NULL)
2572 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2573 else
2574 return (xmlSchemaFormatQName(str, NULL, node->name));
2575 } else if (ni != NULL)
2576 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2577 return (NULL);
2578 }
2579
2580 static void
xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlSchemaAttrInfoPtr ni,xmlNodePtr node)2581 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2582 xmlParserErrors error,
2583 xmlSchemaAttrInfoPtr ni,
2584 xmlNodePtr node)
2585 {
2586 xmlChar *msg = NULL, *str = NULL;
2587
2588 xmlSchemaFormatNodeForError(&msg, actxt, node);
2589 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2590 xmlSchemaErr(actxt, error, node, (const char *) msg,
2591 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2592 NULL);
2593 FREE_AND_NULL(str)
2594 FREE_AND_NULL(msg)
2595 }
2596
2597 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)2598 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2599 xmlParserErrors error,
2600 xmlNodePtr node,
2601 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2602 const char *message,
2603 int nbval,
2604 int nbneg,
2605 xmlChar **values)
2606 {
2607 xmlChar *str = NULL, *msg = NULL;
2608 xmlChar *localName, *nsName;
2609 const xmlChar *cur, *end;
2610 int i;
2611
2612 xmlSchemaFormatNodeForError(&msg, actxt, node);
2613 msg = xmlStrcat(msg, (const xmlChar *) message);
2614 msg = xmlStrcat(msg, BAD_CAST ".");
2615 /*
2616 * Note that is does not make sense to report that we have a
2617 * wildcard here, since the wildcard might be unfolded into
2618 * multiple transitions.
2619 */
2620 if (nbval + nbneg > 0) {
2621 if (nbval + nbneg > 1) {
2622 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2623 } else
2624 str = xmlStrdup(BAD_CAST " Expected is ( ");
2625 nsName = NULL;
2626
2627 for (i = 0; i < nbval + nbneg; i++) {
2628 cur = values[i];
2629 if (cur == NULL)
2630 continue;
2631 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2632 (cur[3] == ' ')) {
2633 cur += 4;
2634 str = xmlStrcat(str, BAD_CAST "##other");
2635 }
2636 /*
2637 * Get the local name.
2638 */
2639 localName = NULL;
2640
2641 end = cur;
2642 if (*end == '*') {
2643 localName = xmlStrdup(BAD_CAST "*");
2644 end++;
2645 } else {
2646 while ((*end != 0) && (*end != '|'))
2647 end++;
2648 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2649 }
2650 if (*end != 0) {
2651 end++;
2652 /*
2653 * Skip "*|*" if they come with negated expressions, since
2654 * they represent the same negated wildcard.
2655 */
2656 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2657 /*
2658 * Get the namespace name.
2659 */
2660 cur = end;
2661 if (*end == '*') {
2662 nsName = xmlStrdup(BAD_CAST "{*}");
2663 } else {
2664 while (*end != 0)
2665 end++;
2666
2667 if (i >= nbval)
2668 nsName = xmlStrdup(BAD_CAST "{##other:");
2669 else
2670 nsName = xmlStrdup(BAD_CAST "{");
2671
2672 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2673 nsName = xmlStrcat(nsName, BAD_CAST "}");
2674 }
2675 str = xmlStrcat(str, BAD_CAST nsName);
2676 FREE_AND_NULL(nsName)
2677 } else {
2678 FREE_AND_NULL(localName);
2679 continue;
2680 }
2681 }
2682 str = xmlStrcat(str, BAD_CAST localName);
2683 FREE_AND_NULL(localName);
2684
2685 if (i < nbval + nbneg -1)
2686 str = xmlStrcat(str, BAD_CAST ", ");
2687 }
2688 str = xmlStrcat(str, BAD_CAST " ).\n");
2689 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2690 FREE_AND_NULL(str)
2691 } else
2692 msg = xmlStrcat(msg, BAD_CAST "\n");
2693 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2694 xmlFree(msg);
2695 }
2696
2697 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)2698 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2699 xmlParserErrors error,
2700 xmlNodePtr node,
2701 const xmlChar *value,
2702 unsigned long length,
2703 xmlSchemaTypePtr type,
2704 xmlSchemaFacetPtr facet,
2705 const char *message,
2706 const xmlChar *str1,
2707 const xmlChar *str2)
2708 {
2709 xmlChar *str = NULL, *msg = NULL;
2710 xmlSchemaTypeType facetType;
2711 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2712
2713 xmlSchemaFormatNodeForError(&msg, actxt, node);
2714 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2715 facetType = XML_SCHEMA_FACET_ENUMERATION;
2716 /*
2717 * If enumerations are validated, one must not expect the
2718 * facet to be given.
2719 */
2720 } else
2721 facetType = facet->type;
2722 msg = xmlStrcat(msg, BAD_CAST "[");
2723 msg = xmlStrcat(msg, BAD_CAST "facet '");
2724 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2725 msg = xmlStrcat(msg, BAD_CAST "'] ");
2726 if (message == NULL) {
2727 /*
2728 * Use a default message.
2729 */
2730 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2731 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2732 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2733
2734 char len[25], actLen[25];
2735
2736 /* FIXME, TODO: What is the max expected string length of the
2737 * this value?
2738 */
2739 if (nodeType == XML_ATTRIBUTE_NODE)
2740 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2741 else
2742 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2743
2744 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2745 snprintf(actLen, 24, "%lu", length);
2746
2747 if (facetType == XML_SCHEMA_FACET_LENGTH)
2748 msg = xmlStrcat(msg,
2749 BAD_CAST "this differs from the allowed length of '%s'.\n");
2750 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2751 msg = xmlStrcat(msg,
2752 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2753 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2754 msg = xmlStrcat(msg,
2755 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2756
2757 if (nodeType == XML_ATTRIBUTE_NODE)
2758 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2759 value, (const xmlChar *) actLen, (const xmlChar *) len);
2760 else
2761 xmlSchemaErr(actxt, error, node, (const char *) msg,
2762 (const xmlChar *) actLen, (const xmlChar *) len);
2763
2764 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2765 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2766 "of the set {%s}.\n");
2767 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2768 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2769 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2770 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2771 "by the pattern '%s'.\n");
2772 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2773 facet->value);
2774 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2775 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2776 "minimum value allowed ('%s').\n");
2777 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2778 facet->value);
2779 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2780 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2781 "maximum value allowed ('%s').\n");
2782 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2783 facet->value);
2784 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2785 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2786 "'%s'.\n");
2787 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2788 facet->value);
2789 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2790 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2791 "'%s'.\n");
2792 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2793 facet->value);
2794 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2795 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2796 "digits than are allowed ('%s').\n");
2797 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2798 facet->value);
2799 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2800 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2801 "digits than are allowed ('%s').\n");
2802 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2803 facet->value);
2804 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2805 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2806 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2807 } else {
2808 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2809 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2810 }
2811 } else {
2812 msg = xmlStrcat(msg, (const xmlChar *) message);
2813 msg = xmlStrcat(msg, BAD_CAST ".\n");
2814 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2815 }
2816 FREE_AND_NULL(str)
2817 xmlFree(msg);
2818 }
2819
2820 #define VERROR(err, type, msg) \
2821 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2822
2823 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2824
2825 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2826 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2827
2828 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2829
2830
2831 /**
2832 * xmlSchemaPMissingAttrErr:
2833 * @ctxt: the schema validation context
2834 * @ownerItem: the owner as a schema object
2835 * @ownerElem: the owner as an element node
2836 * @node: the parent element node of the missing attribute node
2837 * @type: the corresponding type of the attribute node
2838 *
2839 * Reports an illegal attribute.
2840 */
2841 static void
xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const char * message)2842 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2843 xmlParserErrors error,
2844 xmlSchemaBasicItemPtr ownerItem,
2845 xmlNodePtr ownerElem,
2846 const char *name,
2847 const char *message)
2848 {
2849 xmlChar *des = NULL;
2850
2851 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2852
2853 if (message != NULL)
2854 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2855 else
2856 xmlSchemaPErr(ctxt, ownerElem, error,
2857 "%s: The attribute '%s' is required but missing.\n",
2858 BAD_CAST des, BAD_CAST name);
2859 FREE_AND_NULL(des);
2860 }
2861
2862
2863 /**
2864 * xmlSchemaPResCompAttrErr:
2865 * @ctxt: the schema validation context
2866 * @error: the error code
2867 * @ownerItem: the owner as a schema object
2868 * @ownerElem: the owner as an element node
2869 * @name: the name of the attribute holding the QName
2870 * @refName: the referenced local name
2871 * @refURI: the referenced namespace URI
2872 * @message: optional message
2873 *
2874 * Used to report QName attribute values that failed to resolve
2875 * to schema components.
2876 */
2877 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)2878 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2879 xmlParserErrors error,
2880 xmlSchemaBasicItemPtr ownerItem,
2881 xmlNodePtr ownerElem,
2882 const char *name,
2883 const xmlChar *refName,
2884 const xmlChar *refURI,
2885 xmlSchemaTypeType refType,
2886 const char *refTypeStr)
2887 {
2888 xmlChar *des = NULL, *strA = NULL;
2889
2890 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2891 if (refTypeStr == NULL)
2892 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2893 xmlSchemaPErrExt(ctxt, ownerElem, error,
2894 NULL, NULL, NULL,
2895 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2896 "%s.\n", BAD_CAST des, BAD_CAST name,
2897 xmlSchemaFormatQName(&strA, refURI, refName),
2898 BAD_CAST refTypeStr, NULL);
2899 FREE_AND_NULL(des)
2900 FREE_AND_NULL(strA)
2901 }
2902
2903 /**
2904 * xmlSchemaPCustomAttrErr:
2905 * @ctxt: the schema parser context
2906 * @error: the error code
2907 * @ownerDes: the designation of the owner
2908 * @ownerItem: the owner as a schema object
2909 * @attr: the illegal attribute node
2910 *
2911 * Reports an illegal attribute during the parse.
2912 */
2913 static void
xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlChar ** ownerDes,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * msg)2914 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2915 xmlParserErrors error,
2916 xmlChar **ownerDes,
2917 xmlSchemaBasicItemPtr ownerItem,
2918 xmlAttrPtr attr,
2919 const char *msg)
2920 {
2921 xmlChar *des = NULL;
2922
2923 if (ownerDes == NULL)
2924 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2925 else if (*ownerDes == NULL) {
2926 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2927 des = *ownerDes;
2928 } else
2929 des = *ownerDes;
2930 if (attr == NULL) {
2931 xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2932 "%s, attribute '%s': %s.\n",
2933 BAD_CAST des, (const xmlChar *) "Unknown",
2934 (const xmlChar *) msg, NULL, NULL);
2935 } else {
2936 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2937 "%s, attribute '%s': %s.\n",
2938 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2939 }
2940 if (ownerDes == NULL)
2941 FREE_AND_NULL(des);
2942 }
2943
2944 /**
2945 * xmlSchemaPIllegalAttrErr:
2946 * @ctxt: the schema parser context
2947 * @error: the error code
2948 * @ownerItem: the attribute's owner item
2949 * @attr: the illegal attribute node
2950 *
2951 * Reports an illegal attribute during the parse.
2952 */
2953 static void
xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,xmlAttrPtr attr)2954 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2955 xmlParserErrors error,
2956 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2957 xmlAttrPtr attr)
2958 {
2959 xmlChar *strA = NULL, *strB = NULL;
2960
2961 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2962 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2963 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2964 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2965 NULL, NULL);
2966 FREE_AND_NULL(strA);
2967 FREE_AND_NULL(strB);
2968 }
2969
2970 /**
2971 * xmlSchemaPCustomErr:
2972 * @ctxt: the schema parser context
2973 * @error: the error code
2974 * @itemDes: the designation of the schema item
2975 * @item: the schema item
2976 * @itemElem: the node of the schema item
2977 * @message: the error message
2978 * @str1: an optional param for the error message
2979 * @str2: an optional param for the error message
2980 * @str3: an optional param for the error message
2981 *
2982 * Reports an error during parsing.
2983 */
2984 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)2985 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2986 xmlParserErrors error,
2987 xmlSchemaBasicItemPtr item,
2988 xmlNodePtr itemElem,
2989 const char *message,
2990 const xmlChar *str1,
2991 const xmlChar *str2,
2992 const xmlChar *str3)
2993 {
2994 xmlChar *des = NULL, *msg = NULL;
2995
2996 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2997 msg = xmlStrdup(BAD_CAST "%s: ");
2998 msg = xmlStrcat(msg, (const xmlChar *) message);
2999 msg = xmlStrcat(msg, BAD_CAST ".\n");
3000 if ((itemElem == NULL) && (item != NULL))
3001 itemElem = WXS_ITEM_NODE(item);
3002 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
3003 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
3004 FREE_AND_NULL(des);
3005 FREE_AND_NULL(msg);
3006 }
3007
3008 /**
3009 * xmlSchemaPCustomErr:
3010 * @ctxt: the schema parser context
3011 * @error: the error code
3012 * @itemDes: the designation of the schema item
3013 * @item: the schema item
3014 * @itemElem: the node of the schema item
3015 * @message: the error message
3016 * @str1: the optional param for the error message
3017 *
3018 * Reports an error during parsing.
3019 */
3020 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1)3021 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
3022 xmlParserErrors error,
3023 xmlSchemaBasicItemPtr item,
3024 xmlNodePtr itemElem,
3025 const char *message,
3026 const xmlChar *str1)
3027 {
3028 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
3029 str1, NULL, NULL);
3030 }
3031
3032 /**
3033 * xmlSchemaPAttrUseErr:
3034 * @ctxt: the schema parser context
3035 * @error: the error code
3036 * @itemDes: the designation of the schema type
3037 * @item: the schema type
3038 * @itemElem: the node of the schema type
3039 * @attr: the invalid schema attribute
3040 * @message: the error message
3041 * @str1: the optional param for the error message
3042 *
3043 * Reports an attribute use error during parsing.
3044 */
3045 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)3046 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3047 xmlParserErrors error,
3048 xmlNodePtr node,
3049 xmlSchemaBasicItemPtr ownerItem,
3050 const xmlSchemaAttributeUsePtr attruse,
3051 const char *message,
3052 const xmlChar *str1, const xmlChar *str2,
3053 const xmlChar *str3,const xmlChar *str4)
3054 {
3055 xmlChar *str = NULL, *msg = NULL;
3056
3057 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3058 msg = xmlStrcat(msg, BAD_CAST ", ");
3059 msg = xmlStrcat(msg,
3060 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3061 WXS_BASIC_CAST attruse, NULL));
3062 FREE_AND_NULL(str);
3063 msg = xmlStrcat(msg, BAD_CAST ": ");
3064 msg = xmlStrcat(msg, (const xmlChar *) message);
3065 msg = xmlStrcat(msg, BAD_CAST ".\n");
3066 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3067 (const char *) msg, str1, str2, str3, str4);
3068 xmlFree(msg);
3069 }
3070
3071 /**
3072 * xmlSchemaPIllegalFacetAtomicErr:
3073 * @ctxt: the schema parser context
3074 * @error: the error code
3075 * @type: the schema type
3076 * @baseType: the base type of type
3077 * @facet: the illegal facet
3078 *
3079 * Reports an illegal facet for atomic simple types.
3080 */
3081 static void
xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,xmlSchemaFacetPtr facet)3082 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3083 xmlParserErrors error,
3084 xmlSchemaTypePtr type,
3085 xmlSchemaTypePtr baseType,
3086 xmlSchemaFacetPtr facet)
3087 {
3088 xmlChar *des = NULL, *strT = NULL;
3089
3090 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3091 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3092 "%s: The facet '%s' is not allowed on types derived from the "
3093 "type %s.\n",
3094 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3095 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3096 NULL, NULL);
3097 FREE_AND_NULL(des);
3098 FREE_AND_NULL(strT);
3099 }
3100
3101 /**
3102 * xmlSchemaPIllegalFacetListUnionErr:
3103 * @ctxt: the schema parser context
3104 * @error: the error code
3105 * @itemDes: the designation of the schema item involved
3106 * @item: the schema item involved
3107 * @facet: the illegal facet
3108 *
3109 * Reports an illegal facet for <list> and <union>.
3110 */
3111 static void
xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet)3112 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3113 xmlParserErrors error,
3114 xmlSchemaTypePtr type,
3115 xmlSchemaFacetPtr facet)
3116 {
3117 xmlChar *des = NULL;
3118
3119 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3120 type->node);
3121 xmlSchemaPErr(ctxt, type->node, error,
3122 "%s: The facet '%s' is not allowed.\n",
3123 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3124 FREE_AND_NULL(des);
3125 }
3126
3127 /**
3128 * xmlSchemaPMutualExclAttrErr:
3129 * @ctxt: the schema validation context
3130 * @error: the error code
3131 * @elemDes: the designation of the parent element node
3132 * @attr: the bad attribute node
3133 * @type: the corresponding type of the attribute node
3134 *
3135 * Reports an illegal attribute.
3136 */
3137 static void
xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * name1,const char * name2)3138 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3139 xmlParserErrors error,
3140 xmlSchemaBasicItemPtr ownerItem,
3141 xmlAttrPtr attr,
3142 const char *name1,
3143 const char *name2)
3144 {
3145 xmlChar *des = NULL;
3146
3147 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3148 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3149 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3150 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3151 FREE_AND_NULL(des);
3152 }
3153
3154 /**
3155 * xmlSchemaPSimpleTypeErr:
3156 * @ctxt: the schema validation context
3157 * @error: the error code
3158 * @type: the type specifier
3159 * @ownerItem: the schema object if existent
3160 * @node: the validated node
3161 * @value: the validated value
3162 *
3163 * Reports a simple type validation error.
3164 * TODO: Should this report the value of an element as well?
3165 */
3166 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)3167 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3168 xmlParserErrors error,
3169 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3170 xmlNodePtr node,
3171 xmlSchemaTypePtr type,
3172 const char *expected,
3173 const xmlChar *value,
3174 const char *message,
3175 const xmlChar *str1,
3176 const xmlChar *str2)
3177 {
3178 xmlChar *msg = NULL;
3179
3180 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3181 if (message == NULL) {
3182 /*
3183 * Use default messages.
3184 */
3185 if (type != NULL) {
3186 if (node->type == XML_ATTRIBUTE_NODE)
3187 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3188 else
3189 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3190 "valid value of ");
3191 if (! xmlSchemaIsGlobalItem(type))
3192 msg = xmlStrcat(msg, BAD_CAST "the local ");
3193 else
3194 msg = xmlStrcat(msg, BAD_CAST "the ");
3195
3196 if (WXS_IS_ATOMIC(type))
3197 msg = xmlStrcat(msg, BAD_CAST "atomic type");
3198 else if (WXS_IS_LIST(type))
3199 msg = xmlStrcat(msg, BAD_CAST "list type");
3200 else if (WXS_IS_UNION(type))
3201 msg = xmlStrcat(msg, BAD_CAST "union type");
3202
3203 if (xmlSchemaIsGlobalItem(type)) {
3204 xmlChar *str = NULL;
3205 msg = xmlStrcat(msg, BAD_CAST " '");
3206 if (type->builtInType != 0) {
3207 msg = xmlStrcat(msg, BAD_CAST "xs:");
3208 str = xmlStrdup(type->name);
3209 } else {
3210 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3211 if (!str)
3212 str = xmlStrdup(qName);
3213 }
3214 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3215 msg = xmlStrcat(msg, BAD_CAST "'.");
3216 FREE_AND_NULL(str);
3217 }
3218 } else {
3219 if (node->type == XML_ATTRIBUTE_NODE)
3220 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3221 else
3222 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3223 "valid.");
3224 }
3225 if (expected) {
3226 xmlChar *expectedEscaped = xmlCharStrdup(expected);
3227 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3228 msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3229 FREE_AND_NULL(expectedEscaped);
3230 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3231 } else
3232 msg = xmlStrcat(msg, BAD_CAST "\n");
3233 if (node->type == XML_ATTRIBUTE_NODE)
3234 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3235 else
3236 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3237 } else {
3238 msg = xmlStrcat(msg, BAD_CAST message);
3239 msg = xmlStrcat(msg, BAD_CAST ".\n");
3240 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3241 (const char*) msg, str1, str2, NULL, NULL, NULL);
3242 }
3243 /* Cleanup. */
3244 FREE_AND_NULL(msg)
3245 }
3246
3247 /**
3248 * xmlSchemaPContentErr:
3249 * @ctxt: the schema parser context
3250 * @error: the error code
3251 * @ownerItem: the owner item of the holder of the content
3252 * @ownerElem: the node of the holder of the content
3253 * @child: the invalid child node
3254 * @message: the optional error message
3255 * @content: the optional string describing the correct content
3256 *
3257 * Reports an error concerning the content of a schema element.
3258 */
3259 static void
xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,xmlNodePtr child,const char * message,const char * content)3260 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3261 xmlParserErrors error,
3262 xmlSchemaBasicItemPtr ownerItem,
3263 xmlNodePtr ownerElem,
3264 xmlNodePtr child,
3265 const char *message,
3266 const char *content)
3267 {
3268 xmlChar *des = NULL;
3269
3270 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3271 if (message != NULL)
3272 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3273 "%s: %s.\n",
3274 BAD_CAST des, BAD_CAST message);
3275 else {
3276 if (content != NULL) {
3277 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3278 "%s: The content is not valid. Expected is %s.\n",
3279 BAD_CAST des, BAD_CAST content);
3280 } else {
3281 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3282 "%s: The content is not valid.\n",
3283 BAD_CAST des, NULL);
3284 }
3285 }
3286 FREE_AND_NULL(des)
3287 }
3288
3289 /************************************************************************
3290 * *
3291 * Streamable error functions *
3292 * *
3293 ************************************************************************/
3294
3295
3296
3297
3298 /************************************************************************
3299 * *
3300 * Validation helper functions *
3301 * *
3302 ************************************************************************/
3303
3304
3305 /************************************************************************
3306 * *
3307 * Allocation functions *
3308 * *
3309 ************************************************************************/
3310
3311 /**
3312 * xmlSchemaNewSchemaForParserCtxt:
3313 * @ctxt: a schema validation context
3314 *
3315 * Allocate a new Schema structure.
3316 *
3317 * Returns the newly allocated structure or NULL in case or error
3318 */
3319 static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)3320 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3321 {
3322 xmlSchemaPtr ret;
3323
3324 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3325 if (ret == NULL) {
3326 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3327 return (NULL);
3328 }
3329 memset(ret, 0, sizeof(xmlSchema));
3330 ret->dict = ctxt->dict;
3331 xmlDictReference(ret->dict);
3332
3333 return (ret);
3334 }
3335
3336 /**
3337 * xmlSchemaNewFacet:
3338 *
3339 * Allocate a new Facet structure.
3340 *
3341 * Returns the newly allocated structure or NULL in case or error
3342 */
3343 xmlSchemaFacetPtr
xmlSchemaNewFacet(void)3344 xmlSchemaNewFacet(void)
3345 {
3346 xmlSchemaFacetPtr ret;
3347
3348 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3349 if (ret == NULL) {
3350 return (NULL);
3351 }
3352 memset(ret, 0, sizeof(xmlSchemaFacet));
3353
3354 return (ret);
3355 }
3356
3357 /**
3358 * xmlSchemaNewAnnot:
3359 * @ctxt: a schema validation context
3360 * @node: a node
3361 *
3362 * Allocate a new annotation structure.
3363 *
3364 * Returns the newly allocated structure or NULL in case or error
3365 */
3366 static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)3367 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3368 {
3369 xmlSchemaAnnotPtr ret;
3370
3371 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3372 if (ret == NULL) {
3373 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3374 return (NULL);
3375 }
3376 memset(ret, 0, sizeof(xmlSchemaAnnot));
3377 ret->content = node;
3378 return (ret);
3379 }
3380
3381 static xmlSchemaItemListPtr
xmlSchemaItemListCreate(void)3382 xmlSchemaItemListCreate(void)
3383 {
3384 xmlSchemaItemListPtr ret;
3385
3386 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3387 if (ret == NULL) {
3388 xmlSchemaPErrMemory(NULL,
3389 "allocating an item list structure", NULL);
3390 return (NULL);
3391 }
3392 memset(ret, 0, sizeof(xmlSchemaItemList));
3393 return (ret);
3394 }
3395
3396 static void
xmlSchemaItemListClear(xmlSchemaItemListPtr list)3397 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3398 {
3399 if (list->items != NULL) {
3400 xmlFree(list->items);
3401 list->items = NULL;
3402 }
3403 list->nbItems = 0;
3404 list->sizeItems = 0;
3405 }
3406
3407 static int
xmlSchemaItemListAdd(xmlSchemaItemListPtr list,void * item)3408 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3409 {
3410 if (list->items == NULL) {
3411 list->items = (void **) xmlMalloc(
3412 20 * sizeof(void *));
3413 if (list->items == NULL) {
3414 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3415 return(-1);
3416 }
3417 list->sizeItems = 20;
3418 } else if (list->sizeItems <= list->nbItems) {
3419 list->sizeItems *= 2;
3420 list->items = (void **) xmlRealloc(list->items,
3421 list->sizeItems * sizeof(void *));
3422 if (list->items == NULL) {
3423 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3424 list->sizeItems = 0;
3425 return(-1);
3426 }
3427 }
3428 list->items[list->nbItems++] = item;
3429 return(0);
3430 }
3431
3432 static int
xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,int initialSize,void * item)3433 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3434 int initialSize,
3435 void *item)
3436 {
3437 if (list->items == NULL) {
3438 if (initialSize <= 0)
3439 initialSize = 1;
3440 list->items = (void **) xmlMalloc(
3441 initialSize * sizeof(void *));
3442 if (list->items == NULL) {
3443 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3444 return(-1);
3445 }
3446 list->sizeItems = initialSize;
3447 } else if (list->sizeItems <= list->nbItems) {
3448 list->sizeItems *= 2;
3449 list->items = (void **) xmlRealloc(list->items,
3450 list->sizeItems * sizeof(void *));
3451 if (list->items == NULL) {
3452 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3453 list->sizeItems = 0;
3454 return(-1);
3455 }
3456 }
3457 list->items[list->nbItems++] = item;
3458 return(0);
3459 }
3460
3461 static int
xmlSchemaItemListInsert(xmlSchemaItemListPtr list,void * item,int idx)3462 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3463 {
3464 if (list->items == NULL) {
3465 list->items = (void **) xmlMalloc(
3466 20 * sizeof(void *));
3467 if (list->items == NULL) {
3468 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3469 return(-1);
3470 }
3471 list->sizeItems = 20;
3472 } else if (list->sizeItems <= list->nbItems) {
3473 list->sizeItems *= 2;
3474 list->items = (void **) xmlRealloc(list->items,
3475 list->sizeItems * sizeof(void *));
3476 if (list->items == NULL) {
3477 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3478 list->sizeItems = 0;
3479 return(-1);
3480 }
3481 }
3482 /*
3483 * Just append if the index is greater/equal than the item count.
3484 */
3485 if (idx >= list->nbItems) {
3486 list->items[list->nbItems++] = item;
3487 } else {
3488 int i;
3489 for (i = list->nbItems; i > idx; i--)
3490 list->items[i] = list->items[i-1];
3491 list->items[idx] = item;
3492 list->nbItems++;
3493 }
3494 return(0);
3495 }
3496
3497 #if 0 /* enable if ever needed */
3498 static int
3499 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3500 int initialSize,
3501 void *item,
3502 int idx)
3503 {
3504 if (list->items == NULL) {
3505 if (initialSize <= 0)
3506 initialSize = 1;
3507 list->items = (void **) xmlMalloc(
3508 initialSize * sizeof(void *));
3509 if (list->items == NULL) {
3510 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3511 return(-1);
3512 }
3513 list->sizeItems = initialSize;
3514 } else if (list->sizeItems <= list->nbItems) {
3515 list->sizeItems *= 2;
3516 list->items = (void **) xmlRealloc(list->items,
3517 list->sizeItems * sizeof(void *));
3518 if (list->items == NULL) {
3519 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3520 list->sizeItems = 0;
3521 return(-1);
3522 }
3523 }
3524 /*
3525 * Just append if the index is greater/equal than the item count.
3526 */
3527 if (idx >= list->nbItems) {
3528 list->items[list->nbItems++] = item;
3529 } else {
3530 int i;
3531 for (i = list->nbItems; i > idx; i--)
3532 list->items[i] = list->items[i-1];
3533 list->items[idx] = item;
3534 list->nbItems++;
3535 }
3536 return(0);
3537 }
3538 #endif
3539
3540 static int
xmlSchemaItemListRemove(xmlSchemaItemListPtr list,int idx)3541 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3542 {
3543 int i;
3544 if ((list->items == NULL) || (idx >= list->nbItems)) {
3545 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3546 "index error.\n");
3547 return(-1);
3548 }
3549
3550 if (list->nbItems == 1) {
3551 /* TODO: Really free the list? */
3552 xmlFree(list->items);
3553 list->items = NULL;
3554 list->nbItems = 0;
3555 list->sizeItems = 0;
3556 } else if (list->nbItems -1 == idx) {
3557 list->nbItems--;
3558 } else {
3559 for (i = idx; i < list->nbItems -1; i++)
3560 list->items[i] = list->items[i+1];
3561 list->nbItems--;
3562 }
3563 return(0);
3564 }
3565
3566 /**
3567 * xmlSchemaItemListFree:
3568 * @annot: a schema type structure
3569 *
3570 * Deallocate a annotation structure
3571 */
3572 static void
xmlSchemaItemListFree(xmlSchemaItemListPtr list)3573 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3574 {
3575 if (list == NULL)
3576 return;
3577 if (list->items != NULL)
3578 xmlFree(list->items);
3579 xmlFree(list);
3580 }
3581
3582 static void
xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)3583 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3584 {
3585 if (bucket == NULL)
3586 return;
3587 if (bucket->globals != NULL) {
3588 xmlSchemaComponentListFree(bucket->globals);
3589 xmlSchemaItemListFree(bucket->globals);
3590 }
3591 if (bucket->locals != NULL) {
3592 xmlSchemaComponentListFree(bucket->locals);
3593 xmlSchemaItemListFree(bucket->locals);
3594 }
3595 if (bucket->relations != NULL) {
3596 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3597 do {
3598 prev = cur;
3599 cur = cur->next;
3600 xmlFree(prev);
3601 } while (cur != NULL);
3602 }
3603 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3604 xmlFreeDoc(bucket->doc);
3605 }
3606 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3607 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3608 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3609 }
3610 xmlFree(bucket);
3611 }
3612
3613 static void
xmlSchemaBucketFreeEntry(void * bucket,const xmlChar * name ATTRIBUTE_UNUSED)3614 xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3615 {
3616 xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3617 }
3618
3619 static xmlSchemaBucketPtr
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * targetNamespace)3620 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3621 int type, const xmlChar *targetNamespace)
3622 {
3623 xmlSchemaBucketPtr ret;
3624 int size;
3625 xmlSchemaPtr mainSchema;
3626
3627 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3628 PERROR_INT("xmlSchemaBucketCreate",
3629 "no main schema on constructor");
3630 return(NULL);
3631 }
3632 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3633 /* Create the schema bucket. */
3634 if (WXS_IS_BUCKET_INCREDEF(type))
3635 size = sizeof(xmlSchemaInclude);
3636 else
3637 size = sizeof(xmlSchemaImport);
3638 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3639 if (ret == NULL) {
3640 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3641 return(NULL);
3642 }
3643 memset(ret, 0, size);
3644 ret->targetNamespace = targetNamespace;
3645 ret->type = type;
3646 ret->globals = xmlSchemaItemListCreate();
3647 if (ret->globals == NULL) {
3648 xmlFree(ret);
3649 return(NULL);
3650 }
3651 ret->locals = xmlSchemaItemListCreate();
3652 if (ret->locals == NULL) {
3653 xmlFree(ret);
3654 return(NULL);
3655 }
3656 /*
3657 * The following will assure that only the first bucket is marked as
3658 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3659 * For each following import buckets an xmlSchema will be created.
3660 * An xmlSchema will be created for every distinct targetNamespace.
3661 * We assign the targetNamespace to the schemata here.
3662 */
3663 if (! WXS_HAS_BUCKETS(pctxt)) {
3664 if (WXS_IS_BUCKET_INCREDEF(type)) {
3665 PERROR_INT("xmlSchemaBucketCreate",
3666 "first bucket but it's an include or redefine");
3667 xmlSchemaBucketFree(ret);
3668 return(NULL);
3669 }
3670 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3671 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3672 /* Point to the *main* schema. */
3673 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3674 WXS_IMPBUCKET(ret)->schema = mainSchema;
3675 /*
3676 * Ensure that the main schema gets a targetNamespace.
3677 */
3678 mainSchema->targetNamespace = targetNamespace;
3679 } else {
3680 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3681 PERROR_INT("xmlSchemaBucketCreate",
3682 "main bucket but it's not the first one");
3683 xmlSchemaBucketFree(ret);
3684 return(NULL);
3685 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3686 /*
3687 * Create a schema for imports and assign the
3688 * targetNamespace.
3689 */
3690 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3691 if (WXS_IMPBUCKET(ret)->schema == NULL) {
3692 xmlSchemaBucketFree(ret);
3693 return(NULL);
3694 }
3695 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3696 }
3697 }
3698 if (WXS_IS_BUCKET_IMPMAIN(type)) {
3699 int res;
3700 /*
3701 * Imports go into the "schemasImports" slot of the main *schema*.
3702 * Note that we create an import entry for the main schema as well; i.e.,
3703 * even if there's only one schema, we'll get an import.
3704 */
3705 if (mainSchema->schemasImports == NULL) {
3706 mainSchema->schemasImports = xmlHashCreateDict(5,
3707 WXS_CONSTRUCTOR(pctxt)->dict);
3708 if (mainSchema->schemasImports == NULL) {
3709 xmlSchemaBucketFree(ret);
3710 return(NULL);
3711 }
3712 }
3713 if (targetNamespace == NULL)
3714 res = xmlHashAddEntry(mainSchema->schemasImports,
3715 XML_SCHEMAS_NO_NAMESPACE, ret);
3716 else
3717 res = xmlHashAddEntry(mainSchema->schemasImports,
3718 targetNamespace, ret);
3719 if (res != 0) {
3720 PERROR_INT("xmlSchemaBucketCreate",
3721 "failed to add the schema bucket to the hash");
3722 xmlSchemaBucketFree(ret);
3723 return(NULL);
3724 }
3725 } else {
3726 /* Set the @ownerImport of an include bucket. */
3727 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3728 WXS_INCBUCKET(ret)->ownerImport =
3729 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3730 else
3731 WXS_INCBUCKET(ret)->ownerImport =
3732 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3733
3734 /* Includes got into the "includes" slot of the *main* schema. */
3735 if (mainSchema->includes == NULL) {
3736 mainSchema->includes = xmlSchemaItemListCreate();
3737 if (mainSchema->includes == NULL) {
3738 xmlSchemaBucketFree(ret);
3739 return(NULL);
3740 }
3741 }
3742 xmlSchemaItemListAdd(mainSchema->includes, ret);
3743 }
3744 /*
3745 * Add to list of all buckets; this is used for lookup
3746 * during schema construction time only.
3747 */
3748 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3749 return(NULL);
3750 return(ret);
3751 }
3752
3753 static int
xmlSchemaAddItemSize(xmlSchemaItemListPtr * list,int initialSize,void * item)3754 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3755 {
3756 if (*list == NULL) {
3757 *list = xmlSchemaItemListCreate();
3758 if (*list == NULL)
3759 return(-1);
3760 }
3761 xmlSchemaItemListAddSize(*list, initialSize, item);
3762 return(0);
3763 }
3764
3765 /**
3766 * xmlSchemaFreeAnnot:
3767 * @annot: a schema type structure
3768 *
3769 * Deallocate a annotation structure
3770 */
3771 static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)3772 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3773 {
3774 if (annot == NULL)
3775 return;
3776 if (annot->next == NULL) {
3777 xmlFree(annot);
3778 } else {
3779 xmlSchemaAnnotPtr prev;
3780
3781 do {
3782 prev = annot;
3783 annot = annot->next;
3784 xmlFree(prev);
3785 } while (annot != NULL);
3786 }
3787 }
3788
3789 /**
3790 * xmlSchemaFreeNotation:
3791 * @schema: a schema notation structure
3792 *
3793 * Deallocate a Schema Notation structure.
3794 */
3795 static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)3796 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3797 {
3798 if (nota == NULL)
3799 return;
3800 xmlFree(nota);
3801 }
3802
3803 /**
3804 * xmlSchemaFreeAttribute:
3805 * @attr: an attribute declaration
3806 *
3807 * Deallocates an attribute declaration structure.
3808 */
3809 static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)3810 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3811 {
3812 if (attr == NULL)
3813 return;
3814 if (attr->annot != NULL)
3815 xmlSchemaFreeAnnot(attr->annot);
3816 if (attr->defVal != NULL)
3817 xmlSchemaFreeValue(attr->defVal);
3818 xmlFree(attr);
3819 }
3820
3821 /**
3822 * xmlSchemaFreeAttributeUse:
3823 * @use: an attribute use
3824 *
3825 * Deallocates an attribute use structure.
3826 */
3827 static void
xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)3828 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3829 {
3830 if (use == NULL)
3831 return;
3832 if (use->annot != NULL)
3833 xmlSchemaFreeAnnot(use->annot);
3834 if (use->defVal != NULL)
3835 xmlSchemaFreeValue(use->defVal);
3836 xmlFree(use);
3837 }
3838
3839 /**
3840 * xmlSchemaFreeAttributeUseProhib:
3841 * @prohib: an attribute use prohibition
3842 *
3843 * Deallocates an attribute use structure.
3844 */
3845 static void
xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)3846 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3847 {
3848 if (prohib == NULL)
3849 return;
3850 xmlFree(prohib);
3851 }
3852
3853 /**
3854 * xmlSchemaFreeWildcardNsSet:
3855 * set: a schema wildcard namespace
3856 *
3857 * Deallocates a list of wildcard constraint structures.
3858 */
3859 static void
xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)3860 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3861 {
3862 xmlSchemaWildcardNsPtr next;
3863
3864 while (set != NULL) {
3865 next = set->next;
3866 xmlFree(set);
3867 set = next;
3868 }
3869 }
3870
3871 /**
3872 * xmlSchemaFreeWildcard:
3873 * @wildcard: a wildcard structure
3874 *
3875 * Deallocates a wildcard structure.
3876 */
3877 void
xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)3878 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3879 {
3880 if (wildcard == NULL)
3881 return;
3882 if (wildcard->annot != NULL)
3883 xmlSchemaFreeAnnot(wildcard->annot);
3884 if (wildcard->nsSet != NULL)
3885 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3886 if (wildcard->negNsSet != NULL)
3887 xmlFree(wildcard->negNsSet);
3888 xmlFree(wildcard);
3889 }
3890
3891 /**
3892 * xmlSchemaFreeAttributeGroup:
3893 * @schema: a schema attribute group structure
3894 *
3895 * Deallocate a Schema Attribute Group structure.
3896 */
3897 static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)3898 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3899 {
3900 if (attrGr == NULL)
3901 return;
3902 if (attrGr->annot != NULL)
3903 xmlSchemaFreeAnnot(attrGr->annot);
3904 if (attrGr->attrUses != NULL)
3905 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3906 xmlFree(attrGr);
3907 }
3908
3909 /**
3910 * xmlSchemaFreeQNameRef:
3911 * @item: a QName reference structure
3912 *
3913 * Deallocatea a QName reference structure.
3914 */
3915 static void
xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)3916 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3917 {
3918 xmlFree(item);
3919 }
3920
3921 /**
3922 * xmlSchemaFreeTypeLinkList:
3923 * @alink: a type link
3924 *
3925 * Deallocate a list of types.
3926 */
3927 static void
xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)3928 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3929 {
3930 xmlSchemaTypeLinkPtr next;
3931
3932 while (link != NULL) {
3933 next = link->next;
3934 xmlFree(link);
3935 link = next;
3936 }
3937 }
3938
3939 static void
xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)3940 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3941 {
3942 xmlSchemaIDCStateObjPtr next;
3943 while (sto != NULL) {
3944 next = sto->next;
3945 if (sto->history != NULL)
3946 xmlFree(sto->history);
3947 if (sto->xpathCtxt != NULL)
3948 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3949 xmlFree(sto);
3950 sto = next;
3951 }
3952 }
3953
3954 /**
3955 * xmlSchemaFreeIDC:
3956 * @idc: a identity-constraint definition
3957 *
3958 * Deallocates an identity-constraint definition.
3959 */
3960 static void
xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)3961 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3962 {
3963 xmlSchemaIDCSelectPtr cur, prev;
3964
3965 if (idcDef == NULL)
3966 return;
3967 if (idcDef->annot != NULL)
3968 xmlSchemaFreeAnnot(idcDef->annot);
3969 /* Selector */
3970 if (idcDef->selector != NULL) {
3971 if (idcDef->selector->xpathComp != NULL)
3972 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3973 xmlFree(idcDef->selector);
3974 }
3975 /* Fields */
3976 if (idcDef->fields != NULL) {
3977 cur = idcDef->fields;
3978 do {
3979 prev = cur;
3980 cur = cur->next;
3981 if (prev->xpathComp != NULL)
3982 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3983 xmlFree(prev);
3984 } while (cur != NULL);
3985 }
3986 xmlFree(idcDef);
3987 }
3988
3989 /**
3990 * xmlSchemaFreeElement:
3991 * @schema: a schema element structure
3992 *
3993 * Deallocate a Schema Element structure.
3994 */
3995 static void
xmlSchemaFreeElement(xmlSchemaElementPtr elem)3996 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3997 {
3998 if (elem == NULL)
3999 return;
4000 if (elem->annot != NULL)
4001 xmlSchemaFreeAnnot(elem->annot);
4002 if (elem->contModel != NULL)
4003 xmlRegFreeRegexp(elem->contModel);
4004 if (elem->defVal != NULL)
4005 xmlSchemaFreeValue(elem->defVal);
4006 xmlFree(elem);
4007 }
4008
4009 /**
4010 * xmlSchemaFreeFacet:
4011 * @facet: a schema facet structure
4012 *
4013 * Deallocate a Schema Facet structure.
4014 */
4015 void
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)4016 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
4017 {
4018 if (facet == NULL)
4019 return;
4020 if (facet->val != NULL)
4021 xmlSchemaFreeValue(facet->val);
4022 if (facet->regexp != NULL)
4023 xmlRegFreeRegexp(facet->regexp);
4024 if (facet->annot != NULL)
4025 xmlSchemaFreeAnnot(facet->annot);
4026 xmlFree(facet);
4027 }
4028
4029 /**
4030 * xmlSchemaFreeType:
4031 * @type: a schema type structure
4032 *
4033 * Deallocate a Schema Type structure.
4034 */
4035 void
xmlSchemaFreeType(xmlSchemaTypePtr type)4036 xmlSchemaFreeType(xmlSchemaTypePtr type)
4037 {
4038 if (type == NULL)
4039 return;
4040 if (type->annot != NULL)
4041 xmlSchemaFreeAnnot(type->annot);
4042 if (type->facets != NULL) {
4043 xmlSchemaFacetPtr facet, next;
4044
4045 facet = type->facets;
4046 while (facet != NULL) {
4047 next = facet->next;
4048 xmlSchemaFreeFacet(facet);
4049 facet = next;
4050 }
4051 }
4052 if (type->attrUses != NULL)
4053 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4054 if (type->memberTypes != NULL)
4055 xmlSchemaFreeTypeLinkList(type->memberTypes);
4056 if (type->facetSet != NULL) {
4057 xmlSchemaFacetLinkPtr next, link;
4058
4059 link = type->facetSet;
4060 do {
4061 next = link->next;
4062 xmlFree(link);
4063 link = next;
4064 } while (link != NULL);
4065 }
4066 if (type->contModel != NULL)
4067 xmlRegFreeRegexp(type->contModel);
4068 xmlFree(type);
4069 }
4070
4071 /**
4072 * xmlSchemaFreeModelGroupDef:
4073 * @item: a schema model group definition
4074 *
4075 * Deallocates a schema model group definition.
4076 */
4077 static void
xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)4078 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4079 {
4080 if (item->annot != NULL)
4081 xmlSchemaFreeAnnot(item->annot);
4082 xmlFree(item);
4083 }
4084
4085 /**
4086 * xmlSchemaFreeModelGroup:
4087 * @item: a schema model group
4088 *
4089 * Deallocates a schema model group structure.
4090 */
4091 static void
xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)4092 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4093 {
4094 if (item->annot != NULL)
4095 xmlSchemaFreeAnnot(item->annot);
4096 xmlFree(item);
4097 }
4098
4099 static void
xmlSchemaComponentListFree(xmlSchemaItemListPtr list)4100 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4101 {
4102 if ((list == NULL) || (list->nbItems == 0))
4103 return;
4104 {
4105 xmlSchemaTreeItemPtr item;
4106 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4107 int i;
4108
4109 for (i = 0; i < list->nbItems; i++) {
4110 item = items[i];
4111 if (item == NULL)
4112 continue;
4113 switch (item->type) {
4114 case XML_SCHEMA_TYPE_SIMPLE:
4115 case XML_SCHEMA_TYPE_COMPLEX:
4116 xmlSchemaFreeType((xmlSchemaTypePtr) item);
4117 break;
4118 case XML_SCHEMA_TYPE_ATTRIBUTE:
4119 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4120 break;
4121 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4122 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4123 break;
4124 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4125 xmlSchemaFreeAttributeUseProhib(
4126 (xmlSchemaAttributeUseProhibPtr) item);
4127 break;
4128 case XML_SCHEMA_TYPE_ELEMENT:
4129 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4130 break;
4131 case XML_SCHEMA_TYPE_PARTICLE:
4132 if (item->annot != NULL)
4133 xmlSchemaFreeAnnot(item->annot);
4134 xmlFree(item);
4135 break;
4136 case XML_SCHEMA_TYPE_SEQUENCE:
4137 case XML_SCHEMA_TYPE_CHOICE:
4138 case XML_SCHEMA_TYPE_ALL:
4139 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4140 break;
4141 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4142 xmlSchemaFreeAttributeGroup(
4143 (xmlSchemaAttributeGroupPtr) item);
4144 break;
4145 case XML_SCHEMA_TYPE_GROUP:
4146 xmlSchemaFreeModelGroupDef(
4147 (xmlSchemaModelGroupDefPtr) item);
4148 break;
4149 case XML_SCHEMA_TYPE_ANY:
4150 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4151 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4152 break;
4153 case XML_SCHEMA_TYPE_IDC_KEY:
4154 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4155 case XML_SCHEMA_TYPE_IDC_KEYREF:
4156 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4157 break;
4158 case XML_SCHEMA_TYPE_NOTATION:
4159 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4160 break;
4161 case XML_SCHEMA_EXTRA_QNAMEREF:
4162 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4163 break;
4164 default: {
4165 /* TODO: This should never be hit. */
4166 xmlSchemaPSimpleInternalErr(NULL,
4167 "Internal error: xmlSchemaComponentListFree, "
4168 "unexpected component type '%s'\n",
4169 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4170 }
4171 break;
4172 }
4173 }
4174 list->nbItems = 0;
4175 }
4176 }
4177
4178 /**
4179 * xmlSchemaFree:
4180 * @schema: a schema structure
4181 *
4182 * Deallocate a Schema structure.
4183 */
4184 void
xmlSchemaFree(xmlSchemaPtr schema)4185 xmlSchemaFree(xmlSchemaPtr schema)
4186 {
4187 if (schema == NULL)
4188 return;
4189 /* @volatiles is not used anymore :-/ */
4190 if (schema->volatiles != NULL)
4191 TODO
4192 /*
4193 * Note that those slots are not responsible for freeing
4194 * schema components anymore; this will now be done by
4195 * the schema buckets.
4196 */
4197 if (schema->notaDecl != NULL)
4198 xmlHashFree(schema->notaDecl, NULL);
4199 if (schema->attrDecl != NULL)
4200 xmlHashFree(schema->attrDecl, NULL);
4201 if (schema->attrgrpDecl != NULL)
4202 xmlHashFree(schema->attrgrpDecl, NULL);
4203 if (schema->elemDecl != NULL)
4204 xmlHashFree(schema->elemDecl, NULL);
4205 if (schema->typeDecl != NULL)
4206 xmlHashFree(schema->typeDecl, NULL);
4207 if (schema->groupDecl != NULL)
4208 xmlHashFree(schema->groupDecl, NULL);
4209 if (schema->idcDef != NULL)
4210 xmlHashFree(schema->idcDef, NULL);
4211
4212 if (schema->schemasImports != NULL)
4213 xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4214 if (schema->includes != NULL) {
4215 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4216 int i;
4217 for (i = 0; i < list->nbItems; i++) {
4218 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4219 }
4220 xmlSchemaItemListFree(list);
4221 }
4222 if (schema->annot != NULL)
4223 xmlSchemaFreeAnnot(schema->annot);
4224 /* Never free the doc here, since this will be done by the buckets. */
4225
4226 xmlDictFree(schema->dict);
4227 xmlFree(schema);
4228 }
4229
4230 /************************************************************************
4231 * *
4232 * Debug functions *
4233 * *
4234 ************************************************************************/
4235
4236 #ifdef LIBXML_OUTPUT_ENABLED
4237
4238 static void
4239 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4240
4241 /**
4242 * xmlSchemaElementDump:
4243 * @elem: an element
4244 * @output: the file output
4245 *
4246 * Dump the element
4247 */
4248 static void
xmlSchemaElementDump(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED,const xmlChar * context ATTRIBUTE_UNUSED)4249 xmlSchemaElementDump(void *payload, void *data,
4250 const xmlChar * name ATTRIBUTE_UNUSED,
4251 const xmlChar * namespace ATTRIBUTE_UNUSED,
4252 const xmlChar * context ATTRIBUTE_UNUSED)
4253 {
4254 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4255 FILE *output = (FILE *) data;
4256 if (elem == NULL)
4257 return;
4258
4259
4260 fprintf(output, "Element");
4261 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4262 fprintf(output, " (global)");
4263 fprintf(output, ": '%s' ", elem->name);
4264 if (namespace != NULL)
4265 fprintf(output, "ns '%s'", namespace);
4266 fprintf(output, "\n");
4267 #if 0
4268 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4269 fprintf(output, " min %d ", elem->minOccurs);
4270 if (elem->maxOccurs >= UNBOUNDED)
4271 fprintf(output, "max: unbounded\n");
4272 else if (elem->maxOccurs != 1)
4273 fprintf(output, "max: %d\n", elem->maxOccurs);
4274 else
4275 fprintf(output, "\n");
4276 }
4277 #endif
4278 /*
4279 * Misc other properties.
4280 */
4281 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4282 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4283 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4284 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4285 fprintf(output, " props: ");
4286 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4287 fprintf(output, "[fixed] ");
4288 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4289 fprintf(output, "[default] ");
4290 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4291 fprintf(output, "[abstract] ");
4292 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4293 fprintf(output, "[nillable] ");
4294 fprintf(output, "\n");
4295 }
4296 /*
4297 * Default/fixed value.
4298 */
4299 if (elem->value != NULL)
4300 fprintf(output, " value: '%s'\n", elem->value);
4301 /*
4302 * Type.
4303 */
4304 if (elem->namedType != NULL) {
4305 fprintf(output, " type: '%s' ", elem->namedType);
4306 if (elem->namedTypeNs != NULL)
4307 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4308 else
4309 fprintf(output, "\n");
4310 } else if (elem->subtypes != NULL) {
4311 /*
4312 * Dump local types.
4313 */
4314 xmlSchemaTypeDump(elem->subtypes, output);
4315 }
4316 /*
4317 * Substitution group.
4318 */
4319 if (elem->substGroup != NULL) {
4320 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
4321 if (elem->substGroupNs != NULL)
4322 fprintf(output, "ns '%s'\n", elem->substGroupNs);
4323 else
4324 fprintf(output, "\n");
4325 }
4326 }
4327
4328 /**
4329 * xmlSchemaAnnotDump:
4330 * @output: the file output
4331 * @annot: a annotation
4332 *
4333 * Dump the annotation
4334 */
4335 static void
xmlSchemaAnnotDump(FILE * output,xmlSchemaAnnotPtr annot)4336 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4337 {
4338 xmlChar *content;
4339
4340 if (annot == NULL)
4341 return;
4342
4343 content = xmlNodeGetContent(annot->content);
4344 if (content != NULL) {
4345 fprintf(output, " Annot: %s\n", content);
4346 xmlFree(content);
4347 } else
4348 fprintf(output, " Annot: empty\n");
4349 }
4350
4351 /**
4352 * xmlSchemaContentModelDump:
4353 * @particle: the schema particle
4354 * @output: the file output
4355 * @depth: the depth used for indentation
4356 *
4357 * Dump a SchemaType structure
4358 */
4359 static void
xmlSchemaContentModelDump(xmlSchemaParticlePtr particle,FILE * output,int depth)4360 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4361 {
4362 xmlChar *str = NULL;
4363 xmlSchemaTreeItemPtr term;
4364 char shift[100];
4365 int i;
4366
4367 if (particle == NULL)
4368 return;
4369 for (i = 0;((i < depth) && (i < 25));i++)
4370 shift[2 * i] = shift[2 * i + 1] = ' ';
4371 shift[2 * i] = shift[2 * i + 1] = 0;
4372 fprintf(output, "%s", shift);
4373 if (particle->children == NULL) {
4374 fprintf(output, "MISSING particle term\n");
4375 return;
4376 }
4377 term = particle->children;
4378 if (term == NULL) {
4379 fprintf(output, "(NULL)");
4380 } else {
4381 switch (term->type) {
4382 case XML_SCHEMA_TYPE_ELEMENT:
4383 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4384 ((xmlSchemaElementPtr)term)->targetNamespace,
4385 ((xmlSchemaElementPtr)term)->name));
4386 FREE_AND_NULL(str);
4387 break;
4388 case XML_SCHEMA_TYPE_SEQUENCE:
4389 fprintf(output, "SEQUENCE");
4390 break;
4391 case XML_SCHEMA_TYPE_CHOICE:
4392 fprintf(output, "CHOICE");
4393 break;
4394 case XML_SCHEMA_TYPE_ALL:
4395 fprintf(output, "ALL");
4396 break;
4397 case XML_SCHEMA_TYPE_ANY:
4398 fprintf(output, "ANY");
4399 break;
4400 default:
4401 fprintf(output, "UNKNOWN\n");
4402 return;
4403 }
4404 }
4405 if (particle->minOccurs != 1)
4406 fprintf(output, " min: %d", particle->minOccurs);
4407 if (particle->maxOccurs >= UNBOUNDED)
4408 fprintf(output, " max: unbounded");
4409 else if (particle->maxOccurs != 1)
4410 fprintf(output, " max: %d", particle->maxOccurs);
4411 fprintf(output, "\n");
4412 if (term &&
4413 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4414 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4415 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4416 (term->children != NULL)) {
4417 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4418 output, depth +1);
4419 }
4420 if (particle->next != NULL)
4421 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4422 output, depth);
4423 }
4424
4425 /**
4426 * xmlSchemaAttrUsesDump:
4427 * @uses: attribute uses list
4428 * @output: the file output
4429 *
4430 * Dumps a list of attribute use components.
4431 */
4432 static void
xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses,FILE * output)4433 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4434 {
4435 xmlSchemaAttributeUsePtr use;
4436 xmlSchemaAttributeUseProhibPtr prohib;
4437 xmlSchemaQNameRefPtr ref;
4438 const xmlChar *name, *tns;
4439 xmlChar *str = NULL;
4440 int i;
4441
4442 if ((uses == NULL) || (uses->nbItems == 0))
4443 return;
4444
4445 fprintf(output, " attributes:\n");
4446 for (i = 0; i < uses->nbItems; i++) {
4447 use = uses->items[i];
4448 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4449 fprintf(output, " [prohibition] ");
4450 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4451 name = prohib->name;
4452 tns = prohib->targetNamespace;
4453 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4454 fprintf(output, " [reference] ");
4455 ref = (xmlSchemaQNameRefPtr) use;
4456 name = ref->name;
4457 tns = ref->targetNamespace;
4458 } else {
4459 fprintf(output, " [use] ");
4460 name = WXS_ATTRUSE_DECL_NAME(use);
4461 tns = WXS_ATTRUSE_DECL_TNS(use);
4462 }
4463 fprintf(output, "'%s'\n",
4464 (const char *) xmlSchemaFormatQName(&str, tns, name));
4465 FREE_AND_NULL(str);
4466 }
4467 }
4468
4469 /**
4470 * xmlSchemaTypeDump:
4471 * @output: the file output
4472 * @type: a type structure
4473 *
4474 * Dump a SchemaType structure
4475 */
4476 static void
xmlSchemaTypeDump(xmlSchemaTypePtr type,FILE * output)4477 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4478 {
4479 if (type == NULL) {
4480 fprintf(output, "Type: NULL\n");
4481 return;
4482 }
4483 fprintf(output, "Type: ");
4484 if (type->name != NULL)
4485 fprintf(output, "'%s' ", type->name);
4486 else
4487 fprintf(output, "(no name) ");
4488 if (type->targetNamespace != NULL)
4489 fprintf(output, "ns '%s' ", type->targetNamespace);
4490 switch (type->type) {
4491 case XML_SCHEMA_TYPE_BASIC:
4492 fprintf(output, "[basic] ");
4493 break;
4494 case XML_SCHEMA_TYPE_SIMPLE:
4495 fprintf(output, "[simple] ");
4496 break;
4497 case XML_SCHEMA_TYPE_COMPLEX:
4498 fprintf(output, "[complex] ");
4499 break;
4500 case XML_SCHEMA_TYPE_SEQUENCE:
4501 fprintf(output, "[sequence] ");
4502 break;
4503 case XML_SCHEMA_TYPE_CHOICE:
4504 fprintf(output, "[choice] ");
4505 break;
4506 case XML_SCHEMA_TYPE_ALL:
4507 fprintf(output, "[all] ");
4508 break;
4509 case XML_SCHEMA_TYPE_UR:
4510 fprintf(output, "[ur] ");
4511 break;
4512 case XML_SCHEMA_TYPE_RESTRICTION:
4513 fprintf(output, "[restriction] ");
4514 break;
4515 case XML_SCHEMA_TYPE_EXTENSION:
4516 fprintf(output, "[extension] ");
4517 break;
4518 default:
4519 fprintf(output, "[unknown type %d] ", type->type);
4520 break;
4521 }
4522 fprintf(output, "content: ");
4523 switch (type->contentType) {
4524 case XML_SCHEMA_CONTENT_UNKNOWN:
4525 fprintf(output, "[unknown] ");
4526 break;
4527 case XML_SCHEMA_CONTENT_EMPTY:
4528 fprintf(output, "[empty] ");
4529 break;
4530 case XML_SCHEMA_CONTENT_ELEMENTS:
4531 fprintf(output, "[element] ");
4532 break;
4533 case XML_SCHEMA_CONTENT_MIXED:
4534 fprintf(output, "[mixed] ");
4535 break;
4536 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4537 /* not used. */
4538 break;
4539 case XML_SCHEMA_CONTENT_BASIC:
4540 fprintf(output, "[basic] ");
4541 break;
4542 case XML_SCHEMA_CONTENT_SIMPLE:
4543 fprintf(output, "[simple] ");
4544 break;
4545 case XML_SCHEMA_CONTENT_ANY:
4546 fprintf(output, "[any] ");
4547 break;
4548 }
4549 fprintf(output, "\n");
4550 if (type->base != NULL) {
4551 fprintf(output, " base type: '%s'", type->base);
4552 if (type->baseNs != NULL)
4553 fprintf(output, " ns '%s'\n", type->baseNs);
4554 else
4555 fprintf(output, "\n");
4556 }
4557 if (type->attrUses != NULL)
4558 xmlSchemaAttrUsesDump(type->attrUses, output);
4559 if (type->annot != NULL)
4560 xmlSchemaAnnotDump(output, type->annot);
4561 #ifdef DUMP_CONTENT_MODEL
4562 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4563 (type->subtypes != NULL)) {
4564 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4565 output, 1);
4566 }
4567 #endif
4568 }
4569
4570 static void
xmlSchemaTypeDumpEntry(void * type,void * output,const xmlChar * name ATTRIBUTE_UNUSED)4571 xmlSchemaTypeDumpEntry(void *type, void *output,
4572 const xmlChar *name ATTRIBUTE_UNUSED)
4573 {
4574 xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4575 }
4576
4577 /**
4578 * xmlSchemaDump:
4579 * @output: the file output
4580 * @schema: a schema structure
4581 *
4582 * Dump a Schema structure.
4583 */
4584 void
xmlSchemaDump(FILE * output,xmlSchemaPtr schema)4585 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4586 {
4587 if (output == NULL)
4588 return;
4589 if (schema == NULL) {
4590 fprintf(output, "Schemas: NULL\n");
4591 return;
4592 }
4593 fprintf(output, "Schemas: ");
4594 if (schema->name != NULL)
4595 fprintf(output, "%s, ", schema->name);
4596 else
4597 fprintf(output, "no name, ");
4598 if (schema->targetNamespace != NULL)
4599 fprintf(output, "%s", (const char *) schema->targetNamespace);
4600 else
4601 fprintf(output, "no target namespace");
4602 fprintf(output, "\n");
4603 if (schema->annot != NULL)
4604 xmlSchemaAnnotDump(output, schema->annot);
4605 xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4606 xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4607 }
4608
4609 #ifdef DEBUG_IDC_NODE_TABLE
4610 /**
4611 * xmlSchemaDebugDumpIDCTable:
4612 * @vctxt: the WXS validation context
4613 *
4614 * Displays the current IDC table for debug purposes.
4615 */
4616 static void
xmlSchemaDebugDumpIDCTable(FILE * output,const xmlChar * namespaceName,const xmlChar * localName,xmlSchemaPSVIIDCBindingPtr bind)4617 xmlSchemaDebugDumpIDCTable(FILE * output,
4618 const xmlChar *namespaceName,
4619 const xmlChar *localName,
4620 xmlSchemaPSVIIDCBindingPtr bind)
4621 {
4622 xmlChar *str = NULL;
4623 const xmlChar *value;
4624 xmlSchemaPSVIIDCNodePtr tab;
4625 xmlSchemaPSVIIDCKeyPtr key;
4626 int i, j, res;
4627
4628 fprintf(output, "IDC: TABLES on '%s'\n",
4629 xmlSchemaFormatQName(&str, namespaceName, localName));
4630 FREE_AND_NULL(str)
4631
4632 if (bind == NULL)
4633 return;
4634 do {
4635 fprintf(output, "IDC: BINDING '%s' (%d)\n",
4636 xmlSchemaGetComponentQName(&str,
4637 bind->definition), bind->nbNodes);
4638 FREE_AND_NULL(str)
4639 for (i = 0; i < bind->nbNodes; i++) {
4640 tab = bind->nodeTable[i];
4641 fprintf(output, " ( ");
4642 for (j = 0; j < bind->definition->nbFields; j++) {
4643 key = tab->keys[j];
4644 if ((key != NULL) && (key->val != NULL)) {
4645 res = xmlSchemaGetCanonValue(key->val, &value);
4646 if (res >= 0)
4647 fprintf(output, "'%s' ", value);
4648 else
4649 fprintf(output, "CANON-VALUE-FAILED ");
4650 if (res == 0)
4651 FREE_AND_NULL(value)
4652 } else if (key != NULL)
4653 fprintf(output, "(no val), ");
4654 else
4655 fprintf(output, "(key missing), ");
4656 }
4657 fprintf(output, ")\n");
4658 }
4659 if (bind->dupls && bind->dupls->nbItems) {
4660 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
4661 for (i = 0; i < bind->dupls->nbItems; i++) {
4662 tab = bind->dupls->items[i];
4663 fprintf(output, " ( ");
4664 for (j = 0; j < bind->definition->nbFields; j++) {
4665 key = tab->keys[j];
4666 if ((key != NULL) && (key->val != NULL)) {
4667 res = xmlSchemaGetCanonValue(key->val, &value);
4668 if (res >= 0)
4669 fprintf(output, "'%s' ", value);
4670 else
4671 fprintf(output, "CANON-VALUE-FAILED ");
4672 if (res == 0)
4673 FREE_AND_NULL(value)
4674 } else if (key != NULL)
4675 fprintf(output, "(no val), ");
4676 else
4677 fprintf(output, "(key missing), ");
4678 }
4679 fprintf(output, ")\n");
4680 }
4681 }
4682 bind = bind->next;
4683 } while (bind != NULL);
4684 }
4685 #endif /* DEBUG_IDC */
4686 #endif /* LIBXML_OUTPUT_ENABLED */
4687
4688 /************************************************************************
4689 * *
4690 * Utilities *
4691 * *
4692 ************************************************************************/
4693
4694 /**
4695 * xmlSchemaGetPropNode:
4696 * @node: the element node
4697 * @name: the name of the attribute
4698 *
4699 * Seeks an attribute with a name of @name in
4700 * no namespace.
4701 *
4702 * Returns the attribute or NULL if not present.
4703 */
4704 static xmlAttrPtr
xmlSchemaGetPropNode(xmlNodePtr node,const char * name)4705 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4706 {
4707 xmlAttrPtr prop;
4708
4709 if ((node == NULL) || (name == NULL))
4710 return(NULL);
4711 prop = node->properties;
4712 while (prop != NULL) {
4713 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4714 return(prop);
4715 prop = prop->next;
4716 }
4717 return (NULL);
4718 }
4719
4720 /**
4721 * xmlSchemaGetPropNodeNs:
4722 * @node: the element node
4723 * @uri: the uri
4724 * @name: the name of the attribute
4725 *
4726 * Seeks an attribute with a local name of @name and
4727 * a namespace URI of @uri.
4728 *
4729 * Returns the attribute or NULL if not present.
4730 */
4731 static xmlAttrPtr
xmlSchemaGetPropNodeNs(xmlNodePtr node,const char * uri,const char * name)4732 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4733 {
4734 xmlAttrPtr prop;
4735
4736 if ((node == NULL) || (name == NULL))
4737 return(NULL);
4738 prop = node->properties;
4739 while (prop != NULL) {
4740 if ((prop->ns != NULL) &&
4741 xmlStrEqual(prop->name, BAD_CAST name) &&
4742 xmlStrEqual(prop->ns->href, BAD_CAST uri))
4743 return(prop);
4744 prop = prop->next;
4745 }
4746 return (NULL);
4747 }
4748
4749 static const xmlChar *
xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)4750 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4751 {
4752 xmlChar *val;
4753 const xmlChar *ret;
4754
4755 val = xmlNodeGetContent(node);
4756 if (val == NULL)
4757 val = xmlStrdup((xmlChar *)"");
4758 ret = xmlDictLookup(ctxt->dict, val, -1);
4759 xmlFree(val);
4760 return(ret);
4761 }
4762
4763 static const xmlChar *
xmlSchemaGetNodeContentNoDict(xmlNodePtr node)4764 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4765 {
4766 return((const xmlChar*) xmlNodeGetContent(node));
4767 }
4768
4769 /**
4770 * xmlSchemaGetProp:
4771 * @ctxt: the parser context
4772 * @node: the node
4773 * @name: the property name
4774 *
4775 * Read a attribute value and internalize the string
4776 *
4777 * Returns the string or NULL if not present.
4778 */
4779 static const xmlChar *
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name)4780 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4781 const char *name)
4782 {
4783 xmlChar *val;
4784 const xmlChar *ret;
4785
4786 val = xmlGetNoNsProp(node, BAD_CAST name);
4787 if (val == NULL)
4788 return(NULL);
4789 ret = xmlDictLookup(ctxt->dict, val, -1);
4790 xmlFree(val);
4791 return(ret);
4792 }
4793
4794 /************************************************************************
4795 * *
4796 * Parsing functions *
4797 * *
4798 ************************************************************************/
4799
4800 #define WXS_FIND_GLOBAL_ITEM(slot) \
4801 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4802 ret = xmlHashLookup(schema->slot, name); \
4803 if (ret != NULL) goto exit; \
4804 } \
4805 if (xmlHashSize(schema->schemasImports) > 1) { \
4806 xmlSchemaImportPtr import; \
4807 if (nsName == NULL) \
4808 import = xmlHashLookup(schema->schemasImports, \
4809 XML_SCHEMAS_NO_NAMESPACE); \
4810 else \
4811 import = xmlHashLookup(schema->schemasImports, nsName); \
4812 if (import == NULL) \
4813 goto exit; \
4814 ret = xmlHashLookup(import->schema->slot, name); \
4815 }
4816
4817 /**
4818 * xmlSchemaGetElem:
4819 * @schema: the schema context
4820 * @name: the element name
4821 * @ns: the element namespace
4822 *
4823 * Lookup a global element declaration in the schema.
4824 *
4825 * Returns the element declaration or NULL if not found.
4826 */
4827 static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4828 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4829 const xmlChar * nsName)
4830 {
4831 xmlSchemaElementPtr ret = NULL;
4832
4833 if ((name == NULL) || (schema == NULL))
4834 return(NULL);
4835 if (schema != NULL) {
4836 WXS_FIND_GLOBAL_ITEM(elemDecl)
4837 }
4838 exit:
4839 #ifdef DEBUG
4840 if (ret == NULL) {
4841 if (nsName == NULL)
4842 fprintf(stderr, "Unable to lookup element decl. %s", name);
4843 else
4844 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4845 nsName);
4846 }
4847 #endif
4848 return (ret);
4849 }
4850
4851 /**
4852 * xmlSchemaGetType:
4853 * @schema: the main schema
4854 * @name: the type's name
4855 * nsName: the type's namespace
4856 *
4857 * Lookup a type in the schemas or the predefined types
4858 *
4859 * Returns the group definition or NULL if not found.
4860 */
4861 static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4862 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4863 const xmlChar * nsName)
4864 {
4865 xmlSchemaTypePtr ret = NULL;
4866
4867 if (name == NULL)
4868 return (NULL);
4869 /* First try the built-in types. */
4870 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4871 ret = xmlSchemaGetPredefinedType(name, nsName);
4872 if (ret != NULL)
4873 goto exit;
4874 /*
4875 * Note that we try the parsed schemas as well here
4876 * since one might have parsed the S4S, which contain more
4877 * than the built-in types.
4878 * TODO: Can we optimize this?
4879 */
4880 }
4881 if (schema != NULL) {
4882 WXS_FIND_GLOBAL_ITEM(typeDecl)
4883 }
4884 exit:
4885
4886 #ifdef DEBUG
4887 if (ret == NULL) {
4888 if (nsName == NULL)
4889 fprintf(stderr, "Unable to lookup type %s", name);
4890 else
4891 fprintf(stderr, "Unable to lookup type %s:%s", name,
4892 nsName);
4893 }
4894 #endif
4895 return (ret);
4896 }
4897
4898 /**
4899 * xmlSchemaGetAttributeDecl:
4900 * @schema: the context of the schema
4901 * @name: the name of the attribute
4902 * @ns: the target namespace of the attribute
4903 *
4904 * Lookup a an attribute in the schema or imported schemas
4905 *
4906 * Returns the attribute declaration or NULL if not found.
4907 */
4908 static xmlSchemaAttributePtr
xmlSchemaGetAttributeDecl(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4909 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4910 const xmlChar * nsName)
4911 {
4912 xmlSchemaAttributePtr ret = NULL;
4913
4914 if ((name == NULL) || (schema == NULL))
4915 return (NULL);
4916 if (schema != NULL) {
4917 WXS_FIND_GLOBAL_ITEM(attrDecl)
4918 }
4919 exit:
4920 #ifdef DEBUG
4921 if (ret == NULL) {
4922 if (nsName == NULL)
4923 fprintf(stderr, "Unable to lookup attribute %s", name);
4924 else
4925 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4926 nsName);
4927 }
4928 #endif
4929 return (ret);
4930 }
4931
4932 /**
4933 * xmlSchemaGetAttributeGroup:
4934 * @schema: the context of the schema
4935 * @name: the name of the attribute group
4936 * @ns: the target namespace of the attribute group
4937 *
4938 * Lookup a an attribute group in the schema or imported schemas
4939 *
4940 * Returns the attribute group definition or NULL if not found.
4941 */
4942 static xmlSchemaAttributeGroupPtr
xmlSchemaGetAttributeGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4943 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4944 const xmlChar * nsName)
4945 {
4946 xmlSchemaAttributeGroupPtr ret = NULL;
4947
4948 if ((name == NULL) || (schema == NULL))
4949 return (NULL);
4950 if (schema != NULL) {
4951 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4952 }
4953 exit:
4954 /* TODO:
4955 if ((ret != NULL) && (ret->redef != NULL)) {
4956 * Return the last redefinition. *
4957 ret = ret->redef;
4958 }
4959 */
4960 #ifdef DEBUG
4961 if (ret == NULL) {
4962 if (nsName == NULL)
4963 fprintf(stderr, "Unable to lookup attribute group %s", name);
4964 else
4965 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4966 nsName);
4967 }
4968 #endif
4969 return (ret);
4970 }
4971
4972 /**
4973 * xmlSchemaGetGroup:
4974 * @schema: the context of the schema
4975 * @name: the name of the group
4976 * @ns: the target namespace of the group
4977 *
4978 * Lookup a group in the schema or imported schemas
4979 *
4980 * Returns the group definition or NULL if not found.
4981 */
4982 static xmlSchemaModelGroupDefPtr
xmlSchemaGetGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4983 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4984 const xmlChar * nsName)
4985 {
4986 xmlSchemaModelGroupDefPtr ret = NULL;
4987
4988 if ((name == NULL) || (schema == NULL))
4989 return (NULL);
4990 if (schema != NULL) {
4991 WXS_FIND_GLOBAL_ITEM(groupDecl)
4992 }
4993 exit:
4994
4995 #ifdef DEBUG
4996 if (ret == NULL) {
4997 if (nsName == NULL)
4998 fprintf(stderr, "Unable to lookup group %s", name);
4999 else
5000 fprintf(stderr, "Unable to lookup group %s:%s", name,
5001 nsName);
5002 }
5003 #endif
5004 return (ret);
5005 }
5006
5007 static xmlSchemaNotationPtr
xmlSchemaGetNotation(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)5008 xmlSchemaGetNotation(xmlSchemaPtr schema,
5009 const xmlChar *name,
5010 const xmlChar *nsName)
5011 {
5012 xmlSchemaNotationPtr ret = NULL;
5013
5014 if ((name == NULL) || (schema == NULL))
5015 return (NULL);
5016 if (schema != NULL) {
5017 WXS_FIND_GLOBAL_ITEM(notaDecl)
5018 }
5019 exit:
5020 return (ret);
5021 }
5022
5023 static xmlSchemaIDCPtr
xmlSchemaGetIDC(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)5024 xmlSchemaGetIDC(xmlSchemaPtr schema,
5025 const xmlChar *name,
5026 const xmlChar *nsName)
5027 {
5028 xmlSchemaIDCPtr ret = NULL;
5029
5030 if ((name == NULL) || (schema == NULL))
5031 return (NULL);
5032 if (schema != NULL) {
5033 WXS_FIND_GLOBAL_ITEM(idcDef)
5034 }
5035 exit:
5036 return (ret);
5037 }
5038
5039 /**
5040 * xmlSchemaGetNamedComponent:
5041 * @schema: the schema
5042 * @name: the name of the group
5043 * @ns: the target namespace of the group
5044 *
5045 * Lookup a group in the schema or imported schemas
5046 *
5047 * Returns the group definition or NULL if not found.
5048 */
5049 static xmlSchemaBasicItemPtr
xmlSchemaGetNamedComponent(xmlSchemaPtr schema,xmlSchemaTypeType itemType,const xmlChar * name,const xmlChar * targetNs)5050 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
5051 xmlSchemaTypeType itemType,
5052 const xmlChar *name,
5053 const xmlChar *targetNs)
5054 {
5055 switch (itemType) {
5056 case XML_SCHEMA_TYPE_GROUP:
5057 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
5058 name, targetNs));
5059 case XML_SCHEMA_TYPE_ELEMENT:
5060 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
5061 name, targetNs));
5062 default:
5063 TODO
5064 return (NULL);
5065 }
5066 }
5067
5068 /************************************************************************
5069 * *
5070 * Parsing functions *
5071 * *
5072 ************************************************************************/
5073
5074 #define IS_BLANK_NODE(n) \
5075 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
5076
5077 /**
5078 * xmlSchemaIsBlank:
5079 * @str: a string
5080 * @len: the length of the string or -1
5081 *
5082 * Check if a string is ignorable
5083 *
5084 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5085 */
5086 static int
xmlSchemaIsBlank(xmlChar * str,int len)5087 xmlSchemaIsBlank(xmlChar * str, int len)
5088 {
5089 if (str == NULL)
5090 return (1);
5091 if (len < 0) {
5092 while (*str != 0) {
5093 if (!(IS_BLANK_CH(*str)))
5094 return (0);
5095 str++;
5096 }
5097 } else while ((*str != 0) && (len != 0)) {
5098 if (!(IS_BLANK_CH(*str)))
5099 return (0);
5100 str++;
5101 len--;
5102 }
5103
5104 return (1);
5105 }
5106
5107 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5108 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5109 /*
5110 * xmlSchemaFindRedefCompInGraph:
5111 * ATTENTION TODO: This uses pointer comp. for strings.
5112 */
5113 static xmlSchemaBasicItemPtr
xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName)5114 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5115 xmlSchemaTypeType type,
5116 const xmlChar *name,
5117 const xmlChar *nsName)
5118 {
5119 xmlSchemaBasicItemPtr ret;
5120 int i;
5121
5122 if ((bucket == NULL) || (name == NULL))
5123 return(NULL);
5124 if ((bucket->globals == NULL) ||
5125 (bucket->globals->nbItems == 0))
5126 goto subschemas;
5127 /*
5128 * Search in global components.
5129 */
5130 for (i = 0; i < bucket->globals->nbItems; i++) {
5131 ret = bucket->globals->items[i];
5132 if (ret->type == type) {
5133 switch (type) {
5134 case XML_SCHEMA_TYPE_COMPLEX:
5135 case XML_SCHEMA_TYPE_SIMPLE:
5136 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5137 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5138 nsName))
5139 {
5140 return(ret);
5141 }
5142 break;
5143 case XML_SCHEMA_TYPE_GROUP:
5144 if ((WXS_COMP_NAME(ret,
5145 xmlSchemaModelGroupDefPtr) == name) &&
5146 (WXS_COMP_TNS(ret,
5147 xmlSchemaModelGroupDefPtr) == nsName))
5148 {
5149 return(ret);
5150 }
5151 break;
5152 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5153 if ((WXS_COMP_NAME(ret,
5154 xmlSchemaAttributeGroupPtr) == name) &&
5155 (WXS_COMP_TNS(ret,
5156 xmlSchemaAttributeGroupPtr) == nsName))
5157 {
5158 return(ret);
5159 }
5160 break;
5161 default:
5162 /* Should not be hit. */
5163 return(NULL);
5164 }
5165 }
5166 }
5167 subschemas:
5168 /*
5169 * Process imported/included schemas.
5170 */
5171 if (bucket->relations != NULL) {
5172 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5173
5174 /*
5175 * TODO: Marking the bucket will not avoid multiple searches
5176 * in the same schema, but avoids at least circularity.
5177 */
5178 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5179 do {
5180 if ((rel->bucket != NULL) &&
5181 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5182 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5183 type, name, nsName);
5184 if (ret != NULL)
5185 return(ret);
5186 }
5187 rel = rel->next;
5188 } while (rel != NULL);
5189 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5190 }
5191 return(NULL);
5192 }
5193
5194 /**
5195 * xmlSchemaAddNotation:
5196 * @ctxt: a schema parser context
5197 * @schema: the schema being built
5198 * @name: the item name
5199 *
5200 * Add an XML schema annotation declaration
5201 * *WARNING* this interface is highly subject to change
5202 *
5203 * Returns the new structure or NULL in case of error
5204 */
5205 static xmlSchemaNotationPtr
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node ATTRIBUTE_UNUSED)5206 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5207 const xmlChar *name, const xmlChar *nsName,
5208 xmlNodePtr node ATTRIBUTE_UNUSED)
5209 {
5210 xmlSchemaNotationPtr ret = NULL;
5211
5212 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5213 return (NULL);
5214
5215 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5216 if (ret == NULL) {
5217 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5218 return (NULL);
5219 }
5220 memset(ret, 0, sizeof(xmlSchemaNotation));
5221 ret->type = XML_SCHEMA_TYPE_NOTATION;
5222 ret->name = name;
5223 ret->targetNamespace = nsName;
5224 /* TODO: do we need the node to be set?
5225 * ret->node = node;*/
5226 WXS_ADD_GLOBAL(ctxt, ret);
5227 return (ret);
5228 }
5229
5230 /**
5231 * xmlSchemaAddAttribute:
5232 * @ctxt: a schema parser context
5233 * @schema: the schema being built
5234 * @name: the item name
5235 * @namespace: the namespace
5236 *
5237 * Add an XML schema Attribute declaration
5238 * *WARNING* this interface is highly subject to change
5239 *
5240 * Returns the new structure or NULL in case of error
5241 */
5242 static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5243 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5244 const xmlChar * name, const xmlChar * nsName,
5245 xmlNodePtr node, int topLevel)
5246 {
5247 xmlSchemaAttributePtr ret = NULL;
5248
5249 if ((ctxt == NULL) || (schema == NULL))
5250 return (NULL);
5251
5252 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5253 if (ret == NULL) {
5254 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5255 return (NULL);
5256 }
5257 memset(ret, 0, sizeof(xmlSchemaAttribute));
5258 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5259 ret->node = node;
5260 ret->name = name;
5261 ret->targetNamespace = nsName;
5262
5263 if (topLevel)
5264 WXS_ADD_GLOBAL(ctxt, ret);
5265 else
5266 WXS_ADD_LOCAL(ctxt, ret);
5267 WXS_ADD_PENDING(ctxt, ret);
5268 return (ret);
5269 }
5270
5271 /**
5272 * xmlSchemaAddAttributeUse:
5273 * @ctxt: a schema parser context
5274 * @schema: the schema being built
5275 * @name: the item name
5276 * @namespace: the namespace
5277 *
5278 * Add an XML schema Attribute declaration
5279 * *WARNING* this interface is highly subject to change
5280 *
5281 * Returns the new structure or NULL in case of error
5282 */
5283 static xmlSchemaAttributeUsePtr
xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node)5284 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5285 xmlNodePtr node)
5286 {
5287 xmlSchemaAttributeUsePtr ret = NULL;
5288
5289 if (pctxt == NULL)
5290 return (NULL);
5291
5292 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5293 if (ret == NULL) {
5294 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5295 return (NULL);
5296 }
5297 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5298 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5299 ret->node = node;
5300
5301 WXS_ADD_LOCAL(pctxt, ret);
5302 return (ret);
5303 }
5304
5305 /*
5306 * xmlSchemaAddRedef:
5307 *
5308 * Adds a redefinition information. This is used at a later stage to:
5309 * resolve references to the redefined components and to check constraints.
5310 */
5311 static xmlSchemaRedefPtr
xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr targetBucket,void * item,const xmlChar * refName,const xmlChar * refTargetNs)5312 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5313 xmlSchemaBucketPtr targetBucket,
5314 void *item,
5315 const xmlChar *refName,
5316 const xmlChar *refTargetNs)
5317 {
5318 xmlSchemaRedefPtr ret;
5319
5320 ret = (xmlSchemaRedefPtr)
5321 xmlMalloc(sizeof(xmlSchemaRedef));
5322 if (ret == NULL) {
5323 xmlSchemaPErrMemory(pctxt,
5324 "allocating redefinition info", NULL);
5325 return (NULL);
5326 }
5327 memset(ret, 0, sizeof(xmlSchemaRedef));
5328 ret->item = item;
5329 ret->targetBucket = targetBucket;
5330 ret->refName = refName;
5331 ret->refTargetNs = refTargetNs;
5332 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5333 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5334 else
5335 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5336 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5337
5338 return (ret);
5339 }
5340
5341 /**
5342 * xmlSchemaAddAttributeGroupDefinition:
5343 * @ctxt: a schema parser context
5344 * @schema: the schema being built
5345 * @name: the item name
5346 * @nsName: the target namespace
5347 * @node: the corresponding node
5348 *
5349 * Add an XML schema Attribute Group definition.
5350 *
5351 * Returns the new structure or NULL in case of error
5352 */
5353 static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5354 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5355 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5356 const xmlChar *name,
5357 const xmlChar *nsName,
5358 xmlNodePtr node)
5359 {
5360 xmlSchemaAttributeGroupPtr ret = NULL;
5361
5362 if ((pctxt == NULL) || (name == NULL))
5363 return (NULL);
5364
5365 ret = (xmlSchemaAttributeGroupPtr)
5366 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5367 if (ret == NULL) {
5368 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5369 return (NULL);
5370 }
5371 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5372 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5373 ret->name = name;
5374 ret->targetNamespace = nsName;
5375 ret->node = node;
5376
5377 /* TODO: Remove the flag. */
5378 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5379 if (pctxt->isRedefine) {
5380 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5381 ret, name, nsName);
5382 if (pctxt->redef == NULL) {
5383 xmlFree(ret);
5384 return(NULL);
5385 }
5386 pctxt->redefCounter = 0;
5387 }
5388 WXS_ADD_GLOBAL(pctxt, ret);
5389 WXS_ADD_PENDING(pctxt, ret);
5390 return (ret);
5391 }
5392
5393 /**
5394 * xmlSchemaAddElement:
5395 * @ctxt: a schema parser context
5396 * @schema: the schema being built
5397 * @name: the type name
5398 * @namespace: the type namespace
5399 *
5400 * Add an XML schema Element declaration
5401 * *WARNING* this interface is highly subject to change
5402 *
5403 * Returns the new structure or NULL in case of error
5404 */
5405 static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5406 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5407 const xmlChar * name, const xmlChar * nsName,
5408 xmlNodePtr node, int topLevel)
5409 {
5410 xmlSchemaElementPtr ret = NULL;
5411
5412 if ((ctxt == NULL) || (name == NULL))
5413 return (NULL);
5414
5415 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5416 if (ret == NULL) {
5417 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5418 return (NULL);
5419 }
5420 memset(ret, 0, sizeof(xmlSchemaElement));
5421 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5422 ret->name = name;
5423 ret->targetNamespace = nsName;
5424 ret->node = node;
5425
5426 if (topLevel)
5427 WXS_ADD_GLOBAL(ctxt, ret);
5428 else
5429 WXS_ADD_LOCAL(ctxt, ret);
5430 WXS_ADD_PENDING(ctxt, ret);
5431 return (ret);
5432 }
5433
5434 /**
5435 * xmlSchemaAddType:
5436 * @ctxt: a schema parser context
5437 * @schema: the schema being built
5438 * @name: the item name
5439 * @namespace: the namespace
5440 *
5441 * Add an XML schema item
5442 * *WARNING* this interface is highly subject to change
5443 *
5444 * Returns the new structure or NULL in case of error
5445 */
5446 static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5447 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5448 xmlSchemaTypeType type,
5449 const xmlChar * name, const xmlChar * nsName,
5450 xmlNodePtr node, int topLevel)
5451 {
5452 xmlSchemaTypePtr ret = NULL;
5453
5454 if ((ctxt == NULL) || (schema == NULL))
5455 return (NULL);
5456
5457 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5458 if (ret == NULL) {
5459 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5460 return (NULL);
5461 }
5462 memset(ret, 0, sizeof(xmlSchemaType));
5463 ret->type = type;
5464 ret->name = name;
5465 ret->targetNamespace = nsName;
5466 ret->node = node;
5467 if (topLevel) {
5468 if (ctxt->isRedefine) {
5469 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5470 ret, name, nsName);
5471 if (ctxt->redef == NULL) {
5472 xmlFree(ret);
5473 return(NULL);
5474 }
5475 ctxt->redefCounter = 0;
5476 }
5477 WXS_ADD_GLOBAL(ctxt, ret);
5478 } else
5479 WXS_ADD_LOCAL(ctxt, ret);
5480 WXS_ADD_PENDING(ctxt, ret);
5481 return (ret);
5482 }
5483
5484 static xmlSchemaQNameRefPtr
xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypeType refType,const xmlChar * refName,const xmlChar * refNs)5485 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5486 xmlSchemaTypeType refType,
5487 const xmlChar *refName,
5488 const xmlChar *refNs)
5489 {
5490 xmlSchemaQNameRefPtr ret;
5491
5492 ret = (xmlSchemaQNameRefPtr)
5493 xmlMalloc(sizeof(xmlSchemaQNameRef));
5494 if (ret == NULL) {
5495 xmlSchemaPErrMemory(pctxt,
5496 "allocating QName reference item", NULL);
5497 return (NULL);
5498 }
5499 ret->node = NULL;
5500 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5501 ret->name = refName;
5502 ret->targetNamespace = refNs;
5503 ret->item = NULL;
5504 ret->itemType = refType;
5505 /*
5506 * Store the reference item in the schema.
5507 */
5508 WXS_ADD_LOCAL(pctxt, ret);
5509 return (ret);
5510 }
5511
5512 static xmlSchemaAttributeUseProhibPtr
xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)5513 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5514 {
5515 xmlSchemaAttributeUseProhibPtr ret;
5516
5517 ret = (xmlSchemaAttributeUseProhibPtr)
5518 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5519 if (ret == NULL) {
5520 xmlSchemaPErrMemory(pctxt,
5521 "allocating attribute use prohibition", NULL);
5522 return (NULL);
5523 }
5524 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5525 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5526 WXS_ADD_LOCAL(pctxt, ret);
5527 return (ret);
5528 }
5529
5530
5531 /**
5532 * xmlSchemaAddModelGroup:
5533 * @ctxt: a schema parser context
5534 * @schema: the schema being built
5535 * @type: the "compositor" type of the model group
5536 * @node: the node in the schema doc
5537 *
5538 * Adds a schema model group
5539 * *WARNING* this interface is highly subject to change
5540 *
5541 * Returns the new structure or NULL in case of error
5542 */
5543 static xmlSchemaModelGroupPtr
xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5544 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5545 xmlSchemaPtr schema,
5546 xmlSchemaTypeType type,
5547 xmlNodePtr node)
5548 {
5549 xmlSchemaModelGroupPtr ret = NULL;
5550
5551 if ((ctxt == NULL) || (schema == NULL))
5552 return (NULL);
5553
5554 ret = (xmlSchemaModelGroupPtr)
5555 xmlMalloc(sizeof(xmlSchemaModelGroup));
5556 if (ret == NULL) {
5557 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5558 NULL);
5559 return (NULL);
5560 }
5561 memset(ret, 0, sizeof(xmlSchemaModelGroup));
5562 ret->type = type;
5563 ret->node = node;
5564 WXS_ADD_LOCAL(ctxt, ret);
5565 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5566 (type == XML_SCHEMA_TYPE_CHOICE))
5567 WXS_ADD_PENDING(ctxt, ret);
5568 return (ret);
5569 }
5570
5571
5572 /**
5573 * xmlSchemaAddParticle:
5574 * @ctxt: a schema parser context
5575 * @schema: the schema being built
5576 * @node: the corresponding node in the schema doc
5577 * @min: the minOccurs
5578 * @max: the maxOccurs
5579 *
5580 * Adds an XML schema particle component.
5581 * *WARNING* this interface is highly subject to change
5582 *
5583 * Returns the new structure or NULL in case of error
5584 */
5585 static xmlSchemaParticlePtr
xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max)5586 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5587 xmlNodePtr node, int min, int max)
5588 {
5589 xmlSchemaParticlePtr ret = NULL;
5590 if (ctxt == NULL)
5591 return (NULL);
5592
5593 #ifdef DEBUG
5594 fprintf(stderr, "Adding particle component\n");
5595 #endif
5596 ret = (xmlSchemaParticlePtr)
5597 xmlMalloc(sizeof(xmlSchemaParticle));
5598 if (ret == NULL) {
5599 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5600 NULL);
5601 return (NULL);
5602 }
5603 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5604 ret->annot = NULL;
5605 ret->node = node;
5606 ret->minOccurs = min;
5607 ret->maxOccurs = max;
5608 ret->next = NULL;
5609 ret->children = NULL;
5610
5611 WXS_ADD_LOCAL(ctxt, ret);
5612 /*
5613 * Note that addition to pending components will be done locally
5614 * to the specific parsing function, since the most particles
5615 * need not to be fixed up (i.e. the reference to be resolved).
5616 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5617 */
5618 return (ret);
5619 }
5620
5621 /**
5622 * xmlSchemaAddModelGroupDefinition:
5623 * @ctxt: a schema validation context
5624 * @schema: the schema being built
5625 * @name: the group name
5626 *
5627 * Add an XML schema Group definition
5628 *
5629 * Returns the new structure or NULL in case of error
5630 */
5631 static xmlSchemaModelGroupDefPtr
xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5632 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5633 xmlSchemaPtr schema,
5634 const xmlChar *name,
5635 const xmlChar *nsName,
5636 xmlNodePtr node)
5637 {
5638 xmlSchemaModelGroupDefPtr ret = NULL;
5639
5640 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5641 return (NULL);
5642
5643 ret = (xmlSchemaModelGroupDefPtr)
5644 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5645 if (ret == NULL) {
5646 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5647 return (NULL);
5648 }
5649 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5650 ret->name = name;
5651 ret->type = XML_SCHEMA_TYPE_GROUP;
5652 ret->node = node;
5653 ret->targetNamespace = nsName;
5654
5655 if (ctxt->isRedefine) {
5656 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5657 ret, name, nsName);
5658 if (ctxt->redef == NULL) {
5659 xmlFree(ret);
5660 return(NULL);
5661 }
5662 ctxt->redefCounter = 0;
5663 }
5664 WXS_ADD_GLOBAL(ctxt, ret);
5665 WXS_ADD_PENDING(ctxt, ret);
5666 return (ret);
5667 }
5668
5669 /**
5670 * xmlSchemaNewWildcardNs:
5671 * @ctxt: a schema validation context
5672 *
5673 * Creates a new wildcard namespace constraint.
5674 *
5675 * Returns the new structure or NULL in case of error
5676 */
5677 static xmlSchemaWildcardNsPtr
xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)5678 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5679 {
5680 xmlSchemaWildcardNsPtr ret;
5681
5682 ret = (xmlSchemaWildcardNsPtr)
5683 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5684 if (ret == NULL) {
5685 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5686 return (NULL);
5687 }
5688 ret->value = NULL;
5689 ret->next = NULL;
5690 return (ret);
5691 }
5692
5693 static xmlSchemaIDCPtr
xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,int category,xmlNodePtr node)5694 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5695 const xmlChar *name, const xmlChar *nsName,
5696 int category, xmlNodePtr node)
5697 {
5698 xmlSchemaIDCPtr ret = NULL;
5699
5700 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5701 return (NULL);
5702
5703 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5704 if (ret == NULL) {
5705 xmlSchemaPErrMemory(ctxt,
5706 "allocating an identity-constraint definition", NULL);
5707 return (NULL);
5708 }
5709 memset(ret, 0, sizeof(xmlSchemaIDC));
5710 /* The target namespace of the parent element declaration. */
5711 ret->targetNamespace = nsName;
5712 ret->name = name;
5713 ret->type = category;
5714 ret->node = node;
5715
5716 WXS_ADD_GLOBAL(ctxt, ret);
5717 /*
5718 * Only keyrefs need to be fixup up.
5719 */
5720 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5721 WXS_ADD_PENDING(ctxt, ret);
5722 return (ret);
5723 }
5724
5725 /**
5726 * xmlSchemaAddWildcard:
5727 * @ctxt: a schema validation context
5728 * @schema: a schema
5729 *
5730 * Adds a wildcard.
5731 * It corresponds to a xsd:anyAttribute and xsd:any.
5732 *
5733 * Returns the new structure or NULL in case of error
5734 */
5735 static xmlSchemaWildcardPtr
xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5736 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5737 xmlSchemaTypeType type, xmlNodePtr node)
5738 {
5739 xmlSchemaWildcardPtr ret = NULL;
5740
5741 if ((ctxt == NULL) || (schema == NULL))
5742 return (NULL);
5743
5744 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5745 if (ret == NULL) {
5746 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5747 return (NULL);
5748 }
5749 memset(ret, 0, sizeof(xmlSchemaWildcard));
5750 ret->type = type;
5751 ret->node = node;
5752 WXS_ADD_LOCAL(ctxt, ret);
5753 return (ret);
5754 }
5755
5756 static void
xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)5757 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5758 {
5759 if (group == NULL)
5760 return;
5761 if (group->members != NULL)
5762 xmlSchemaItemListFree(group->members);
5763 xmlFree(group);
5764 }
5765
5766 static void
xmlSchemaSubstGroupFreeEntry(void * group,const xmlChar * name ATTRIBUTE_UNUSED)5767 xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5768 {
5769 xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5770 }
5771
5772 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5773 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5774 xmlSchemaElementPtr head)
5775 {
5776 xmlSchemaSubstGroupPtr ret;
5777
5778 /* Init subst group hash. */
5779 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5780 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5781 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5782 return(NULL);
5783 }
5784 /* Create a new substitution group. */
5785 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5786 if (ret == NULL) {
5787 xmlSchemaPErrMemory(NULL,
5788 "allocating a substitution group container", NULL);
5789 return(NULL);
5790 }
5791 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5792 ret->head = head;
5793 /* Create list of members. */
5794 ret->members = xmlSchemaItemListCreate();
5795 if (ret->members == NULL) {
5796 xmlSchemaSubstGroupFree(ret);
5797 return(NULL);
5798 }
5799 /* Add subst group to hash. */
5800 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5801 head->name, head->targetNamespace, ret) != 0) {
5802 PERROR_INT("xmlSchemaSubstGroupAdd",
5803 "failed to add a new substitution container");
5804 xmlSchemaSubstGroupFree(ret);
5805 return(NULL);
5806 }
5807 return(ret);
5808 }
5809
5810 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5811 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5812 xmlSchemaElementPtr head)
5813 {
5814 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5815 return(NULL);
5816 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5817 head->name, head->targetNamespace));
5818
5819 }
5820
5821 /**
5822 * xmlSchemaAddElementSubstitutionMember:
5823 * @pctxt: a schema parser context
5824 * @head: the head of the substitution group
5825 * @member: the new member of the substitution group
5826 *
5827 * Allocate a new annotation structure.
5828 *
5829 * Returns the newly allocated structure or NULL in case or error
5830 */
5831 static int
xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head,xmlSchemaElementPtr member)5832 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5833 xmlSchemaElementPtr head,
5834 xmlSchemaElementPtr member)
5835 {
5836 xmlSchemaSubstGroupPtr substGroup = NULL;
5837
5838 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5839 return (-1);
5840
5841 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5842 if (substGroup == NULL)
5843 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5844 if (substGroup == NULL)
5845 return(-1);
5846 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5847 return(-1);
5848 return(0);
5849 }
5850
5851 /************************************************************************
5852 * *
5853 * Utilities for parsing *
5854 * *
5855 ************************************************************************/
5856
5857 /**
5858 * xmlSchemaPValAttrNodeQNameValue:
5859 * @ctxt: a schema parser context
5860 * @schema: the schema context
5861 * @ownerItem: the parent as a schema object
5862 * @value: the QName value
5863 * @uri: the resulting namespace URI if found
5864 * @local: the resulting local part if found, the attribute value otherwise
5865 *
5866 * Extracts the local name and the URI of a QName value and validates it.
5867 * This one is intended to be used on attribute values that
5868 * should resolve to schema components.
5869 *
5870 * Returns 0, in case the QName is valid, a positive error code
5871 * if not valid and -1 if an internal error occurs.
5872 */
5873 static int
xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,const xmlChar ** uri,const xmlChar ** local)5874 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5875 xmlSchemaPtr schema,
5876 xmlSchemaBasicItemPtr ownerItem,
5877 xmlAttrPtr attr,
5878 const xmlChar *value,
5879 const xmlChar **uri,
5880 const xmlChar **local)
5881 {
5882 const xmlChar *pref;
5883 xmlNsPtr ns;
5884 int len, ret;
5885
5886 *uri = NULL;
5887 *local = NULL;
5888 ret = xmlValidateQName(value, 1);
5889 if (ret > 0) {
5890 xmlSchemaPSimpleTypeErr(ctxt,
5891 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5892 ownerItem, (xmlNodePtr) attr,
5893 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5894 NULL, value, NULL, NULL, NULL);
5895 *local = value;
5896 return (ctxt->err);
5897 } else if (ret < 0)
5898 return (-1);
5899
5900 if (!strchr((char *) value, ':')) {
5901 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5902 if (ns && ns->href && ns->href[0])
5903 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5904 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5905 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5906 * parser context. */
5907 /*
5908 * This one takes care of included schemas with no
5909 * target namespace.
5910 */
5911 *uri = ctxt->targetNamespace;
5912 }
5913 *local = xmlDictLookup(ctxt->dict, value, -1);
5914 return (0);
5915 }
5916 /*
5917 * At this point xmlSplitQName3 has to return a local name.
5918 */
5919 *local = xmlSplitQName3(value, &len);
5920 *local = xmlDictLookup(ctxt->dict, *local, -1);
5921 pref = xmlDictLookup(ctxt->dict, value, len);
5922 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5923 if (ns == NULL) {
5924 xmlSchemaPSimpleTypeErr(ctxt,
5925 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5926 ownerItem, (xmlNodePtr) attr,
5927 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5928 "The value '%s' of simple type 'xs:QName' has no "
5929 "corresponding namespace declaration in scope", value, NULL);
5930 return (ctxt->err);
5931 } else {
5932 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5933 }
5934 return (0);
5935 }
5936
5937 /**
5938 * xmlSchemaPValAttrNodeQName:
5939 * @ctxt: a schema parser context
5940 * @schema: the schema context
5941 * @ownerItem: the owner as a schema object
5942 * @attr: the attribute node
5943 * @uri: the resulting namespace URI if found
5944 * @local: the resulting local part if found, the attribute value otherwise
5945 *
5946 * Extracts and validates the QName of an attribute value.
5947 * This one is intended to be used on attribute values that
5948 * should resolve to schema components.
5949 *
5950 * Returns 0, in case the QName is valid, a positive error code
5951 * if not valid and -1 if an internal error occurs.
5952 */
5953 static int
xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar ** uri,const xmlChar ** local)5954 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5955 xmlSchemaPtr schema,
5956 xmlSchemaBasicItemPtr ownerItem,
5957 xmlAttrPtr attr,
5958 const xmlChar **uri,
5959 const xmlChar **local)
5960 {
5961 const xmlChar *value;
5962
5963 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5964 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5965 ownerItem, attr, value, uri, local));
5966 }
5967
5968 /**
5969 * xmlSchemaPValAttrQName:
5970 * @ctxt: a schema parser context
5971 * @schema: the schema context
5972 * @ownerItem: the owner as a schema object
5973 * @ownerElem: the parent node of the attribute
5974 * @name: the name of the attribute
5975 * @uri: the resulting namespace URI if found
5976 * @local: the resulting local part if found, the attribute value otherwise
5977 *
5978 * Extracts and validates the QName of an attribute value.
5979 *
5980 * Returns 0, in case the QName is valid, a positive error code
5981 * if not valid and -1 if an internal error occurs.
5982 */
5983 static int
xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar ** uri,const xmlChar ** local)5984 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5985 xmlSchemaPtr schema,
5986 xmlSchemaBasicItemPtr ownerItem,
5987 xmlNodePtr ownerElem,
5988 const char *name,
5989 const xmlChar **uri,
5990 const xmlChar **local)
5991 {
5992 xmlAttrPtr attr;
5993
5994 attr = xmlSchemaGetPropNode(ownerElem, name);
5995 if (attr == NULL) {
5996 *local = NULL;
5997 *uri = NULL;
5998 return (0);
5999 }
6000 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
6001 ownerItem, attr, uri, local));
6002 }
6003
6004 /**
6005 * xmlSchemaPValAttrID:
6006 * @ctxt: a schema parser context
6007 *
6008 * Extracts and validates the ID of an attribute value.
6009 *
6010 * Returns 0, in case the ID is valid, a positive error code
6011 * if not valid and -1 if an internal error occurs.
6012 */
6013 static int
xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt,xmlAttrPtr attr)6014 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
6015 {
6016 int ret;
6017 const xmlChar *value;
6018
6019 if (attr == NULL)
6020 return(0);
6021 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
6022 ret = xmlValidateNCName(value, 1);
6023 if (ret == 0) {
6024 /*
6025 * NOTE: the IDness might have already be declared in the DTD
6026 */
6027 if (attr->atype != XML_ATTRIBUTE_ID) {
6028 xmlIDPtr res;
6029 xmlChar *strip;
6030
6031 /*
6032 * TODO: Use xmlSchemaStrip here; it's not exported at this
6033 * moment.
6034 */
6035 strip = xmlSchemaCollapseString(value);
6036 if (strip != NULL) {
6037 xmlFree((xmlChar *) value);
6038 value = strip;
6039 }
6040 res = xmlAddID(NULL, attr->doc, value, attr);
6041 if (res == NULL) {
6042 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6043 xmlSchemaPSimpleTypeErr(ctxt,
6044 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6045 NULL, (xmlNodePtr) attr,
6046 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6047 NULL, NULL, "Duplicate value '%s' of simple "
6048 "type 'xs:ID'", value, NULL);
6049 } else
6050 attr->atype = XML_ATTRIBUTE_ID;
6051 }
6052 } else if (ret > 0) {
6053 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6054 xmlSchemaPSimpleTypeErr(ctxt,
6055 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6056 NULL, (xmlNodePtr) attr,
6057 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6058 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
6059 "not a valid 'xs:NCName'",
6060 value, NULL);
6061 }
6062 if (value != NULL)
6063 xmlFree((xmlChar *)value);
6064
6065 return (ret);
6066 }
6067
6068 static int
xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr ownerElem,const xmlChar * name)6069 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
6070 xmlNodePtr ownerElem,
6071 const xmlChar *name)
6072 {
6073 xmlAttrPtr attr;
6074
6075 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
6076 if (attr == NULL)
6077 return(0);
6078 return(xmlSchemaPValAttrNodeID(ctxt, attr));
6079
6080 }
6081
6082 /**
6083 * xmlGetMaxOccurs:
6084 * @ctxt: a schema validation context
6085 * @node: a subtree containing XML Schema information
6086 *
6087 * Get the maxOccurs property
6088 *
6089 * Returns the default if not found, or the value
6090 */
6091 static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6092 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6093 int min, int max, int def, const char *expected)
6094 {
6095 const xmlChar *val, *cur;
6096 int ret = 0;
6097 xmlAttrPtr attr;
6098
6099 attr = xmlSchemaGetPropNode(node, "maxOccurs");
6100 if (attr == NULL)
6101 return (def);
6102 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6103
6104 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6105 if (max != UNBOUNDED) {
6106 xmlSchemaPSimpleTypeErr(ctxt,
6107 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6108 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6109 NULL, (xmlNodePtr) attr, NULL, expected,
6110 val, NULL, NULL, NULL);
6111 return (def);
6112 } else
6113 return (UNBOUNDED); /* encoding it with -1 might be another option */
6114 }
6115
6116 cur = val;
6117 while (IS_BLANK_CH(*cur))
6118 cur++;
6119 if (*cur == 0) {
6120 xmlSchemaPSimpleTypeErr(ctxt,
6121 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6122 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6123 NULL, (xmlNodePtr) attr, NULL, expected,
6124 val, NULL, NULL, NULL);
6125 return (def);
6126 }
6127 while ((*cur >= '0') && (*cur <= '9')) {
6128 if (ret > INT_MAX / 10) {
6129 ret = INT_MAX;
6130 } else {
6131 int digit = *cur - '0';
6132 ret *= 10;
6133 if (ret > INT_MAX - digit)
6134 ret = INT_MAX;
6135 else
6136 ret += digit;
6137 }
6138 cur++;
6139 }
6140 while (IS_BLANK_CH(*cur))
6141 cur++;
6142 /*
6143 * TODO: Restrict the maximal value to Integer.
6144 */
6145 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6146 xmlSchemaPSimpleTypeErr(ctxt,
6147 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6148 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6149 NULL, (xmlNodePtr) attr, NULL, expected,
6150 val, NULL, NULL, NULL);
6151 return (def);
6152 }
6153 return (ret);
6154 }
6155
6156 /**
6157 * xmlGetMinOccurs:
6158 * @ctxt: a schema validation context
6159 * @node: a subtree containing XML Schema information
6160 *
6161 * Get the minOccurs property
6162 *
6163 * Returns the default if not found, or the value
6164 */
6165 static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6166 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6167 int min, int max, int def, const char *expected)
6168 {
6169 const xmlChar *val, *cur;
6170 int ret = 0;
6171 xmlAttrPtr attr;
6172
6173 attr = xmlSchemaGetPropNode(node, "minOccurs");
6174 if (attr == NULL)
6175 return (def);
6176 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6177 cur = val;
6178 while (IS_BLANK_CH(*cur))
6179 cur++;
6180 if (*cur == 0) {
6181 xmlSchemaPSimpleTypeErr(ctxt,
6182 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6183 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6184 NULL, (xmlNodePtr) attr, NULL, expected,
6185 val, NULL, NULL, NULL);
6186 return (def);
6187 }
6188 while ((*cur >= '0') && (*cur <= '9')) {
6189 if (ret > INT_MAX / 10) {
6190 ret = INT_MAX;
6191 } else {
6192 int digit = *cur - '0';
6193 ret *= 10;
6194 if (ret > INT_MAX - digit)
6195 ret = INT_MAX;
6196 else
6197 ret += digit;
6198 }
6199 cur++;
6200 }
6201 while (IS_BLANK_CH(*cur))
6202 cur++;
6203 /*
6204 * TODO: Restrict the maximal value to Integer.
6205 */
6206 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6207 xmlSchemaPSimpleTypeErr(ctxt,
6208 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6209 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6210 NULL, (xmlNodePtr) attr, NULL, expected,
6211 val, NULL, NULL, NULL);
6212 return (def);
6213 }
6214 return (ret);
6215 }
6216
6217 /**
6218 * xmlSchemaPGetBoolNodeValue:
6219 * @ctxt: a schema validation context
6220 * @ownerItem: the owner as a schema item
6221 * @node: the node holding the value
6222 *
6223 * Converts a boolean string value into 1 or 0.
6224 *
6225 * Returns 0 or 1.
6226 */
6227 static int
xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr node)6228 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6229 xmlSchemaBasicItemPtr ownerItem,
6230 xmlNodePtr node)
6231 {
6232 xmlChar *value = NULL;
6233 int res = 0;
6234
6235 value = xmlNodeGetContent(node);
6236 /*
6237 * 3.2.2.1 Lexical representation
6238 * An instance of a datatype that is defined as `boolean`
6239 * can have the following legal literals {true, false, 1, 0}.
6240 */
6241 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6242 res = 1;
6243 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6244 res = 0;
6245 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6246 res = 1;
6247 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6248 res = 0;
6249 else {
6250 xmlSchemaPSimpleTypeErr(ctxt,
6251 XML_SCHEMAP_INVALID_BOOLEAN,
6252 ownerItem, node,
6253 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6254 NULL, BAD_CAST value,
6255 NULL, NULL, NULL);
6256 }
6257 if (value != NULL)
6258 xmlFree(value);
6259 return (res);
6260 }
6261
6262 /**
6263 * xmlGetBooleanProp:
6264 * @ctxt: a schema validation context
6265 * @node: a subtree containing XML Schema information
6266 * @name: the attribute name
6267 * @def: the default value
6268 *
6269 * Evaluate if a boolean property is set
6270 *
6271 * Returns the default if not found, 0 if found to be false,
6272 * 1 if found to be true
6273 */
6274 static int
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,int def)6275 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6276 xmlNodePtr node,
6277 const char *name, int def)
6278 {
6279 const xmlChar *val;
6280
6281 val = xmlSchemaGetProp(ctxt, node, name);
6282 if (val == NULL)
6283 return (def);
6284 /*
6285 * 3.2.2.1 Lexical representation
6286 * An instance of a datatype that is defined as `boolean`
6287 * can have the following legal literals {true, false, 1, 0}.
6288 */
6289 if (xmlStrEqual(val, BAD_CAST "true"))
6290 def = 1;
6291 else if (xmlStrEqual(val, BAD_CAST "false"))
6292 def = 0;
6293 else if (xmlStrEqual(val, BAD_CAST "1"))
6294 def = 1;
6295 else if (xmlStrEqual(val, BAD_CAST "0"))
6296 def = 0;
6297 else {
6298 xmlSchemaPSimpleTypeErr(ctxt,
6299 XML_SCHEMAP_INVALID_BOOLEAN,
6300 NULL,
6301 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6302 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6303 NULL, val, NULL, NULL, NULL);
6304 }
6305 return (def);
6306 }
6307
6308 /************************************************************************
6309 * *
6310 * Schema extraction from an Infoset *
6311 * *
6312 ************************************************************************/
6313 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6314 ctxt, xmlSchemaPtr schema,
6315 xmlNodePtr node,
6316 int topLevel);
6317 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6318 ctxt,
6319 xmlSchemaPtr schema,
6320 xmlNodePtr node,
6321 int topLevel);
6322 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6323 ctxt,
6324 xmlSchemaPtr schema,
6325 xmlNodePtr node,
6326 xmlSchemaTypeType parentType);
6327 static xmlSchemaBasicItemPtr
6328 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6329 xmlSchemaPtr schema,
6330 xmlNodePtr node,
6331 xmlSchemaItemListPtr uses,
6332 int parentType);
6333 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6334 xmlSchemaPtr schema,
6335 xmlNodePtr node);
6336 static xmlSchemaWildcardPtr
6337 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6338 xmlSchemaPtr schema, xmlNodePtr node);
6339
6340 /**
6341 * xmlSchemaPValAttrNodeValue:
6342 *
6343 * @pctxt: a schema parser context
6344 * @ownerItem: the schema object owner if existent
6345 * @attr: the schema attribute node being validated
6346 * @value: the value
6347 * @type: the built-in type to be validated against
6348 *
6349 * Validates a value against the given built-in type.
6350 * This one is intended to be used internally for validation
6351 * of schema attribute values during parsing of the schema.
6352 *
6353 * Returns 0 if the value is valid, a positive error code
6354 * number otherwise and -1 in case of an internal or API error.
6355 */
6356 static int
xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,xmlSchemaTypePtr type)6357 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6358 xmlSchemaBasicItemPtr ownerItem,
6359 xmlAttrPtr attr,
6360 const xmlChar *value,
6361 xmlSchemaTypePtr type)
6362 {
6363
6364 int ret = 0;
6365
6366 /*
6367 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6368 * one is really meant to be used internally, so better not.
6369 */
6370 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6371 return (-1);
6372 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6373 PERROR_INT("xmlSchemaPValAttrNodeValue",
6374 "the given type is not a built-in type");
6375 return (-1);
6376 }
6377 switch (type->builtInType) {
6378 case XML_SCHEMAS_NCNAME:
6379 case XML_SCHEMAS_QNAME:
6380 case XML_SCHEMAS_ANYURI:
6381 case XML_SCHEMAS_TOKEN:
6382 case XML_SCHEMAS_LANGUAGE:
6383 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6384 (xmlNodePtr) attr);
6385 break;
6386 default: {
6387 PERROR_INT("xmlSchemaPValAttrNodeValue",
6388 "validation using the given type is not supported while "
6389 "parsing a schema");
6390 return (-1);
6391 }
6392 }
6393 /*
6394 * TODO: Should we use the S4S error codes instead?
6395 */
6396 if (ret < 0) {
6397 PERROR_INT("xmlSchemaPValAttrNodeValue",
6398 "failed to validate a schema attribute value");
6399 return (-1);
6400 } else if (ret > 0) {
6401 if (WXS_IS_LIST(type))
6402 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6403 else
6404 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6405 xmlSchemaPSimpleTypeErr(pctxt,
6406 ret, ownerItem, (xmlNodePtr) attr,
6407 type, NULL, value, NULL, NULL, NULL);
6408 }
6409 return (ret);
6410 }
6411
6412 /**
6413 * xmlSchemaPValAttrNode:
6414 *
6415 * @ctxt: a schema parser context
6416 * @ownerItem: the schema object owner if existent
6417 * @attr: the schema attribute node being validated
6418 * @type: the built-in type to be validated against
6419 * @value: the resulting value if any
6420 *
6421 * Extracts and validates a value against the given built-in type.
6422 * This one is intended to be used internally for validation
6423 * of schema attribute values during parsing of the schema.
6424 *
6425 * Returns 0 if the value is valid, a positive error code
6426 * number otherwise and -1 in case of an internal or API error.
6427 */
6428 static int
xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,xmlSchemaTypePtr type,const xmlChar ** value)6429 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6430 xmlSchemaBasicItemPtr ownerItem,
6431 xmlAttrPtr attr,
6432 xmlSchemaTypePtr type,
6433 const xmlChar **value)
6434 {
6435 const xmlChar *val;
6436
6437 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6438 return (-1);
6439
6440 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6441 if (value != NULL)
6442 *value = val;
6443
6444 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6445 val, type));
6446 }
6447
6448 /**
6449 * xmlSchemaPValAttr:
6450 *
6451 * @ctxt: a schema parser context
6452 * @node: the element node of the attribute
6453 * @ownerItem: the schema object owner if existent
6454 * @ownerElem: the owner element node
6455 * @name: the name of the schema attribute node
6456 * @type: the built-in type to be validated against
6457 * @value: the resulting value if any
6458 *
6459 * Extracts and validates a value against the given built-in type.
6460 * This one is intended to be used internally for validation
6461 * of schema attribute values during parsing of the schema.
6462 *
6463 * Returns 0 if the value is valid, a positive error code
6464 * number otherwise and -1 in case of an internal or API error.
6465 */
6466 static int
xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,xmlSchemaTypePtr type,const xmlChar ** value)6467 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6468 xmlSchemaBasicItemPtr ownerItem,
6469 xmlNodePtr ownerElem,
6470 const char *name,
6471 xmlSchemaTypePtr type,
6472 const xmlChar **value)
6473 {
6474 xmlAttrPtr attr;
6475
6476 if ((ctxt == NULL) || (type == NULL)) {
6477 if (value != NULL)
6478 *value = NULL;
6479 return (-1);
6480 }
6481 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6482 if (value != NULL)
6483 *value = NULL;
6484 xmlSchemaPErr(ctxt, ownerElem,
6485 XML_SCHEMAP_INTERNAL,
6486 "Internal error: xmlSchemaPValAttr, the given "
6487 "type '%s' is not a built-in type.\n",
6488 type->name, NULL);
6489 return (-1);
6490 }
6491 attr = xmlSchemaGetPropNode(ownerElem, name);
6492 if (attr == NULL) {
6493 if (value != NULL)
6494 *value = NULL;
6495 return (0);
6496 }
6497 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6498 type, value));
6499 }
6500
6501 static int
xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlNodePtr node,xmlAttrPtr attr,const xmlChar * namespaceName)6502 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6503 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6504 xmlNodePtr node,
6505 xmlAttrPtr attr,
6506 const xmlChar *namespaceName)
6507 {
6508 /* TODO: Pointer comparison instead? */
6509 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6510 return (0);
6511 if (xmlStrEqual(xmlSchemaNs, namespaceName))
6512 return (0);
6513 /*
6514 * Check if the referenced namespace was <import>ed.
6515 */
6516 if (WXS_BUCKET(pctxt)->relations != NULL) {
6517 xmlSchemaSchemaRelationPtr rel;
6518
6519 rel = WXS_BUCKET(pctxt)->relations;
6520 do {
6521 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6522 xmlStrEqual(namespaceName, rel->importNamespace))
6523 return (0);
6524 rel = rel->next;
6525 } while (rel != NULL);
6526 }
6527 /*
6528 * No matching <import>ed namespace found.
6529 */
6530 {
6531 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6532
6533 if (namespaceName == NULL)
6534 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6535 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6536 "References from this schema to components in no "
6537 "namespace are not allowed, since not indicated by an "
6538 "import statement", NULL, NULL);
6539 else
6540 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6541 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6542 "References from this schema to components in the "
6543 "namespace '%s' are not allowed, since not indicated by an "
6544 "import statement", namespaceName, NULL);
6545 }
6546 return (XML_SCHEMAP_SRC_RESOLVE);
6547 }
6548
6549 /**
6550 * xmlSchemaParseLocalAttributes:
6551 * @ctxt: a schema validation context
6552 * @schema: the schema being built
6553 * @node: a subtree containing XML Schema information
6554 * @type: the hosting type where the attributes will be anchored
6555 *
6556 * Parses attribute uses and attribute declarations and
6557 * attribute group references.
6558 */
6559 static int
xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr * child,xmlSchemaItemListPtr * list,int parentType,int * hasRefs)6560 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6561 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6562 int parentType, int *hasRefs)
6563 {
6564 void *item;
6565
6566 while ((IS_SCHEMA((*child), "attribute")) ||
6567 (IS_SCHEMA((*child), "attributeGroup"))) {
6568 if (IS_SCHEMA((*child), "attribute")) {
6569 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6570 *list, parentType);
6571 } else {
6572 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6573 if ((item != NULL) && (hasRefs != NULL))
6574 *hasRefs = 1;
6575 }
6576 if (item != NULL) {
6577 if (*list == NULL) {
6578 /* TODO: Customize grow factor. */
6579 *list = xmlSchemaItemListCreate();
6580 if (*list == NULL)
6581 return(-1);
6582 }
6583 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6584 return(-1);
6585 }
6586 *child = (*child)->next;
6587 }
6588 return (0);
6589 }
6590
6591 /**
6592 * xmlSchemaParseAnnotation:
6593 * @ctxt: a schema validation context
6594 * @schema: the schema being built
6595 * @node: a subtree containing XML Schema information
6596 *
6597 * parse a XML schema Attribute declaration
6598 * *WARNING* this interface is highly subject to change
6599 *
6600 * Returns -1 in case of error, 0 if the declaration is improper and
6601 * 1 in case of success.
6602 */
6603 static xmlSchemaAnnotPtr
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int needed)6604 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6605 {
6606 xmlSchemaAnnotPtr ret;
6607 xmlNodePtr child = NULL;
6608 xmlAttrPtr attr;
6609 int barked = 0;
6610
6611 /*
6612 * INFO: S4S completed.
6613 */
6614 /*
6615 * id = ID
6616 * {any attributes with non-schema namespace . . .}>
6617 * Content: (appinfo | documentation)*
6618 */
6619 if ((ctxt == NULL) || (node == NULL))
6620 return (NULL);
6621 if (needed)
6622 ret = xmlSchemaNewAnnot(ctxt, node);
6623 else
6624 ret = NULL;
6625 attr = node->properties;
6626 while (attr != NULL) {
6627 if (((attr->ns == NULL) &&
6628 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6629 ((attr->ns != NULL) &&
6630 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6631
6632 xmlSchemaPIllegalAttrErr(ctxt,
6633 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6634 }
6635 attr = attr->next;
6636 }
6637 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6638 /*
6639 * And now for the children...
6640 */
6641 child = node->children;
6642 while (child != NULL) {
6643 if (IS_SCHEMA(child, "appinfo")) {
6644 /* TODO: make available the content of "appinfo". */
6645 /*
6646 * source = anyURI
6647 * {any attributes with non-schema namespace . . .}>
6648 * Content: ({any})*
6649 */
6650 attr = child->properties;
6651 while (attr != NULL) {
6652 if (((attr->ns == NULL) &&
6653 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6654 ((attr->ns != NULL) &&
6655 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6656
6657 xmlSchemaPIllegalAttrErr(ctxt,
6658 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6659 }
6660 attr = attr->next;
6661 }
6662 xmlSchemaPValAttr(ctxt, NULL, child, "source",
6663 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6664 child = child->next;
6665 } else if (IS_SCHEMA(child, "documentation")) {
6666 /* TODO: make available the content of "documentation". */
6667 /*
6668 * source = anyURI
6669 * {any attributes with non-schema namespace . . .}>
6670 * Content: ({any})*
6671 */
6672 attr = child->properties;
6673 while (attr != NULL) {
6674 if (attr->ns == NULL) {
6675 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6676 xmlSchemaPIllegalAttrErr(ctxt,
6677 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6678 }
6679 } else {
6680 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6681 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6682 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6683
6684 xmlSchemaPIllegalAttrErr(ctxt,
6685 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6686 }
6687 }
6688 attr = attr->next;
6689 }
6690 /*
6691 * Attribute "xml:lang".
6692 */
6693 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6694 if (attr != NULL)
6695 xmlSchemaPValAttrNode(ctxt, NULL, attr,
6696 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6697 child = child->next;
6698 } else {
6699 if (!barked)
6700 xmlSchemaPContentErr(ctxt,
6701 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6702 NULL, node, child, NULL, "(appinfo | documentation)*");
6703 barked = 1;
6704 child = child->next;
6705 }
6706 }
6707
6708 return (ret);
6709 }
6710
6711 /**
6712 * xmlSchemaParseFacet:
6713 * @ctxt: a schema validation context
6714 * @schema: the schema being built
6715 * @node: a subtree containing XML Schema information
6716 *
6717 * parse a XML schema Facet declaration
6718 * *WARNING* this interface is highly subject to change
6719 *
6720 * Returns the new type structure or NULL in case of error
6721 */
6722 static xmlSchemaFacetPtr
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6723 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6724 xmlNodePtr node)
6725 {
6726 xmlSchemaFacetPtr facet;
6727 xmlNodePtr child = NULL;
6728 const xmlChar *value;
6729
6730 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6731 return (NULL);
6732
6733 facet = xmlSchemaNewFacet();
6734 if (facet == NULL) {
6735 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6736 return (NULL);
6737 }
6738 facet->node = node;
6739 value = xmlSchemaGetProp(ctxt, node, "value");
6740 if (value == NULL) {
6741 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6742 "Facet %s has no value\n", node->name, NULL);
6743 xmlSchemaFreeFacet(facet);
6744 return (NULL);
6745 }
6746 if (IS_SCHEMA(node, "minInclusive")) {
6747 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6748 } else if (IS_SCHEMA(node, "minExclusive")) {
6749 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6750 } else if (IS_SCHEMA(node, "maxInclusive")) {
6751 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6752 } else if (IS_SCHEMA(node, "maxExclusive")) {
6753 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6754 } else if (IS_SCHEMA(node, "totalDigits")) {
6755 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6756 } else if (IS_SCHEMA(node, "fractionDigits")) {
6757 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6758 } else if (IS_SCHEMA(node, "pattern")) {
6759 facet->type = XML_SCHEMA_FACET_PATTERN;
6760 } else if (IS_SCHEMA(node, "enumeration")) {
6761 facet->type = XML_SCHEMA_FACET_ENUMERATION;
6762 } else if (IS_SCHEMA(node, "whiteSpace")) {
6763 facet->type = XML_SCHEMA_FACET_WHITESPACE;
6764 } else if (IS_SCHEMA(node, "length")) {
6765 facet->type = XML_SCHEMA_FACET_LENGTH;
6766 } else if (IS_SCHEMA(node, "maxLength")) {
6767 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6768 } else if (IS_SCHEMA(node, "minLength")) {
6769 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6770 } else {
6771 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6772 "Unknown facet type %s\n", node->name, NULL);
6773 xmlSchemaFreeFacet(facet);
6774 return (NULL);
6775 }
6776 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6777 facet->value = value;
6778 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6779 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6780 const xmlChar *fixed;
6781
6782 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6783 if (fixed != NULL) {
6784 if (xmlStrEqual(fixed, BAD_CAST "true"))
6785 facet->fixed = 1;
6786 }
6787 }
6788 child = node->children;
6789
6790 if (IS_SCHEMA(child, "annotation")) {
6791 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6792 child = child->next;
6793 }
6794 if (child != NULL) {
6795 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6796 "Facet %s has unexpected child content\n",
6797 node->name, NULL);
6798 }
6799 return (facet);
6800 }
6801
6802 /**
6803 * xmlSchemaParseWildcardNs:
6804 * @ctxt: a schema parser context
6805 * @wildc: the wildcard, already created
6806 * @node: a subtree containing XML Schema information
6807 *
6808 * Parses the attribute "processContents" and "namespace"
6809 * of a xsd:anyAttribute and xsd:any.
6810 * *WARNING* this interface is highly subject to change
6811 *
6812 * Returns 0 if everything goes fine, a positive error code
6813 * if something is not valid and -1 if an internal error occurs.
6814 */
6815 static int
xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlSchemaWildcardPtr wildc,xmlNodePtr node)6816 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6817 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6818 xmlSchemaWildcardPtr wildc,
6819 xmlNodePtr node)
6820 {
6821 const xmlChar *pc, *ns, *dictnsItem;
6822 int ret = 0;
6823 xmlChar *nsItem;
6824 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6825 xmlAttrPtr attr;
6826
6827 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6828 if ((pc == NULL)
6829 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6830 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6831 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6832 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6833 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6834 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6835 } else {
6836 xmlSchemaPSimpleTypeErr(ctxt,
6837 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6838 NULL, node,
6839 NULL, "(strict | skip | lax)", pc,
6840 NULL, NULL, NULL);
6841 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6842 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6843 }
6844 /*
6845 * Build the namespace constraints.
6846 */
6847 attr = xmlSchemaGetPropNode(node, "namespace");
6848 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6849 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6850 wildc->any = 1;
6851 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6852 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6853 if (wildc->negNsSet == NULL) {
6854 return (-1);
6855 }
6856 wildc->negNsSet->value = ctxt->targetNamespace;
6857 } else {
6858 const xmlChar *end, *cur;
6859
6860 cur = ns;
6861 do {
6862 while (IS_BLANK_CH(*cur))
6863 cur++;
6864 end = cur;
6865 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6866 end++;
6867 if (end == cur)
6868 break;
6869 nsItem = xmlStrndup(cur, end - cur);
6870 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6871 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6872 xmlSchemaPSimpleTypeErr(ctxt,
6873 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6874 NULL, (xmlNodePtr) attr,
6875 NULL,
6876 "((##any | ##other) | List of (xs:anyURI | "
6877 "(##targetNamespace | ##local)))",
6878 nsItem, NULL, NULL, NULL);
6879 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6880 } else {
6881 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6882 dictnsItem = ctxt->targetNamespace;
6883 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6884 dictnsItem = NULL;
6885 } else {
6886 /*
6887 * Validate the item (anyURI).
6888 */
6889 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6890 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6891 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6892 }
6893 /*
6894 * Avoid duplicate namespaces.
6895 */
6896 tmp = wildc->nsSet;
6897 while (tmp != NULL) {
6898 if (dictnsItem == tmp->value)
6899 break;
6900 tmp = tmp->next;
6901 }
6902 if (tmp == NULL) {
6903 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6904 if (tmp == NULL) {
6905 xmlFree(nsItem);
6906 return (-1);
6907 }
6908 tmp->value = dictnsItem;
6909 tmp->next = NULL;
6910 if (wildc->nsSet == NULL)
6911 wildc->nsSet = tmp;
6912 else if (lastNs != NULL)
6913 lastNs->next = tmp;
6914 lastNs = tmp;
6915 }
6916
6917 }
6918 xmlFree(nsItem);
6919 cur = end;
6920 } while (*cur != 0);
6921 }
6922 return (ret);
6923 }
6924
6925 static int
xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,xmlNodePtr node,int minOccurs,int maxOccurs)6926 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6927 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6928 xmlNodePtr node,
6929 int minOccurs,
6930 int maxOccurs) {
6931
6932 if ((maxOccurs == 0) && ( minOccurs == 0))
6933 return (0);
6934 if (maxOccurs != UNBOUNDED) {
6935 /*
6936 * TODO: Maybe we should better not create the particle,
6937 * if min/max is invalid, since it could confuse the build of the
6938 * content model.
6939 */
6940 /*
6941 * 3.9.6 Schema Component Constraint: Particle Correct
6942 *
6943 */
6944 if (maxOccurs < 1) {
6945 /*
6946 * 2.2 {max occurs} must be greater than or equal to 1.
6947 */
6948 xmlSchemaPCustomAttrErr(ctxt,
6949 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6950 NULL, NULL,
6951 xmlSchemaGetPropNode(node, "maxOccurs"),
6952 "The value must be greater than or equal to 1");
6953 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6954 } else if (minOccurs > maxOccurs) {
6955 /*
6956 * 2.1 {min occurs} must not be greater than {max occurs}.
6957 */
6958 xmlSchemaPCustomAttrErr(ctxt,
6959 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6960 NULL, NULL,
6961 xmlSchemaGetPropNode(node, "minOccurs"),
6962 "The value must not be greater than the value of 'maxOccurs'");
6963 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6964 }
6965 }
6966 return (0);
6967 }
6968
6969 /**
6970 * xmlSchemaParseAny:
6971 * @ctxt: a schema validation context
6972 * @schema: the schema being built
6973 * @node: a subtree containing XML Schema information
6974 *
6975 * Parsea a XML schema <any> element. A particle and wildcard
6976 * will be created (except if minOccurs==maxOccurs==0, in this case
6977 * nothing will be created).
6978 * *WARNING* this interface is highly subject to change
6979 *
6980 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6981 */
6982 static xmlSchemaParticlePtr
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6983 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6984 xmlNodePtr node)
6985 {
6986 xmlSchemaParticlePtr particle;
6987 xmlNodePtr child = NULL;
6988 xmlSchemaWildcardPtr wild;
6989 int min, max;
6990 xmlAttrPtr attr;
6991 xmlSchemaAnnotPtr annot = NULL;
6992
6993 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6994 return (NULL);
6995 /*
6996 * Check for illegal attributes.
6997 */
6998 attr = node->properties;
6999 while (attr != NULL) {
7000 if (attr->ns == NULL) {
7001 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7002 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
7003 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7004 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7005 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7006 xmlSchemaPIllegalAttrErr(ctxt,
7007 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7008 }
7009 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7010 xmlSchemaPIllegalAttrErr(ctxt,
7011 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7012 }
7013 attr = attr->next;
7014 }
7015 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7016 /*
7017 * minOccurs/maxOccurs.
7018 */
7019 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7020 "(xs:nonNegativeInteger | unbounded)");
7021 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
7022 "xs:nonNegativeInteger");
7023 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7024 /*
7025 * Create & parse the wildcard.
7026 */
7027 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
7028 if (wild == NULL)
7029 return (NULL);
7030 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
7031 /*
7032 * And now for the children...
7033 */
7034 child = node->children;
7035 if (IS_SCHEMA(child, "annotation")) {
7036 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7037 child = child->next;
7038 }
7039 if (child != NULL) {
7040 xmlSchemaPContentErr(ctxt,
7041 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7042 NULL, node, child,
7043 NULL, "(annotation?)");
7044 }
7045 /*
7046 * No component if minOccurs==maxOccurs==0.
7047 */
7048 if ((min == 0) && (max == 0)) {
7049 /* Don't free the wildcard, since it's already on the list. */
7050 return (NULL);
7051 }
7052 /*
7053 * Create the particle.
7054 */
7055 particle = xmlSchemaAddParticle(ctxt, node, min, max);
7056 if (particle == NULL)
7057 return (NULL);
7058 particle->annot = annot;
7059 particle->children = (xmlSchemaTreeItemPtr) wild;
7060
7061 return (particle);
7062 }
7063
7064 /**
7065 * xmlSchemaParseNotation:
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 Notation declaration
7071 *
7072 * Returns the new structure or NULL in case of error
7073 */
7074 static xmlSchemaNotationPtr
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7075 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7076 xmlNodePtr node)
7077 {
7078 const xmlChar *name;
7079 xmlSchemaNotationPtr ret;
7080 xmlNodePtr child = NULL;
7081
7082 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7083 return (NULL);
7084 name = xmlSchemaGetProp(ctxt, node, "name");
7085 if (name == NULL) {
7086 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
7087 "Notation has no name\n", NULL, NULL);
7088 return (NULL);
7089 }
7090 ret = xmlSchemaAddNotation(ctxt, schema, name,
7091 ctxt->targetNamespace, node);
7092 if (ret == NULL)
7093 return (NULL);
7094 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7095
7096 child = node->children;
7097 if (IS_SCHEMA(child, "annotation")) {
7098 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7099 child = child->next;
7100 }
7101 if (child != NULL) {
7102 xmlSchemaPContentErr(ctxt,
7103 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7104 NULL, node, child,
7105 NULL, "(annotation?)");
7106 }
7107
7108 return (ret);
7109 }
7110
7111 /**
7112 * xmlSchemaParseAnyAttribute:
7113 * @ctxt: a schema validation context
7114 * @schema: the schema being built
7115 * @node: a subtree containing XML Schema information
7116 *
7117 * parse a XML schema AnyAttribute declaration
7118 * *WARNING* this interface is highly subject to change
7119 *
7120 * Returns a wildcard or NULL.
7121 */
7122 static xmlSchemaWildcardPtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7123 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7124 xmlSchemaPtr schema, xmlNodePtr node)
7125 {
7126 xmlSchemaWildcardPtr ret;
7127 xmlNodePtr child = NULL;
7128 xmlAttrPtr attr;
7129
7130 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7131 return (NULL);
7132
7133 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7134 node);
7135 if (ret == NULL) {
7136 return (NULL);
7137 }
7138 /*
7139 * Check for illegal attributes.
7140 */
7141 attr = node->properties;
7142 while (attr != NULL) {
7143 if (attr->ns == NULL) {
7144 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7145 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7146 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7147 xmlSchemaPIllegalAttrErr(ctxt,
7148 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7149 }
7150 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7151 xmlSchemaPIllegalAttrErr(ctxt,
7152 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7153 }
7154 attr = attr->next;
7155 }
7156 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7157 /*
7158 * Parse the namespace list.
7159 */
7160 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7161 return (NULL);
7162 /*
7163 * And now for the children...
7164 */
7165 child = node->children;
7166 if (IS_SCHEMA(child, "annotation")) {
7167 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7168 child = child->next;
7169 }
7170 if (child != NULL) {
7171 xmlSchemaPContentErr(ctxt,
7172 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7173 NULL, node, child,
7174 NULL, "(annotation?)");
7175 }
7176
7177 return (ret);
7178 }
7179
7180
7181 /**
7182 * xmlSchemaParseAttribute:
7183 * @ctxt: a schema validation context
7184 * @schema: the schema being built
7185 * @node: a subtree containing XML Schema information
7186 *
7187 * parse a XML schema Attribute declaration
7188 * *WARNING* this interface is highly subject to change
7189 *
7190 * Returns the attribute declaration.
7191 */
7192 static xmlSchemaBasicItemPtr
xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaItemListPtr uses,int parentType)7193 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7194 xmlSchemaPtr schema,
7195 xmlNodePtr node,
7196 xmlSchemaItemListPtr uses,
7197 int parentType)
7198 {
7199 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7200 xmlSchemaAttributeUsePtr use = NULL;
7201 xmlNodePtr child = NULL;
7202 xmlAttrPtr attr;
7203 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7204 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7205 int nberrors, hasForm = 0, defValueType = 0;
7206
7207 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7208 #define WXS_ATTR_DEF_VAL_FIXED 2
7209
7210 /*
7211 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7212 */
7213
7214 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7215 return (NULL);
7216 attr = xmlSchemaGetPropNode(node, "ref");
7217 if (attr != NULL) {
7218 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7219 NULL, attr, &tmpNs, &tmpName) != 0) {
7220 return (NULL);
7221 }
7222 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7223 return(NULL);
7224 isRef = 1;
7225 }
7226 nberrors = pctxt->nberrors;
7227 /*
7228 * Check for illegal attributes.
7229 */
7230 attr = node->properties;
7231 while (attr != NULL) {
7232 if (attr->ns == NULL) {
7233 if (isRef) {
7234 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7235 xmlSchemaPValAttrNodeID(pctxt, attr);
7236 goto attr_next;
7237 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7238 goto attr_next;
7239 }
7240 } else {
7241 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7242 goto attr_next;
7243 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7244 xmlSchemaPValAttrNodeID(pctxt, attr);
7245 goto attr_next;
7246 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7247 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7248 attr, &tmpNs, &tmpName);
7249 goto attr_next;
7250 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7251 /*
7252 * Evaluate the target namespace
7253 */
7254 hasForm = 1;
7255 attrValue = xmlSchemaGetNodeContent(pctxt,
7256 (xmlNodePtr) attr);
7257 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7258 ns = pctxt->targetNamespace;
7259 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7260 {
7261 xmlSchemaPSimpleTypeErr(pctxt,
7262 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7263 NULL, (xmlNodePtr) attr,
7264 NULL, "(qualified | unqualified)",
7265 attrValue, NULL, NULL, NULL);
7266 }
7267 goto attr_next;
7268 }
7269 }
7270 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7271
7272 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7273 /* TODO: Maybe we need to normalize the value beforehand. */
7274 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7275 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7276 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7277 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7278 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7279 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7280 else {
7281 xmlSchemaPSimpleTypeErr(pctxt,
7282 XML_SCHEMAP_INVALID_ATTR_USE,
7283 NULL, (xmlNodePtr) attr,
7284 NULL, "(optional | prohibited | required)",
7285 attrValue, NULL, NULL, NULL);
7286 }
7287 goto attr_next;
7288 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7289 /*
7290 * 3.2.3 : 1
7291 * default and fixed must not both be present.
7292 */
7293 if (defValue) {
7294 xmlSchemaPMutualExclAttrErr(pctxt,
7295 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7296 NULL, attr, "default", "fixed");
7297 } else {
7298 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7299 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7300 }
7301 goto attr_next;
7302 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7303 /*
7304 * 3.2.3 : 1
7305 * default and fixed must not both be present.
7306 */
7307 if (defValue) {
7308 xmlSchemaPMutualExclAttrErr(pctxt,
7309 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7310 NULL, attr, "default", "fixed");
7311 } else {
7312 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7313 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7314 }
7315 goto attr_next;
7316 }
7317 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7318 goto attr_next;
7319
7320 xmlSchemaPIllegalAttrErr(pctxt,
7321 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7322
7323 attr_next:
7324 attr = attr->next;
7325 }
7326 /*
7327 * 3.2.3 : 2
7328 * If default and use are both present, use must have
7329 * the actual value optional.
7330 */
7331 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7332 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7333 xmlSchemaPSimpleTypeErr(pctxt,
7334 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7335 NULL, node, NULL,
7336 "(optional | prohibited | required)", NULL,
7337 "The value of the attribute 'use' must be 'optional' "
7338 "if the attribute 'default' is present",
7339 NULL, NULL);
7340 }
7341 /*
7342 * We want correct attributes.
7343 */
7344 if (nberrors != pctxt->nberrors)
7345 return(NULL);
7346 if (! isRef) {
7347 xmlSchemaAttributePtr attrDecl;
7348
7349 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7350 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7351 ns = pctxt->targetNamespace;
7352 /*
7353 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7354 * TODO: Move this to the component layer.
7355 */
7356 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7357 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7358 XML_SCHEMAP_NO_XSI,
7359 node, NULL,
7360 "The target namespace must not match '%s'",
7361 xmlSchemaInstanceNs, NULL);
7362 }
7363 attr = xmlSchemaGetPropNode(node, "name");
7364 if (attr == NULL) {
7365 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7366 NULL, node, "name", NULL);
7367 return (NULL);
7368 }
7369 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7370 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7371 return (NULL);
7372 }
7373 /*
7374 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7375 * TODO: Move this to the component layer.
7376 */
7377 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7378 xmlSchemaPSimpleTypeErr(pctxt,
7379 XML_SCHEMAP_NO_XMLNS,
7380 NULL, (xmlNodePtr) attr,
7381 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7382 "The value of the attribute must not match 'xmlns'",
7383 NULL, NULL);
7384 return (NULL);
7385 }
7386 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7387 goto check_children;
7388 /*
7389 * Create the attribute use component.
7390 */
7391 use = xmlSchemaAddAttributeUse(pctxt, node);
7392 if (use == NULL)
7393 return(NULL);
7394 use->occurs = occurs;
7395 /*
7396 * Create the attribute declaration.
7397 */
7398 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7399 if (attrDecl == NULL)
7400 return (NULL);
7401 if (tmpName != NULL) {
7402 attrDecl->typeName = tmpName;
7403 attrDecl->typeNs = tmpNs;
7404 }
7405 use->attrDecl = attrDecl;
7406 /*
7407 * Value constraint.
7408 */
7409 if (defValue != NULL) {
7410 attrDecl->defValue = defValue;
7411 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7412 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7413 }
7414 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7415 xmlSchemaQNameRefPtr ref;
7416
7417 /*
7418 * Create the attribute use component.
7419 */
7420 use = xmlSchemaAddAttributeUse(pctxt, node);
7421 if (use == NULL)
7422 return(NULL);
7423 /*
7424 * We need to resolve the reference at later stage.
7425 */
7426 WXS_ADD_PENDING(pctxt, use);
7427 use->occurs = occurs;
7428 /*
7429 * Create a QName reference to the attribute declaration.
7430 */
7431 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7432 tmpName, tmpNs);
7433 if (ref == NULL)
7434 return(NULL);
7435 /*
7436 * Assign the reference. This will be substituted for the
7437 * referenced attribute declaration when the QName is resolved.
7438 */
7439 use->attrDecl = WXS_ATTR_CAST ref;
7440 /*
7441 * Value constraint.
7442 */
7443 if (defValue != NULL)
7444 use->defValue = defValue;
7445 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7446 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7447 }
7448
7449 check_children:
7450 /*
7451 * And now for the children...
7452 */
7453 child = node->children;
7454 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7455 xmlSchemaAttributeUseProhibPtr prohib;
7456
7457 if (IS_SCHEMA(child, "annotation")) {
7458 xmlSchemaParseAnnotation(pctxt, child, 0);
7459 child = child->next;
7460 }
7461 if (child != NULL) {
7462 xmlSchemaPContentErr(pctxt,
7463 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464 NULL, node, child, NULL,
7465 "(annotation?)");
7466 }
7467 /*
7468 * Check for pointlessness of attribute prohibitions.
7469 */
7470 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7471 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7472 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7473 node, NULL,
7474 "Skipping attribute use prohibition, since it is "
7475 "pointless inside an <attributeGroup>",
7476 NULL, NULL, NULL);
7477 return(NULL);
7478 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7479 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7480 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7481 node, NULL,
7482 "Skipping attribute use prohibition, since it is "
7483 "pointless when extending a type",
7484 NULL, NULL, NULL);
7485 return(NULL);
7486 }
7487 if (! isRef) {
7488 tmpName = name;
7489 tmpNs = ns;
7490 }
7491 /*
7492 * Check for duplicate attribute prohibitions.
7493 */
7494 if (uses) {
7495 int i;
7496
7497 for (i = 0; i < uses->nbItems; i++) {
7498 use = uses->items[i];
7499 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7500 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7501 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7502 {
7503 xmlChar *str = NULL;
7504
7505 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7506 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7507 node, NULL,
7508 "Skipping duplicate attribute use prohibition '%s'",
7509 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7510 NULL, NULL);
7511 FREE_AND_NULL(str)
7512 return(NULL);
7513 }
7514 }
7515 }
7516 /*
7517 * Create the attribute prohibition helper component.
7518 */
7519 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7520 if (prohib == NULL)
7521 return(NULL);
7522 prohib->node = node;
7523 prohib->name = tmpName;
7524 prohib->targetNamespace = tmpNs;
7525 if (isRef) {
7526 /*
7527 * We need at least to resolve to the attribute declaration.
7528 */
7529 WXS_ADD_PENDING(pctxt, prohib);
7530 }
7531 return(WXS_BASIC_CAST prohib);
7532 } else {
7533 if (IS_SCHEMA(child, "annotation")) {
7534 /*
7535 * TODO: Should this go into the attr decl?
7536 */
7537 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7538 child = child->next;
7539 }
7540 if (isRef) {
7541 if (child != NULL) {
7542 if (IS_SCHEMA(child, "simpleType"))
7543 /*
7544 * 3.2.3 : 3.2
7545 * If ref is present, then all of <simpleType>,
7546 * form and type must be absent.
7547 */
7548 xmlSchemaPContentErr(pctxt,
7549 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7550 NULL, node, child, NULL,
7551 "(annotation?)");
7552 else
7553 xmlSchemaPContentErr(pctxt,
7554 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7555 NULL, node, child, NULL,
7556 "(annotation?)");
7557 }
7558 } else {
7559 if (IS_SCHEMA(child, "simpleType")) {
7560 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7561 /*
7562 * 3.2.3 : 4
7563 * type and <simpleType> must not both be present.
7564 */
7565 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7566 NULL, node, child,
7567 "The attribute 'type' and the <simpleType> child "
7568 "are mutually exclusive", NULL);
7569 } else
7570 WXS_ATTRUSE_TYPEDEF(use) =
7571 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7572 child = child->next;
7573 }
7574 if (child != NULL)
7575 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7576 NULL, node, child, NULL,
7577 "(annotation?, simpleType?)");
7578 }
7579 }
7580 return (WXS_BASIC_CAST use);
7581 }
7582
7583
7584 static xmlSchemaAttributePtr
xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7585 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7586 xmlSchemaPtr schema,
7587 xmlNodePtr node)
7588 {
7589 const xmlChar *attrValue;
7590 xmlSchemaAttributePtr ret;
7591 xmlNodePtr child = NULL;
7592 xmlAttrPtr attr;
7593
7594 /*
7595 * Note that the w3c spec assumes the schema to be validated with schema
7596 * for schemas beforehand.
7597 *
7598 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7599 */
7600 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7601 return (NULL);
7602 /*
7603 * 3.2.3 : 3.1
7604 * One of ref or name must be present, but not both
7605 */
7606 attr = xmlSchemaGetPropNode(node, "name");
7607 if (attr == NULL) {
7608 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7609 NULL, node, "name", NULL);
7610 return (NULL);
7611 }
7612 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7613 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7614 return (NULL);
7615 }
7616 /*
7617 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7618 * TODO: Move this to the component layer.
7619 */
7620 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7621 xmlSchemaPSimpleTypeErr(pctxt,
7622 XML_SCHEMAP_NO_XMLNS,
7623 NULL, (xmlNodePtr) attr,
7624 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7625 "The value of the attribute must not match 'xmlns'",
7626 NULL, NULL);
7627 return (NULL);
7628 }
7629 /*
7630 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7631 * TODO: Move this to the component layer.
7632 * Or better leave it here and add it to the component layer
7633 * if we have a schema construction API.
7634 */
7635 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7636 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7637 XML_SCHEMAP_NO_XSI, node, NULL,
7638 "The target namespace must not match '%s'",
7639 xmlSchemaInstanceNs, NULL);
7640 }
7641
7642 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7643 pctxt->targetNamespace, node, 1);
7644 if (ret == NULL)
7645 return (NULL);
7646 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7647
7648 /*
7649 * Check for illegal attributes.
7650 */
7651 attr = node->properties;
7652 while (attr != NULL) {
7653 if (attr->ns == NULL) {
7654 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7655 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7656 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7657 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7658 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7659 {
7660 xmlSchemaPIllegalAttrErr(pctxt,
7661 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7662 }
7663 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7664 xmlSchemaPIllegalAttrErr(pctxt,
7665 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7666 }
7667 attr = attr->next;
7668 }
7669 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7670 node, "type", &ret->typeNs, &ret->typeName);
7671
7672 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7673 /*
7674 * Attribute "fixed".
7675 */
7676 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7677 if (ret->defValue != NULL)
7678 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7679 /*
7680 * Attribute "default".
7681 */
7682 attr = xmlSchemaGetPropNode(node, "default");
7683 if (attr != NULL) {
7684 /*
7685 * 3.2.3 : 1
7686 * default and fixed must not both be present.
7687 */
7688 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7689 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7690 WXS_BASIC_CAST ret, attr, "default", "fixed");
7691 } else
7692 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7693 }
7694 /*
7695 * And now for the children...
7696 */
7697 child = node->children;
7698 if (IS_SCHEMA(child, "annotation")) {
7699 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7700 child = child->next;
7701 }
7702 if (IS_SCHEMA(child, "simpleType")) {
7703 if (ret->typeName != NULL) {
7704 /*
7705 * 3.2.3 : 4
7706 * type and <simpleType> must not both be present.
7707 */
7708 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7709 NULL, node, child,
7710 "The attribute 'type' and the <simpleType> child "
7711 "are mutually exclusive", NULL);
7712 } else
7713 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7714 child = child->next;
7715 }
7716 if (child != NULL)
7717 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7718 NULL, node, child, NULL,
7719 "(annotation?, simpleType?)");
7720
7721 return (ret);
7722 }
7723
7724 /**
7725 * xmlSchemaParseAttributeGroupRef:
7726 * @ctxt: a schema validation context
7727 * @schema: the schema being built
7728 * @node: a subtree containing XML Schema information
7729 *
7730 * Parse an attribute group definition reference.
7731 * Note that a reference to an attribute group does not
7732 * correspond to any component at all.
7733 * *WARNING* this interface is highly subject to change
7734 *
7735 * Returns the attribute group or NULL in case of error.
7736 */
7737 static xmlSchemaQNameRefPtr
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7738 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7739 xmlSchemaPtr schema,
7740 xmlNodePtr node)
7741 {
7742 xmlSchemaQNameRefPtr ret;
7743 xmlNodePtr child = NULL;
7744 xmlAttrPtr attr;
7745 const xmlChar *refNs = NULL, *ref = NULL;
7746
7747 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7748 return (NULL);
7749
7750 attr = xmlSchemaGetPropNode(node, "ref");
7751 if (attr == NULL) {
7752 xmlSchemaPMissingAttrErr(pctxt,
7753 XML_SCHEMAP_S4S_ATTR_MISSING,
7754 NULL, node, "ref", NULL);
7755 return (NULL);
7756 }
7757 xmlSchemaPValAttrNodeQName(pctxt, schema,
7758 NULL, attr, &refNs, &ref);
7759 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7760 return(NULL);
7761
7762 /*
7763 * Check for illegal attributes.
7764 */
7765 attr = node->properties;
7766 while (attr != NULL) {
7767 if (attr->ns == NULL) {
7768 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7769 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7770 {
7771 xmlSchemaPIllegalAttrErr(pctxt,
7772 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7773 }
7774 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7775 xmlSchemaPIllegalAttrErr(pctxt,
7776 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7777 }
7778 attr = attr->next;
7779 }
7780 /* Attribute ID */
7781 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7782
7783 /*
7784 * And now for the children...
7785 */
7786 child = node->children;
7787 if (IS_SCHEMA(child, "annotation")) {
7788 /*
7789 * TODO: We do not have a place to store the annotation, do we?
7790 */
7791 xmlSchemaParseAnnotation(pctxt, child, 0);
7792 child = child->next;
7793 }
7794 if (child != NULL) {
7795 xmlSchemaPContentErr(pctxt,
7796 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7797 NULL, node, child, NULL,
7798 "(annotation?)");
7799 }
7800
7801 /*
7802 * Handle attribute group redefinitions.
7803 */
7804 if (pctxt->isRedefine && pctxt->redef &&
7805 (pctxt->redef->item->type ==
7806 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7807 (ref == pctxt->redef->refName) &&
7808 (refNs == pctxt->redef->refTargetNs))
7809 {
7810 /*
7811 * SPEC src-redefine:
7812 * (7.1) "If it has an <attributeGroup> among its contents
7813 * the `actual value` of whose ref [attribute] is the same
7814 * as the `actual value` of its own name attribute plus
7815 * target namespace, then it must have exactly one such group."
7816 */
7817 if (pctxt->redefCounter != 0) {
7818 xmlChar *str = NULL;
7819
7820 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7821 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7822 "The redefining attribute group definition "
7823 "'%s' must not contain more than one "
7824 "reference to the redefined definition",
7825 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7826 FREE_AND_NULL(str);
7827 return(NULL);
7828 }
7829 pctxt->redefCounter++;
7830 /*
7831 * URGENT TODO: How to ensure that the reference will not be
7832 * handled by the normal component resolution mechanism?
7833 */
7834 ret = xmlSchemaNewQNameRef(pctxt,
7835 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7836 if (ret == NULL)
7837 return(NULL);
7838 ret->node = node;
7839 pctxt->redef->reference = WXS_BASIC_CAST ret;
7840 } else {
7841 /*
7842 * Create a QName-reference helper component. We will substitute this
7843 * component for the attribute uses of the referenced attribute group
7844 * definition.
7845 */
7846 ret = xmlSchemaNewQNameRef(pctxt,
7847 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7848 if (ret == NULL)
7849 return(NULL);
7850 ret->node = node;
7851 /* Add to pending items, to be able to resolve the reference. */
7852 WXS_ADD_PENDING(pctxt, ret);
7853 }
7854 return (ret);
7855 }
7856
7857 /**
7858 * xmlSchemaParseAttributeGroupDefinition:
7859 * @pctxt: a schema validation context
7860 * @schema: the schema being built
7861 * @node: a subtree containing XML Schema information
7862 *
7863 * parse a XML schema Attribute Group declaration
7864 * *WARNING* this interface is highly subject to change
7865 *
7866 * Returns the attribute group definition or NULL in case of error.
7867 */
7868 static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7869 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7870 xmlSchemaPtr schema,
7871 xmlNodePtr node)
7872 {
7873 const xmlChar *name;
7874 xmlSchemaAttributeGroupPtr ret;
7875 xmlNodePtr child = NULL;
7876 xmlAttrPtr attr;
7877 int hasRefs = 0;
7878
7879 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7880 return (NULL);
7881
7882 attr = xmlSchemaGetPropNode(node, "name");
7883 if (attr == NULL) {
7884 xmlSchemaPMissingAttrErr(pctxt,
7885 XML_SCHEMAP_S4S_ATTR_MISSING,
7886 NULL, node, "name", NULL);
7887 return (NULL);
7888 }
7889 /*
7890 * The name is crucial, exit if invalid.
7891 */
7892 if (xmlSchemaPValAttrNode(pctxt,
7893 NULL, attr,
7894 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7895 return (NULL);
7896 }
7897 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7898 name, pctxt->targetNamespace, node);
7899 if (ret == NULL)
7900 return (NULL);
7901 /*
7902 * Check for illegal attributes.
7903 */
7904 attr = node->properties;
7905 while (attr != NULL) {
7906 if (attr->ns == NULL) {
7907 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7908 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7909 {
7910 xmlSchemaPIllegalAttrErr(pctxt,
7911 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7912 }
7913 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7914 xmlSchemaPIllegalAttrErr(pctxt,
7915 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7916 }
7917 attr = attr->next;
7918 }
7919 /* Attribute ID */
7920 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7921 /*
7922 * And now for the children...
7923 */
7924 child = node->children;
7925 if (IS_SCHEMA(child, "annotation")) {
7926 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7927 child = child->next;
7928 }
7929 /*
7930 * Parse contained attribute decls/refs.
7931 */
7932 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7933 (xmlSchemaItemListPtr *) &(ret->attrUses),
7934 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7935 return(NULL);
7936 if (hasRefs)
7937 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7938 /*
7939 * Parse the attribute wildcard.
7940 */
7941 if (IS_SCHEMA(child, "anyAttribute")) {
7942 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7943 schema, child);
7944 child = child->next;
7945 }
7946 if (child != NULL) {
7947 xmlSchemaPContentErr(pctxt,
7948 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7949 NULL, node, child, NULL,
7950 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7951 }
7952 return (ret);
7953 }
7954
7955 /**
7956 * xmlSchemaPValAttrFormDefault:
7957 * @value: the value
7958 * @flags: the flags to be modified
7959 * @flagQualified: the specific flag for "qualified"
7960 *
7961 * Returns 0 if the value is valid, 1 otherwise.
7962 */
7963 static int
xmlSchemaPValAttrFormDefault(const xmlChar * value,int * flags,int flagQualified)7964 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7965 int *flags,
7966 int flagQualified)
7967 {
7968 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7969 if ((*flags & flagQualified) == 0)
7970 *flags |= flagQualified;
7971 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7972 return (1);
7973
7974 return (0);
7975 }
7976
7977 /**
7978 * xmlSchemaPValAttrBlockFinal:
7979 * @value: the value
7980 * @flags: the flags to be modified
7981 * @flagAll: the specific flag for "#all"
7982 * @flagExtension: the specific flag for "extension"
7983 * @flagRestriction: the specific flag for "restriction"
7984 * @flagSubstitution: the specific flag for "substitution"
7985 * @flagList: the specific flag for "list"
7986 * @flagUnion: the specific flag for "union"
7987 *
7988 * Validates the value of the attribute "final" and "block". The value
7989 * is converted into the specified flag values and returned in @flags.
7990 *
7991 * Returns 0 if the value is valid, 1 otherwise.
7992 */
7993
7994 static int
xmlSchemaPValAttrBlockFinal(const xmlChar * value,int * flags,int flagAll,int flagExtension,int flagRestriction,int flagSubstitution,int flagList,int flagUnion)7995 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7996 int *flags,
7997 int flagAll,
7998 int flagExtension,
7999 int flagRestriction,
8000 int flagSubstitution,
8001 int flagList,
8002 int flagUnion)
8003 {
8004 int ret = 0;
8005
8006 /*
8007 * TODO: This does not check for duplicate entries.
8008 */
8009 if ((flags == NULL) || (value == NULL))
8010 return (-1);
8011 if (value[0] == 0)
8012 return (0);
8013 if (xmlStrEqual(value, BAD_CAST "#all")) {
8014 if (flagAll != -1)
8015 *flags |= flagAll;
8016 else {
8017 if (flagExtension != -1)
8018 *flags |= flagExtension;
8019 if (flagRestriction != -1)
8020 *flags |= flagRestriction;
8021 if (flagSubstitution != -1)
8022 *flags |= flagSubstitution;
8023 if (flagList != -1)
8024 *flags |= flagList;
8025 if (flagUnion != -1)
8026 *flags |= flagUnion;
8027 }
8028 } else {
8029 const xmlChar *end, *cur = value;
8030 xmlChar *item;
8031
8032 do {
8033 while (IS_BLANK_CH(*cur))
8034 cur++;
8035 end = cur;
8036 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8037 end++;
8038 if (end == cur)
8039 break;
8040 item = xmlStrndup(cur, end - cur);
8041 if (xmlStrEqual(item, BAD_CAST "extension")) {
8042 if (flagExtension != -1) {
8043 if ((*flags & flagExtension) == 0)
8044 *flags |= flagExtension;
8045 } else
8046 ret = 1;
8047 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
8048 if (flagRestriction != -1) {
8049 if ((*flags & flagRestriction) == 0)
8050 *flags |= flagRestriction;
8051 } else
8052 ret = 1;
8053 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
8054 if (flagSubstitution != -1) {
8055 if ((*flags & flagSubstitution) == 0)
8056 *flags |= flagSubstitution;
8057 } else
8058 ret = 1;
8059 } else if (xmlStrEqual(item, BAD_CAST "list")) {
8060 if (flagList != -1) {
8061 if ((*flags & flagList) == 0)
8062 *flags |= flagList;
8063 } else
8064 ret = 1;
8065 } else if (xmlStrEqual(item, BAD_CAST "union")) {
8066 if (flagUnion != -1) {
8067 if ((*flags & flagUnion) == 0)
8068 *flags |= flagUnion;
8069 } else
8070 ret = 1;
8071 } else
8072 ret = 1;
8073 if (item != NULL)
8074 xmlFree(item);
8075 cur = end;
8076 } while ((ret == 0) && (*cur != 0));
8077 }
8078
8079 return (ret);
8080 }
8081
8082 static int
xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlSchemaIDCSelectPtr selector,xmlAttrPtr attr,int isField)8083 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
8084 xmlSchemaIDCPtr idc,
8085 xmlSchemaIDCSelectPtr selector,
8086 xmlAttrPtr attr,
8087 int isField)
8088 {
8089 xmlNodePtr node;
8090
8091 /*
8092 * c-selector-xpath:
8093 * Schema Component Constraint: Selector Value OK
8094 *
8095 * TODO: 1 The {selector} must be a valid XPath expression, as defined
8096 * in [XPath].
8097 */
8098 if (selector == NULL) {
8099 xmlSchemaPErr(ctxt, idc->node,
8100 XML_SCHEMAP_INTERNAL,
8101 "Internal error: xmlSchemaCheckCSelectorXPath, "
8102 "the selector is not specified.\n", NULL, NULL);
8103 return (-1);
8104 }
8105 if (attr == NULL)
8106 node = idc->node;
8107 else
8108 node = (xmlNodePtr) attr;
8109 if (selector->xpath == NULL) {
8110 xmlSchemaPCustomErr(ctxt,
8111 /* TODO: Adjust error code. */
8112 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8113 NULL, node,
8114 "The XPath expression of the selector is not valid", NULL);
8115 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8116 } else {
8117 const xmlChar **nsArray = NULL;
8118 xmlNsPtr *nsList = NULL;
8119 /*
8120 * Compile the XPath expression.
8121 */
8122 /*
8123 * TODO: We need the array of in-scope namespaces for compilation.
8124 * TODO: Call xmlPatterncompile with different options for selector/
8125 * field.
8126 */
8127 if (attr == NULL)
8128 nsList = NULL;
8129 else
8130 nsList = xmlGetNsList(attr->doc, attr->parent);
8131 /*
8132 * Build an array of prefixes and namespaces.
8133 */
8134 if (nsList != NULL) {
8135 int i, count = 0;
8136
8137 for (i = 0; nsList[i] != NULL; i++)
8138 count++;
8139
8140 nsArray = (const xmlChar **) xmlMalloc(
8141 (count * 2 + 1) * sizeof(const xmlChar *));
8142 if (nsArray == NULL) {
8143 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8144 NULL);
8145 xmlFree(nsList);
8146 return (-1);
8147 }
8148 for (i = 0; i < count; i++) {
8149 nsArray[2 * i] = nsList[i]->href;
8150 nsArray[2 * i + 1] = nsList[i]->prefix;
8151 }
8152 nsArray[count * 2] = NULL;
8153 xmlFree(nsList);
8154 }
8155 /*
8156 * TODO: Differentiate between "selector" and "field".
8157 */
8158 if (isField)
8159 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8160 NULL, XML_PATTERN_XSFIELD, nsArray);
8161 else
8162 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8163 NULL, XML_PATTERN_XSSEL, nsArray);
8164 if (nsArray != NULL)
8165 xmlFree((xmlChar **) nsArray);
8166
8167 if (selector->xpathComp == NULL) {
8168 xmlSchemaPCustomErr(ctxt,
8169 /* TODO: Adjust error code? */
8170 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8171 NULL, node,
8172 "The XPath expression '%s' could not be "
8173 "compiled", selector->xpath);
8174 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8175 }
8176 }
8177 return (0);
8178 }
8179
8180 #define ADD_ANNOTATION(annot) \
8181 xmlSchemaAnnotPtr cur = item->annot; \
8182 if (item->annot == NULL) { \
8183 item->annot = annot; \
8184 return (annot); \
8185 } \
8186 cur = item->annot; \
8187 if (cur->next != NULL) { \
8188 cur = cur->next; \
8189 } \
8190 cur->next = annot;
8191
8192 /**
8193 * xmlSchemaAssignAnnotation:
8194 * @item: the schema component
8195 * @annot: the annotation
8196 *
8197 * Adds the annotation to the given schema component.
8198 *
8199 * Returns the given annotation.
8200 */
8201 static xmlSchemaAnnotPtr
xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,xmlSchemaAnnotPtr annot)8202 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8203 xmlSchemaAnnotPtr annot)
8204 {
8205 if ((annItem == NULL) || (annot == NULL))
8206 return (NULL);
8207 switch (annItem->type) {
8208 case XML_SCHEMA_TYPE_ELEMENT: {
8209 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8210 ADD_ANNOTATION(annot)
8211 }
8212 break;
8213 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8214 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8215 ADD_ANNOTATION(annot)
8216 }
8217 break;
8218 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8219 case XML_SCHEMA_TYPE_ANY: {
8220 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8221 ADD_ANNOTATION(annot)
8222 }
8223 break;
8224 case XML_SCHEMA_TYPE_PARTICLE:
8225 case XML_SCHEMA_TYPE_IDC_KEY:
8226 case XML_SCHEMA_TYPE_IDC_KEYREF:
8227 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8228 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8229 ADD_ANNOTATION(annot)
8230 }
8231 break;
8232 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8233 xmlSchemaAttributeGroupPtr item =
8234 (xmlSchemaAttributeGroupPtr) annItem;
8235 ADD_ANNOTATION(annot)
8236 }
8237 break;
8238 case XML_SCHEMA_TYPE_NOTATION: {
8239 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8240 ADD_ANNOTATION(annot)
8241 }
8242 break;
8243 case XML_SCHEMA_FACET_MININCLUSIVE:
8244 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8245 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8246 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8247 case XML_SCHEMA_FACET_TOTALDIGITS:
8248 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8249 case XML_SCHEMA_FACET_PATTERN:
8250 case XML_SCHEMA_FACET_ENUMERATION:
8251 case XML_SCHEMA_FACET_WHITESPACE:
8252 case XML_SCHEMA_FACET_LENGTH:
8253 case XML_SCHEMA_FACET_MAXLENGTH:
8254 case XML_SCHEMA_FACET_MINLENGTH: {
8255 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8256 ADD_ANNOTATION(annot)
8257 }
8258 break;
8259 case XML_SCHEMA_TYPE_SIMPLE:
8260 case XML_SCHEMA_TYPE_COMPLEX: {
8261 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8262 ADD_ANNOTATION(annot)
8263 }
8264 break;
8265 case XML_SCHEMA_TYPE_GROUP: {
8266 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8267 ADD_ANNOTATION(annot)
8268 }
8269 break;
8270 case XML_SCHEMA_TYPE_SEQUENCE:
8271 case XML_SCHEMA_TYPE_CHOICE:
8272 case XML_SCHEMA_TYPE_ALL: {
8273 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8274 ADD_ANNOTATION(annot)
8275 }
8276 break;
8277 default:
8278 xmlSchemaPCustomErr(NULL,
8279 XML_SCHEMAP_INTERNAL,
8280 NULL, NULL,
8281 "Internal error: xmlSchemaAddAnnotation, "
8282 "The item is not a annotated schema component", NULL);
8283 break;
8284 }
8285 return (annot);
8286 }
8287
8288 /**
8289 * xmlSchemaParseIDCSelectorAndField:
8290 * @ctxt: a schema validation context
8291 * @schema: the schema being built
8292 * @node: a subtree containing XML Schema information
8293 *
8294 * Parses a XML Schema identity-constraint definition's
8295 * <selector> and <field> elements.
8296 *
8297 * Returns the parsed identity-constraint definition.
8298 */
8299 static xmlSchemaIDCSelectPtr
xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlNodePtr node,int isField)8300 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8301 xmlSchemaIDCPtr idc,
8302 xmlNodePtr node,
8303 int isField)
8304 {
8305 xmlSchemaIDCSelectPtr item;
8306 xmlNodePtr child = NULL;
8307 xmlAttrPtr attr;
8308
8309 /*
8310 * Check for illegal attributes.
8311 */
8312 attr = node->properties;
8313 while (attr != NULL) {
8314 if (attr->ns == NULL) {
8315 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8316 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8317 xmlSchemaPIllegalAttrErr(ctxt,
8318 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8319 }
8320 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8321 xmlSchemaPIllegalAttrErr(ctxt,
8322 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8323 }
8324 attr = attr->next;
8325 }
8326 /*
8327 * Create the item.
8328 */
8329 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8330 if (item == NULL) {
8331 xmlSchemaPErrMemory(ctxt,
8332 "allocating a 'selector' of an identity-constraint definition",
8333 NULL);
8334 return (NULL);
8335 }
8336 memset(item, 0, sizeof(xmlSchemaIDCSelect));
8337 /*
8338 * Attribute "xpath" (mandatory).
8339 */
8340 attr = xmlSchemaGetPropNode(node, "xpath");
8341 if (attr == NULL) {
8342 xmlSchemaPMissingAttrErr(ctxt,
8343 XML_SCHEMAP_S4S_ATTR_MISSING,
8344 NULL, node,
8345 "name", NULL);
8346 } else {
8347 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8348 /*
8349 * URGENT TODO: "field"s have an other syntax than "selector"s.
8350 */
8351
8352 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8353 isField) == -1) {
8354 xmlSchemaPErr(ctxt,
8355 (xmlNodePtr) attr,
8356 XML_SCHEMAP_INTERNAL,
8357 "Internal error: xmlSchemaParseIDCSelectorAndField, "
8358 "validating the XPath expression of a IDC selector.\n",
8359 NULL, NULL);
8360 }
8361
8362 }
8363 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8364 /*
8365 * And now for the children...
8366 */
8367 child = node->children;
8368 if (IS_SCHEMA(child, "annotation")) {
8369 /*
8370 * Add the annotation to the parent IDC.
8371 */
8372 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8373 xmlSchemaParseAnnotation(ctxt, child, 1));
8374 child = child->next;
8375 }
8376 if (child != NULL) {
8377 xmlSchemaPContentErr(ctxt,
8378 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8379 NULL, node, child,
8380 NULL, "(annotation?)");
8381 }
8382
8383 return (item);
8384 }
8385
8386 /**
8387 * xmlSchemaParseIDC:
8388 * @ctxt: a schema validation context
8389 * @schema: the schema being built
8390 * @node: a subtree containing XML Schema information
8391 *
8392 * Parses a XML Schema identity-constraint definition.
8393 *
8394 * Returns the parsed identity-constraint definition.
8395 */
8396 static xmlSchemaIDCPtr
xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType idcCategory,const xmlChar * targetNamespace)8397 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8398 xmlSchemaPtr schema,
8399 xmlNodePtr node,
8400 xmlSchemaTypeType idcCategory,
8401 const xmlChar *targetNamespace)
8402 {
8403 xmlSchemaIDCPtr item = NULL;
8404 xmlNodePtr child = NULL;
8405 xmlAttrPtr attr;
8406 const xmlChar *name = NULL;
8407 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8408
8409 /*
8410 * Check for illegal attributes.
8411 */
8412 attr = node->properties;
8413 while (attr != NULL) {
8414 if (attr->ns == NULL) {
8415 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8416 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8417 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8418 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8419 xmlSchemaPIllegalAttrErr(ctxt,
8420 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8421 }
8422 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8423 xmlSchemaPIllegalAttrErr(ctxt,
8424 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8425 }
8426 attr = attr->next;
8427 }
8428 /*
8429 * Attribute "name" (mandatory).
8430 */
8431 attr = xmlSchemaGetPropNode(node, "name");
8432 if (attr == NULL) {
8433 xmlSchemaPMissingAttrErr(ctxt,
8434 XML_SCHEMAP_S4S_ATTR_MISSING,
8435 NULL, node,
8436 "name", NULL);
8437 return (NULL);
8438 } else if (xmlSchemaPValAttrNode(ctxt,
8439 NULL, attr,
8440 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8441 return (NULL);
8442 }
8443 /* Create the component. */
8444 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8445 idcCategory, node);
8446 if (item == NULL)
8447 return(NULL);
8448
8449 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8450 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8451 /*
8452 * Attribute "refer" (mandatory).
8453 */
8454 attr = xmlSchemaGetPropNode(node, "refer");
8455 if (attr == NULL) {
8456 xmlSchemaPMissingAttrErr(ctxt,
8457 XML_SCHEMAP_S4S_ATTR_MISSING,
8458 NULL, node,
8459 "refer", NULL);
8460 } else {
8461 /*
8462 * Create a reference item.
8463 */
8464 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8465 NULL, NULL);
8466 if (item->ref == NULL)
8467 return (NULL);
8468 xmlSchemaPValAttrNodeQName(ctxt, schema,
8469 NULL, attr,
8470 &(item->ref->targetNamespace),
8471 &(item->ref->name));
8472 xmlSchemaCheckReference(ctxt, schema, node, attr,
8473 item->ref->targetNamespace);
8474 }
8475 }
8476 /*
8477 * And now for the children...
8478 */
8479 child = node->children;
8480 if (IS_SCHEMA(child, "annotation")) {
8481 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8482 child = child->next;
8483 }
8484 if (child == NULL) {
8485 xmlSchemaPContentErr(ctxt,
8486 XML_SCHEMAP_S4S_ELEM_MISSING,
8487 NULL, node, child,
8488 "A child element is missing",
8489 "(annotation?, (selector, field+))");
8490 }
8491 /*
8492 * Child element <selector>.
8493 */
8494 if (IS_SCHEMA(child, "selector")) {
8495 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8496 item, child, 0);
8497 child = child->next;
8498 /*
8499 * Child elements <field>.
8500 */
8501 if (IS_SCHEMA(child, "field")) {
8502 do {
8503 field = xmlSchemaParseIDCSelectorAndField(ctxt,
8504 item, child, 1);
8505 if (field != NULL) {
8506 field->index = item->nbFields;
8507 item->nbFields++;
8508 if (lastField != NULL)
8509 lastField->next = field;
8510 else
8511 item->fields = field;
8512 lastField = field;
8513 }
8514 child = child->next;
8515 } while (IS_SCHEMA(child, "field"));
8516 } else {
8517 xmlSchemaPContentErr(ctxt,
8518 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8519 NULL, node, child,
8520 NULL, "(annotation?, (selector, field+))");
8521 }
8522 }
8523 if (child != NULL) {
8524 xmlSchemaPContentErr(ctxt,
8525 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8526 NULL, node, child,
8527 NULL, "(annotation?, (selector, field+))");
8528 }
8529
8530 return (item);
8531 }
8532
8533 /**
8534 * xmlSchemaParseElement:
8535 * @ctxt: a schema validation context
8536 * @schema: the schema being built
8537 * @node: a subtree containing XML Schema information
8538 * @topLevel: indicates if this is global declaration
8539 *
8540 * Parses a XML schema element declaration.
8541 * *WARNING* this interface is highly subject to change
8542 *
8543 * Returns the element declaration or a particle; NULL in case
8544 * of an error or if the particle has minOccurs==maxOccurs==0.
8545 */
8546 static xmlSchemaBasicItemPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * isElemRef,int topLevel)8547 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8548 xmlNodePtr node, int *isElemRef, int topLevel)
8549 {
8550 xmlSchemaElementPtr decl = NULL;
8551 xmlSchemaParticlePtr particle = NULL;
8552 xmlSchemaAnnotPtr annot = NULL;
8553 xmlNodePtr child = NULL;
8554 xmlAttrPtr attr, nameAttr;
8555 int min, max, isRef = 0;
8556 xmlChar *des = NULL;
8557
8558 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8559 /* TODO: Complete implementation of 3.3.6 */
8560
8561 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8562 return (NULL);
8563
8564 if (isElemRef != NULL)
8565 *isElemRef = 0;
8566 /*
8567 * If we get a "ref" attribute on a local <element> we will assume it's
8568 * a reference - even if there's a "name" attribute; this seems to be more
8569 * robust.
8570 */
8571 nameAttr = xmlSchemaGetPropNode(node, "name");
8572 attr = xmlSchemaGetPropNode(node, "ref");
8573 if ((topLevel) || (attr == NULL)) {
8574 if (nameAttr == NULL) {
8575 xmlSchemaPMissingAttrErr(ctxt,
8576 XML_SCHEMAP_S4S_ATTR_MISSING,
8577 NULL, node, "name", NULL);
8578 return (NULL);
8579 }
8580 } else
8581 isRef = 1;
8582
8583 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8584 child = node->children;
8585 if (IS_SCHEMA(child, "annotation")) {
8586 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8587 child = child->next;
8588 }
8589 /*
8590 * Skip particle part if a global declaration.
8591 */
8592 if (topLevel)
8593 goto declaration_part;
8594 /*
8595 * The particle part ==================================================
8596 */
8597 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8598 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8599 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8600 particle = xmlSchemaAddParticle(ctxt, node, min, max);
8601 if (particle == NULL)
8602 goto return_null;
8603
8604 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8605
8606 if (isRef) {
8607 const xmlChar *refNs = NULL, *ref = NULL;
8608 xmlSchemaQNameRefPtr refer = NULL;
8609 /*
8610 * The reference part =============================================
8611 */
8612 if (isElemRef != NULL)
8613 *isElemRef = 1;
8614
8615 xmlSchemaPValAttrNodeQName(ctxt, schema,
8616 NULL, attr, &refNs, &ref);
8617 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8618 /*
8619 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8620 */
8621 if (nameAttr != NULL) {
8622 xmlSchemaPMutualExclAttrErr(ctxt,
8623 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8624 }
8625 /*
8626 * Check for illegal attributes.
8627 */
8628 attr = node->properties;
8629 while (attr != NULL) {
8630 if (attr->ns == NULL) {
8631 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8632 xmlStrEqual(attr->name, BAD_CAST "name") ||
8633 xmlStrEqual(attr->name, BAD_CAST "id") ||
8634 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8635 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8636 {
8637 attr = attr->next;
8638 continue;
8639 } else {
8640 /* SPEC (3.3.3 : 2.2) */
8641 xmlSchemaPCustomAttrErr(ctxt,
8642 XML_SCHEMAP_SRC_ELEMENT_2_2,
8643 NULL, NULL, attr,
8644 "Only the attributes 'minOccurs', 'maxOccurs' and "
8645 "'id' are allowed in addition to 'ref'");
8646 break;
8647 }
8648 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8649 xmlSchemaPIllegalAttrErr(ctxt,
8650 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8651 }
8652 attr = attr->next;
8653 }
8654 /*
8655 * No children except <annotation> expected.
8656 */
8657 if (child != NULL) {
8658 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8659 NULL, node, child, NULL, "(annotation?)");
8660 }
8661 if ((min == 0) && (max == 0))
8662 goto return_null;
8663 /*
8664 * Create the reference item and attach it to the particle.
8665 */
8666 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8667 ref, refNs);
8668 if (refer == NULL)
8669 goto return_null;
8670 particle->children = (xmlSchemaTreeItemPtr) refer;
8671 particle->annot = annot;
8672 /*
8673 * Add the particle to pending components, since the reference
8674 * need to be resolved.
8675 */
8676 WXS_ADD_PENDING(ctxt, particle);
8677 return ((xmlSchemaBasicItemPtr) particle);
8678 }
8679 /*
8680 * The declaration part ===============================================
8681 */
8682 declaration_part:
8683 {
8684 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8685 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8686
8687 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8688 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8689 goto return_null;
8690 /*
8691 * Evaluate the target namespace.
8692 */
8693 if (topLevel) {
8694 ns = ctxt->targetNamespace;
8695 } else {
8696 attr = xmlSchemaGetPropNode(node, "form");
8697 if (attr != NULL) {
8698 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8699 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8700 ns = ctxt->targetNamespace;
8701 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8702 xmlSchemaPSimpleTypeErr(ctxt,
8703 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8704 NULL, (xmlNodePtr) attr,
8705 NULL, "(qualified | unqualified)",
8706 attrValue, NULL, NULL, NULL);
8707 }
8708 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8709 ns = ctxt->targetNamespace;
8710 }
8711 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8712 if (decl == NULL) {
8713 goto return_null;
8714 }
8715 /*
8716 * Check for illegal attributes.
8717 */
8718 attr = node->properties;
8719 while (attr != NULL) {
8720 if (attr->ns == NULL) {
8721 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8722 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8723 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8724 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8725 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8726 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8727 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8728 {
8729 if (topLevel == 0) {
8730 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8731 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8732 (!xmlStrEqual(attr->name, BAD_CAST "form")))
8733 {
8734 xmlSchemaPIllegalAttrErr(ctxt,
8735 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8736 }
8737 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8738 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8739 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8740
8741 xmlSchemaPIllegalAttrErr(ctxt,
8742 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8743 }
8744 }
8745 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8746
8747 xmlSchemaPIllegalAttrErr(ctxt,
8748 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8749 }
8750 attr = attr->next;
8751 }
8752 /*
8753 * Extract/validate attributes.
8754 */
8755 if (topLevel) {
8756 /*
8757 * Process top attributes of global element declarations here.
8758 */
8759 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8760 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8761 xmlSchemaPValAttrQName(ctxt, schema,
8762 NULL, node, "substitutionGroup",
8763 &(decl->substGroupNs), &(decl->substGroup));
8764 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8765 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8766 /*
8767 * Attribute "final".
8768 */
8769 attr = xmlSchemaGetPropNode(node, "final");
8770 if (attr == NULL) {
8771 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8772 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8773 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8774 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8775 } else {
8776 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8777 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8778 -1,
8779 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8780 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8781 xmlSchemaPSimpleTypeErr(ctxt,
8782 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8783 NULL, (xmlNodePtr) attr,
8784 NULL, "(#all | List of (extension | restriction))",
8785 attrValue, NULL, NULL, NULL);
8786 }
8787 }
8788 }
8789 /*
8790 * Attribute "block".
8791 */
8792 attr = xmlSchemaGetPropNode(node, "block");
8793 if (attr == NULL) {
8794 /*
8795 * Apply default "block" values.
8796 */
8797 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8798 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8799 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8800 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8801 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8802 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8803 } else {
8804 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8805 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8806 -1,
8807 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8808 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8809 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8810 xmlSchemaPSimpleTypeErr(ctxt,
8811 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8812 NULL, (xmlNodePtr) attr,
8813 NULL, "(#all | List of (extension | "
8814 "restriction | substitution))", attrValue,
8815 NULL, NULL, NULL);
8816 }
8817 }
8818 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8819 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8820
8821 attr = xmlSchemaGetPropNode(node, "type");
8822 if (attr != NULL) {
8823 xmlSchemaPValAttrNodeQName(ctxt, schema,
8824 NULL, attr,
8825 &(decl->namedTypeNs), &(decl->namedType));
8826 xmlSchemaCheckReference(ctxt, schema, node,
8827 attr, decl->namedTypeNs);
8828 }
8829 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8830 attr = xmlSchemaGetPropNode(node, "fixed");
8831 if (attr != NULL) {
8832 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8833 if (decl->value != NULL) {
8834 /*
8835 * 3.3.3 : 1
8836 * default and fixed must not both be present.
8837 */
8838 xmlSchemaPMutualExclAttrErr(ctxt,
8839 XML_SCHEMAP_SRC_ELEMENT_1,
8840 NULL, attr, "default", "fixed");
8841 } else {
8842 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8843 decl->value = fixed;
8844 }
8845 }
8846 /*
8847 * And now for the children...
8848 */
8849 if (IS_SCHEMA(child, "complexType")) {
8850 /*
8851 * 3.3.3 : 3
8852 * "type" and either <simpleType> or <complexType> are mutually
8853 * exclusive
8854 */
8855 if (decl->namedType != NULL) {
8856 xmlSchemaPContentErr(ctxt,
8857 XML_SCHEMAP_SRC_ELEMENT_3,
8858 NULL, node, child,
8859 "The attribute 'type' and the <complexType> child are "
8860 "mutually exclusive", NULL);
8861 } else
8862 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8863 child = child->next;
8864 } else if (IS_SCHEMA(child, "simpleType")) {
8865 /*
8866 * 3.3.3 : 3
8867 * "type" and either <simpleType> or <complexType> are
8868 * mutually exclusive
8869 */
8870 if (decl->namedType != NULL) {
8871 xmlSchemaPContentErr(ctxt,
8872 XML_SCHEMAP_SRC_ELEMENT_3,
8873 NULL, node, child,
8874 "The attribute 'type' and the <simpleType> child are "
8875 "mutually exclusive", NULL);
8876 } else
8877 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8878 child = child->next;
8879 }
8880 while ((IS_SCHEMA(child, "unique")) ||
8881 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8882 if (IS_SCHEMA(child, "unique")) {
8883 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8884 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8885 } else if (IS_SCHEMA(child, "key")) {
8886 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8887 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8888 } else if (IS_SCHEMA(child, "keyref")) {
8889 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8890 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8891 }
8892 if (lastIDC != NULL)
8893 lastIDC->next = curIDC;
8894 else
8895 decl->idcs = (void *) curIDC;
8896 lastIDC = curIDC;
8897 child = child->next;
8898 }
8899 if (child != NULL) {
8900 xmlSchemaPContentErr(ctxt,
8901 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8902 NULL, node, child,
8903 NULL, "(annotation?, ((simpleType | complexType)?, "
8904 "(unique | key | keyref)*))");
8905 }
8906 decl->annot = annot;
8907 }
8908 /*
8909 * NOTE: Element Declaration Representation OK 4. will be checked at a
8910 * different layer.
8911 */
8912 FREE_AND_NULL(des)
8913 if (topLevel)
8914 return ((xmlSchemaBasicItemPtr) decl);
8915 else {
8916 particle->children = (xmlSchemaTreeItemPtr) decl;
8917 return ((xmlSchemaBasicItemPtr) particle);
8918 }
8919
8920 return_null:
8921 FREE_AND_NULL(des);
8922 if (annot != NULL) {
8923 if (particle != NULL)
8924 particle->annot = NULL;
8925 if (decl != NULL)
8926 decl->annot = NULL;
8927 xmlSchemaFreeAnnot(annot);
8928 }
8929 return (NULL);
8930 }
8931
8932 /**
8933 * xmlSchemaParseUnion:
8934 * @ctxt: a schema validation context
8935 * @schema: the schema being built
8936 * @node: a subtree containing XML Schema information
8937 *
8938 * parse a XML schema Union definition
8939 * *WARNING* this interface is highly subject to change
8940 *
8941 * Returns -1 in case of internal error, 0 in case of success and a positive
8942 * error code otherwise.
8943 */
8944 static int
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)8945 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8946 xmlNodePtr node)
8947 {
8948 xmlSchemaTypePtr type;
8949 xmlNodePtr child = NULL;
8950 xmlAttrPtr attr;
8951 const xmlChar *cur = NULL;
8952
8953 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8954 return (-1);
8955 /* Not a component, don't create it. */
8956 type = ctxt->ctxtType;
8957 /*
8958 * Mark the simple type as being of variety "union".
8959 */
8960 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8961 /*
8962 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8963 * then the `simple ur-type definition`."
8964 */
8965 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8966 /*
8967 * Check for illegal attributes.
8968 */
8969 attr = node->properties;
8970 while (attr != NULL) {
8971 if (attr->ns == NULL) {
8972 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8973 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8974 xmlSchemaPIllegalAttrErr(ctxt,
8975 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8976 }
8977 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8978 xmlSchemaPIllegalAttrErr(ctxt,
8979 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8980 }
8981 attr = attr->next;
8982 }
8983 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8984 /*
8985 * Attribute "memberTypes". This is a list of QNames.
8986 * TODO: Check the value to contain anything.
8987 */
8988 attr = xmlSchemaGetPropNode(node, "memberTypes");
8989 if (attr != NULL) {
8990 const xmlChar *end;
8991 xmlChar *tmp;
8992 const xmlChar *localName, *nsName;
8993 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8994 xmlSchemaQNameRefPtr ref;
8995
8996 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8997 type->base = cur;
8998 do {
8999 while (IS_BLANK_CH(*cur))
9000 cur++;
9001 end = cur;
9002 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9003 end++;
9004 if (end == cur)
9005 break;
9006 tmp = xmlStrndup(cur, end - cur);
9007 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
9008 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
9009 /*
9010 * Create the member type link.
9011 */
9012 link = (xmlSchemaTypeLinkPtr)
9013 xmlMalloc(sizeof(xmlSchemaTypeLink));
9014 if (link == NULL) {
9015 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
9016 "allocating a type link", NULL);
9017 return (-1);
9018 }
9019 link->type = NULL;
9020 link->next = NULL;
9021 if (lastLink == NULL)
9022 type->memberTypes = link;
9023 else
9024 lastLink->next = link;
9025 lastLink = link;
9026 /*
9027 * Create a reference item.
9028 */
9029 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
9030 localName, nsName);
9031 if (ref == NULL) {
9032 FREE_AND_NULL(tmp)
9033 return (-1);
9034 }
9035 /*
9036 * Assign the reference to the link, it will be resolved
9037 * later during fixup of the union simple type.
9038 */
9039 link->type = (xmlSchemaTypePtr) ref;
9040 }
9041 FREE_AND_NULL(tmp)
9042 cur = end;
9043 } while (*cur != 0);
9044
9045 }
9046 /*
9047 * And now for the children...
9048 */
9049 child = node->children;
9050 if (IS_SCHEMA(child, "annotation")) {
9051 /*
9052 * Add the annotation to the simple type ancestor.
9053 */
9054 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9055 xmlSchemaParseAnnotation(ctxt, child, 1));
9056 child = child->next;
9057 }
9058 if (IS_SCHEMA(child, "simpleType")) {
9059 xmlSchemaTypePtr subtype, last = NULL;
9060
9061 /*
9062 * Anchor the member types in the "subtypes" field of the
9063 * simple type.
9064 */
9065 while (IS_SCHEMA(child, "simpleType")) {
9066 subtype = (xmlSchemaTypePtr)
9067 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9068 if (subtype != NULL) {
9069 if (last == NULL) {
9070 type->subtypes = subtype;
9071 last = subtype;
9072 } else {
9073 last->next = subtype;
9074 last = subtype;
9075 }
9076 last->next = NULL;
9077 }
9078 child = child->next;
9079 }
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 ((attr == NULL) && (type->subtypes == NULL)) {
9087 /*
9088 * src-union-memberTypes-or-simpleTypes
9089 * Either the memberTypes [attribute] of the <union> element must
9090 * be non-empty or there must be at least one simpleType [child].
9091 */
9092 xmlSchemaPCustomErr(ctxt,
9093 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9094 NULL, node,
9095 "Either the attribute 'memberTypes' or "
9096 "at least one <simpleType> child must be present", NULL);
9097 }
9098 return (0);
9099 }
9100
9101 /**
9102 * xmlSchemaParseList:
9103 * @ctxt: a schema validation context
9104 * @schema: the schema being built
9105 * @node: a subtree containing XML Schema information
9106 *
9107 * parse a XML schema List definition
9108 * *WARNING* this interface is highly subject to change
9109 *
9110 * Returns -1 in case of error, 0 if the declaration is improper and
9111 * 1 in case of success.
9112 */
9113 static xmlSchemaTypePtr
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9114 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9115 xmlNodePtr node)
9116 {
9117 xmlSchemaTypePtr type;
9118 xmlNodePtr child = NULL;
9119 xmlAttrPtr attr;
9120
9121 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9122 return (NULL);
9123 /* Not a component, don't create it. */
9124 type = ctxt->ctxtType;
9125 /*
9126 * Mark the type as being of variety "list".
9127 */
9128 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9129 /*
9130 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9131 * then the `simple ur-type definition`."
9132 */
9133 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9134 /*
9135 * Check for illegal attributes.
9136 */
9137 attr = node->properties;
9138 while (attr != NULL) {
9139 if (attr->ns == NULL) {
9140 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9141 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9142 xmlSchemaPIllegalAttrErr(ctxt,
9143 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9144 }
9145 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9146 xmlSchemaPIllegalAttrErr(ctxt,
9147 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9148 }
9149 attr = attr->next;
9150 }
9151
9152 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9153
9154 /*
9155 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9156 * fields for holding the reference to the itemType.
9157 *
9158 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9159 * the "ref" fields.
9160 */
9161 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9162 node, "itemType", &(type->baseNs), &(type->base));
9163 /*
9164 * And now for the children...
9165 */
9166 child = node->children;
9167 if (IS_SCHEMA(child, "annotation")) {
9168 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9169 xmlSchemaParseAnnotation(ctxt, child, 1));
9170 child = child->next;
9171 }
9172 if (IS_SCHEMA(child, "simpleType")) {
9173 /*
9174 * src-list-itemType-or-simpleType
9175 * Either the itemType [attribute] or the <simpleType> [child] of
9176 * the <list> element must be present, but not both.
9177 */
9178 if (type->base != NULL) {
9179 xmlSchemaPCustomErr(ctxt,
9180 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9181 NULL, node,
9182 "The attribute 'itemType' and the <simpleType> child "
9183 "are mutually exclusive", NULL);
9184 } else {
9185 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9186 }
9187 child = child->next;
9188 } else if (type->base == NULL) {
9189 xmlSchemaPCustomErr(ctxt,
9190 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9191 NULL, node,
9192 "Either the attribute 'itemType' or the <simpleType> child "
9193 "must be present", NULL);
9194 }
9195 if (child != NULL) {
9196 xmlSchemaPContentErr(ctxt,
9197 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9198 NULL, node, child, NULL, "(annotation?, simpleType?)");
9199 }
9200 if ((type->base == NULL) &&
9201 (type->subtypes == NULL) &&
9202 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9203 xmlSchemaPCustomErr(ctxt,
9204 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9205 NULL, node,
9206 "Either the attribute 'itemType' or the <simpleType> child "
9207 "must be present", NULL);
9208 }
9209 return (NULL);
9210 }
9211
9212 /**
9213 * xmlSchemaParseSimpleType:
9214 * @ctxt: a schema validation context
9215 * @schema: the schema being built
9216 * @node: a subtree containing XML Schema information
9217 *
9218 * parse a XML schema Simple Type definition
9219 * *WARNING* this interface is highly subject to change
9220 *
9221 * Returns -1 in case of error, 0 if the declaration is improper and
9222 * 1 in case of success.
9223 */
9224 static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)9225 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9226 xmlNodePtr node, int topLevel)
9227 {
9228 xmlSchemaTypePtr type, oldCtxtType;
9229 xmlNodePtr child = NULL;
9230 const xmlChar *attrValue = NULL;
9231 xmlAttrPtr attr;
9232 int hasRestriction = 0;
9233
9234 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9235 return (NULL);
9236
9237 if (topLevel) {
9238 attr = xmlSchemaGetPropNode(node, "name");
9239 if (attr == NULL) {
9240 xmlSchemaPMissingAttrErr(ctxt,
9241 XML_SCHEMAP_S4S_ATTR_MISSING,
9242 NULL, node,
9243 "name", NULL);
9244 return (NULL);
9245 } else {
9246 if (xmlSchemaPValAttrNode(ctxt,
9247 NULL, attr,
9248 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9249 return (NULL);
9250 /*
9251 * Skip built-in types.
9252 */
9253 if (ctxt->isS4S) {
9254 xmlSchemaTypePtr biType;
9255
9256 if (ctxt->isRedefine) {
9257 /*
9258 * REDEFINE: Disallow redefinition of built-in-types.
9259 * TODO: It seems that the spec does not say anything
9260 * about this case.
9261 */
9262 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9263 NULL, node,
9264 "Redefinition of built-in simple types is not "
9265 "supported", NULL);
9266 return(NULL);
9267 }
9268 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9269 if (biType != NULL)
9270 return (biType);
9271 }
9272 }
9273 }
9274 /*
9275 * TargetNamespace:
9276 * SPEC "The `actual value` of the targetNamespace [attribute]
9277 * of the <schema> ancestor element information item if present,
9278 * otherwise `absent`.
9279 */
9280 if (topLevel == 0) {
9281 #ifdef ENABLE_NAMED_LOCALS
9282 char buf[40];
9283 #endif
9284 /*
9285 * Parse as local simple type definition.
9286 */
9287 #ifdef ENABLE_NAMED_LOCALS
9288 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9289 type = xmlSchemaAddType(ctxt, schema,
9290 XML_SCHEMA_TYPE_SIMPLE,
9291 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9292 ctxt->targetNamespace, node, 0);
9293 #else
9294 type = xmlSchemaAddType(ctxt, schema,
9295 XML_SCHEMA_TYPE_SIMPLE,
9296 NULL, ctxt->targetNamespace, node, 0);
9297 #endif
9298 if (type == NULL)
9299 return (NULL);
9300 type->type = XML_SCHEMA_TYPE_SIMPLE;
9301 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9302 /*
9303 * Check for illegal attributes.
9304 */
9305 attr = node->properties;
9306 while (attr != NULL) {
9307 if (attr->ns == NULL) {
9308 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9309 xmlSchemaPIllegalAttrErr(ctxt,
9310 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9311 }
9312 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9313 xmlSchemaPIllegalAttrErr(ctxt,
9314 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9315 }
9316 attr = attr->next;
9317 }
9318 } else {
9319 /*
9320 * Parse as global simple type definition.
9321 *
9322 * Note that attrValue is the value of the attribute "name" here.
9323 */
9324 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9325 attrValue, ctxt->targetNamespace, node, 1);
9326 if (type == NULL)
9327 return (NULL);
9328 type->type = XML_SCHEMA_TYPE_SIMPLE;
9329 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9330 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9331 /*
9332 * Check for illegal attributes.
9333 */
9334 attr = node->properties;
9335 while (attr != NULL) {
9336 if (attr->ns == NULL) {
9337 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9338 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9339 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9340 xmlSchemaPIllegalAttrErr(ctxt,
9341 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9342 }
9343 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9344 xmlSchemaPIllegalAttrErr(ctxt,
9345 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9346 }
9347 attr = attr->next;
9348 }
9349 /*
9350 * Attribute "final".
9351 */
9352 attr = xmlSchemaGetPropNode(node, "final");
9353 if (attr == NULL) {
9354 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9355 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9356 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9357 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9358 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9359 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9360 } else {
9361 attrValue = xmlSchemaGetProp(ctxt, node, "final");
9362 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9363 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9364 XML_SCHEMAS_TYPE_FINAL_LIST,
9365 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9366
9367 xmlSchemaPSimpleTypeErr(ctxt,
9368 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9369 WXS_BASIC_CAST type, (xmlNodePtr) attr,
9370 NULL, "(#all | List of (list | union | restriction)",
9371 attrValue, NULL, NULL, NULL);
9372 }
9373 }
9374 }
9375 type->targetNamespace = ctxt->targetNamespace;
9376 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9377 /*
9378 * And now for the children...
9379 */
9380 oldCtxtType = ctxt->ctxtType;
9381
9382 ctxt->ctxtType = type;
9383
9384 child = node->children;
9385 if (IS_SCHEMA(child, "annotation")) {
9386 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9387 child = child->next;
9388 }
9389 if (child == NULL) {
9390 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9391 NULL, node, child, NULL,
9392 "(annotation?, (restriction | list | union))");
9393 } else if (IS_SCHEMA(child, "restriction")) {
9394 xmlSchemaParseRestriction(ctxt, schema, child,
9395 XML_SCHEMA_TYPE_SIMPLE);
9396 hasRestriction = 1;
9397 child = child->next;
9398 } else if (IS_SCHEMA(child, "list")) {
9399 xmlSchemaParseList(ctxt, schema, child);
9400 child = child->next;
9401 } else if (IS_SCHEMA(child, "union")) {
9402 xmlSchemaParseUnion(ctxt, schema, child);
9403 child = child->next;
9404 }
9405 if (child != NULL) {
9406 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9407 NULL, node, child, NULL,
9408 "(annotation?, (restriction | list | union))");
9409 }
9410 /*
9411 * REDEFINE: SPEC src-redefine (5)
9412 * "Within the [children], each <simpleType> must have a
9413 * <restriction> among its [children] ... the `actual value` of whose
9414 * base [attribute] must be the same as the `actual value` of its own
9415 * name attribute plus target namespace;"
9416 */
9417 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9418 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9419 NULL, node, "This is a redefinition, thus the "
9420 "<simpleType> must have a <restriction> child", NULL);
9421 }
9422
9423 ctxt->ctxtType = oldCtxtType;
9424 return (type);
9425 }
9426
9427 /**
9428 * xmlSchemaParseModelGroupDefRef:
9429 * @ctxt: the parser context
9430 * @schema: the schema being built
9431 * @node: the node
9432 *
9433 * Parses a reference to a model group definition.
9434 *
9435 * We will return a particle component with a qname-component or
9436 * NULL in case of an error.
9437 */
9438 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9439 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9440 xmlSchemaPtr schema,
9441 xmlNodePtr node)
9442 {
9443 xmlSchemaParticlePtr item;
9444 xmlNodePtr child = NULL;
9445 xmlAttrPtr attr;
9446 const xmlChar *ref = NULL, *refNs = NULL;
9447 int min, max;
9448
9449 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9450 return (NULL);
9451
9452 attr = xmlSchemaGetPropNode(node, "ref");
9453 if (attr == NULL) {
9454 xmlSchemaPMissingAttrErr(ctxt,
9455 XML_SCHEMAP_S4S_ATTR_MISSING,
9456 NULL, node, "ref", NULL);
9457 return (NULL);
9458 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9459 attr, &refNs, &ref) != 0) {
9460 return (NULL);
9461 }
9462 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9463 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9464 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9465 "(xs:nonNegativeInteger | unbounded)");
9466 /*
9467 * Check for illegal attributes.
9468 */
9469 attr = node->properties;
9470 while (attr != NULL) {
9471 if (attr->ns == NULL) {
9472 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9473 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9474 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9475 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9476 xmlSchemaPIllegalAttrErr(ctxt,
9477 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9478 }
9479 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9480 xmlSchemaPIllegalAttrErr(ctxt,
9481 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9482 }
9483 attr = attr->next;
9484 }
9485 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9486 item = xmlSchemaAddParticle(ctxt, node, min, max);
9487 if (item == NULL)
9488 return (NULL);
9489 /*
9490 * Create a qname-reference and set as the term; it will be substituted
9491 * for the model group after the reference has been resolved.
9492 */
9493 item->children = (xmlSchemaTreeItemPtr)
9494 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9495 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9496 /*
9497 * And now for the children...
9498 */
9499 child = node->children;
9500 /* TODO: Is annotation even allowed for a model group reference? */
9501 if (IS_SCHEMA(child, "annotation")) {
9502 /*
9503 * TODO: What to do exactly with the annotation?
9504 */
9505 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9506 child = child->next;
9507 }
9508 if (child != NULL) {
9509 xmlSchemaPContentErr(ctxt,
9510 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9511 NULL, node, child, NULL,
9512 "(annotation?)");
9513 }
9514 /*
9515 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9516 */
9517 if ((min == 0) && (max == 0))
9518 return (NULL);
9519
9520 return ((xmlSchemaTreeItemPtr) item);
9521 }
9522
9523 /**
9524 * xmlSchemaParseModelGroupDefinition:
9525 * @ctxt: a schema validation context
9526 * @schema: the schema being built
9527 * @node: a subtree containing XML Schema information
9528 *
9529 * Parses a XML schema model group definition.
9530 *
9531 * Note that the constraint src-redefine (6.2) can't be applied until
9532 * references have been resolved. So we will do this at the
9533 * component fixup level.
9534 *
9535 * *WARNING* this interface is highly subject to change
9536 *
9537 * Returns -1 in case of error, 0 if the declaration is improper and
9538 * 1 in case of success.
9539 */
9540 static xmlSchemaModelGroupDefPtr
xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9541 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9542 xmlSchemaPtr schema,
9543 xmlNodePtr node)
9544 {
9545 xmlSchemaModelGroupDefPtr item;
9546 xmlNodePtr child = NULL;
9547 xmlAttrPtr attr;
9548 const xmlChar *name;
9549
9550 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9551 return (NULL);
9552
9553 attr = xmlSchemaGetPropNode(node, "name");
9554 if (attr == NULL) {
9555 xmlSchemaPMissingAttrErr(ctxt,
9556 XML_SCHEMAP_S4S_ATTR_MISSING,
9557 NULL, node,
9558 "name", NULL);
9559 return (NULL);
9560 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9561 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9562 return (NULL);
9563 }
9564 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9565 ctxt->targetNamespace, node);
9566 if (item == NULL)
9567 return (NULL);
9568 /*
9569 * Check for illegal attributes.
9570 */
9571 attr = node->properties;
9572 while (attr != NULL) {
9573 if (attr->ns == NULL) {
9574 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9575 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9576 xmlSchemaPIllegalAttrErr(ctxt,
9577 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9578 }
9579 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9580 xmlSchemaPIllegalAttrErr(ctxt,
9581 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9582 }
9583 attr = attr->next;
9584 }
9585 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9586 /*
9587 * And now for the children...
9588 */
9589 child = node->children;
9590 if (IS_SCHEMA(child, "annotation")) {
9591 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9592 child = child->next;
9593 }
9594 if (IS_SCHEMA(child, "all")) {
9595 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9596 XML_SCHEMA_TYPE_ALL, 0);
9597 child = child->next;
9598 } else if (IS_SCHEMA(child, "choice")) {
9599 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9600 XML_SCHEMA_TYPE_CHOICE, 0);
9601 child = child->next;
9602 } else if (IS_SCHEMA(child, "sequence")) {
9603 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9604 XML_SCHEMA_TYPE_SEQUENCE, 0);
9605 child = child->next;
9606 }
9607
9608
9609
9610 if (child != NULL) {
9611 xmlSchemaPContentErr(ctxt,
9612 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9613 NULL, node, child, NULL,
9614 "(annotation?, (all | choice | sequence)?)");
9615 }
9616 return (item);
9617 }
9618
9619 /**
9620 * xmlSchemaCleanupDoc:
9621 * @ctxt: a schema validation context
9622 * @node: the root of the document.
9623 *
9624 * removes unwanted nodes in a schemas document tree
9625 */
9626 static void
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr root)9627 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9628 {
9629 xmlNodePtr delete, cur;
9630
9631 if ((ctxt == NULL) || (root == NULL)) return;
9632
9633 /*
9634 * Remove all the blank text nodes
9635 */
9636 delete = NULL;
9637 cur = root;
9638 while (cur != NULL) {
9639 if (delete != NULL) {
9640 xmlUnlinkNode(delete);
9641 xmlFreeNode(delete);
9642 delete = NULL;
9643 }
9644 if (cur->type == XML_TEXT_NODE) {
9645 if (IS_BLANK_NODE(cur)) {
9646 if (xmlNodeGetSpacePreserve(cur) != 1) {
9647 delete = cur;
9648 }
9649 }
9650 } else if ((cur->type != XML_ELEMENT_NODE) &&
9651 (cur->type != XML_CDATA_SECTION_NODE)) {
9652 delete = cur;
9653 goto skip_children;
9654 }
9655
9656 /*
9657 * Skip to next node
9658 */
9659 if (cur->children != NULL) {
9660 if ((cur->children->type != XML_ENTITY_DECL) &&
9661 (cur->children->type != XML_ENTITY_REF_NODE) &&
9662 (cur->children->type != XML_ENTITY_NODE)) {
9663 cur = cur->children;
9664 continue;
9665 }
9666 }
9667 skip_children:
9668 if (cur->next != NULL) {
9669 cur = cur->next;
9670 continue;
9671 }
9672
9673 do {
9674 cur = cur->parent;
9675 if (cur == NULL)
9676 break;
9677 if (cur == root) {
9678 cur = NULL;
9679 break;
9680 }
9681 if (cur->next != NULL) {
9682 cur = cur->next;
9683 break;
9684 }
9685 } while (cur != NULL);
9686 }
9687 if (delete != NULL) {
9688 xmlUnlinkNode(delete);
9689 xmlFreeNode(delete);
9690 delete = NULL;
9691 }
9692 }
9693
9694
9695 static void
xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)9696 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9697 {
9698 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9699 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9700
9701 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9702 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9703
9704 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9705 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9706 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9707 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9708 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9709 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9710 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9711 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9712
9713 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9714 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9715 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9716 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9717 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9718 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9719 }
9720
9721 static int
xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9722 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9723 xmlSchemaPtr schema,
9724 xmlNodePtr node)
9725 {
9726 xmlAttrPtr attr;
9727 const xmlChar *val;
9728 int res = 0, oldErrs = ctxt->nberrors;
9729
9730 /*
9731 * Those flags should be moved to the parser context flags,
9732 * since they are not visible at the component level. I.e.
9733 * they are used if processing schema *documents* only.
9734 */
9735 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9736 HFAILURE;
9737
9738 /*
9739 * Since the version is of type xs:token, we won't bother to
9740 * check it.
9741 */
9742 /* REMOVED:
9743 attr = xmlSchemaGetPropNode(node, "version");
9744 if (attr != NULL) {
9745 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9746 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9747 HFAILURE;
9748 }
9749 */
9750 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9751 if (attr != NULL) {
9752 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9753 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9754 HFAILURE;
9755 if (res != 0) {
9756 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9757 goto exit;
9758 }
9759 }
9760 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9761 if (attr != NULL) {
9762 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9763 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9764 XML_SCHEMAS_QUALIF_ELEM);
9765 HFAILURE;
9766 if (res != 0) {
9767 xmlSchemaPSimpleTypeErr(ctxt,
9768 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9769 NULL, (xmlNodePtr) attr, NULL,
9770 "(qualified | unqualified)", val, NULL, NULL, NULL);
9771 }
9772 }
9773 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9774 if (attr != NULL) {
9775 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9776 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9777 XML_SCHEMAS_QUALIF_ATTR);
9778 HFAILURE;
9779 if (res != 0) {
9780 xmlSchemaPSimpleTypeErr(ctxt,
9781 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9782 NULL, (xmlNodePtr) attr, NULL,
9783 "(qualified | unqualified)", val, NULL, NULL, NULL);
9784 }
9785 }
9786 attr = xmlSchemaGetPropNode(node, "finalDefault");
9787 if (attr != NULL) {
9788 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9789 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9790 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9791 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9792 -1,
9793 XML_SCHEMAS_FINAL_DEFAULT_LIST,
9794 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9795 HFAILURE;
9796 if (res != 0) {
9797 xmlSchemaPSimpleTypeErr(ctxt,
9798 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9799 NULL, (xmlNodePtr) attr, NULL,
9800 "(#all | List of (extension | restriction | list | union))",
9801 val, NULL, NULL, NULL);
9802 }
9803 }
9804 attr = xmlSchemaGetPropNode(node, "blockDefault");
9805 if (attr != NULL) {
9806 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9807 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9808 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9809 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9810 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9811 HFAILURE;
9812 if (res != 0) {
9813 xmlSchemaPSimpleTypeErr(ctxt,
9814 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9815 NULL, (xmlNodePtr) attr, NULL,
9816 "(#all | List of (extension | restriction | substitution))",
9817 val, NULL, NULL, NULL);
9818 }
9819 }
9820
9821 exit:
9822 if (oldErrs != ctxt->nberrors)
9823 res = ctxt->err;
9824 return(res);
9825 exit_failure:
9826 return(-1);
9827 }
9828
9829 /**
9830 * xmlSchemaParseSchemaTopLevel:
9831 * @ctxt: a schema validation context
9832 * @schema: the schemas
9833 * @nodes: the list of top level nodes
9834 *
9835 * Returns the internal XML Schema structure built from the resource or
9836 * NULL in case of error
9837 */
9838 static int
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr nodes)9839 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9840 xmlSchemaPtr schema, xmlNodePtr nodes)
9841 {
9842 xmlNodePtr child;
9843 xmlSchemaAnnotPtr annot;
9844 int res = 0, oldErrs, tmpOldErrs;
9845
9846 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9847 return(-1);
9848
9849 oldErrs = ctxt->nberrors;
9850 child = nodes;
9851 while ((IS_SCHEMA(child, "include")) ||
9852 (IS_SCHEMA(child, "import")) ||
9853 (IS_SCHEMA(child, "redefine")) ||
9854 (IS_SCHEMA(child, "annotation"))) {
9855 if (IS_SCHEMA(child, "annotation")) {
9856 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9857 if (schema->annot == NULL)
9858 schema->annot = annot;
9859 else
9860 xmlSchemaFreeAnnot(annot);
9861 } else if (IS_SCHEMA(child, "import")) {
9862 tmpOldErrs = ctxt->nberrors;
9863 res = xmlSchemaParseImport(ctxt, schema, child);
9864 HFAILURE;
9865 HSTOP(ctxt);
9866 if (tmpOldErrs != ctxt->nberrors)
9867 goto exit;
9868 } else if (IS_SCHEMA(child, "include")) {
9869 tmpOldErrs = ctxt->nberrors;
9870 res = xmlSchemaParseInclude(ctxt, schema, child);
9871 HFAILURE;
9872 HSTOP(ctxt);
9873 if (tmpOldErrs != ctxt->nberrors)
9874 goto exit;
9875 } else if (IS_SCHEMA(child, "redefine")) {
9876 tmpOldErrs = ctxt->nberrors;
9877 res = xmlSchemaParseRedefine(ctxt, schema, child);
9878 HFAILURE;
9879 HSTOP(ctxt);
9880 if (tmpOldErrs != ctxt->nberrors)
9881 goto exit;
9882 }
9883 child = child->next;
9884 }
9885 /*
9886 * URGENT TODO: Change the functions to return int results.
9887 * We need especially to catch internal errors.
9888 */
9889 while (child != NULL) {
9890 if (IS_SCHEMA(child, "complexType")) {
9891 xmlSchemaParseComplexType(ctxt, schema, child, 1);
9892 child = child->next;
9893 } else if (IS_SCHEMA(child, "simpleType")) {
9894 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9895 child = child->next;
9896 } else if (IS_SCHEMA(child, "element")) {
9897 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9898 child = child->next;
9899 } else if (IS_SCHEMA(child, "attribute")) {
9900 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9901 child = child->next;
9902 } else if (IS_SCHEMA(child, "attributeGroup")) {
9903 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9904 child = child->next;
9905 } else if (IS_SCHEMA(child, "group")) {
9906 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9907 child = child->next;
9908 } else if (IS_SCHEMA(child, "notation")) {
9909 xmlSchemaParseNotation(ctxt, schema, child);
9910 child = child->next;
9911 } else {
9912 xmlSchemaPContentErr(ctxt,
9913 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9914 NULL, child->parent, child,
9915 NULL, "((include | import | redefine | annotation)*, "
9916 "(((simpleType | complexType | group | attributeGroup) "
9917 "| element | attribute | notation), annotation*)*)");
9918 child = child->next;
9919 }
9920 while (IS_SCHEMA(child, "annotation")) {
9921 /*
9922 * TODO: We should add all annotations.
9923 */
9924 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9925 if (schema->annot == NULL)
9926 schema->annot = annot;
9927 else
9928 xmlSchemaFreeAnnot(annot);
9929 child = child->next;
9930 }
9931 }
9932 exit:
9933 ctxt->ctxtType = NULL;
9934 if (oldErrs != ctxt->nberrors)
9935 res = ctxt->err;
9936 return(res);
9937 exit_failure:
9938 return(-1);
9939 }
9940
9941 static xmlSchemaSchemaRelationPtr
xmlSchemaSchemaRelationCreate(void)9942 xmlSchemaSchemaRelationCreate(void)
9943 {
9944 xmlSchemaSchemaRelationPtr ret;
9945
9946 ret = (xmlSchemaSchemaRelationPtr)
9947 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9948 if (ret == NULL) {
9949 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9950 return(NULL);
9951 }
9952 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9953 return(ret);
9954 }
9955
9956 #if 0
9957 static void
9958 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9959 {
9960 xmlFree(rel);
9961 }
9962 #endif
9963
9964 static void
xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)9965 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9966 {
9967 xmlSchemaRedefPtr prev;
9968
9969 while (redef != NULL) {
9970 prev = redef;
9971 redef = redef->next;
9972 xmlFree(prev);
9973 }
9974 }
9975
9976 static void
xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)9977 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9978 {
9979 /*
9980 * After the construction context has been freed, there will be
9981 * no schema graph available any more. Only the schema buckets
9982 * will stay alive, which are put into the "schemasImports" and
9983 * "includes" slots of the xmlSchema.
9984 */
9985 if (con->buckets != NULL)
9986 xmlSchemaItemListFree(con->buckets);
9987 if (con->pending != NULL)
9988 xmlSchemaItemListFree(con->pending);
9989 if (con->substGroups != NULL)
9990 xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
9991 if (con->redefs != NULL)
9992 xmlSchemaRedefListFree(con->redefs);
9993 if (con->dict != NULL)
9994 xmlDictFree(con->dict);
9995 xmlFree(con);
9996 }
9997
9998 static xmlSchemaConstructionCtxtPtr
xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)9999 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
10000 {
10001 xmlSchemaConstructionCtxtPtr ret;
10002
10003 ret = (xmlSchemaConstructionCtxtPtr)
10004 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
10005 if (ret == NULL) {
10006 xmlSchemaPErrMemory(NULL,
10007 "allocating schema construction context", NULL);
10008 return (NULL);
10009 }
10010 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
10011
10012 ret->buckets = xmlSchemaItemListCreate();
10013 if (ret->buckets == NULL) {
10014 xmlSchemaPErrMemory(NULL,
10015 "allocating list of schema buckets", NULL);
10016 xmlFree(ret);
10017 return (NULL);
10018 }
10019 ret->pending = xmlSchemaItemListCreate();
10020 if (ret->pending == NULL) {
10021 xmlSchemaPErrMemory(NULL,
10022 "allocating list of pending global components", NULL);
10023 xmlSchemaConstructionCtxtFree(ret);
10024 return (NULL);
10025 }
10026 ret->dict = dict;
10027 xmlDictReference(dict);
10028 return(ret);
10029 }
10030
10031 static xmlSchemaParserCtxtPtr
xmlSchemaParserCtxtCreate(void)10032 xmlSchemaParserCtxtCreate(void)
10033 {
10034 xmlSchemaParserCtxtPtr ret;
10035
10036 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10037 if (ret == NULL) {
10038 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10039 NULL);
10040 return (NULL);
10041 }
10042 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10043 ret->type = XML_SCHEMA_CTXT_PARSER;
10044 ret->attrProhibs = xmlSchemaItemListCreate();
10045 if (ret->attrProhibs == NULL) {
10046 xmlFree(ret);
10047 return(NULL);
10048 }
10049 return(ret);
10050 }
10051
10052 /**
10053 * xmlSchemaNewParserCtxtUseDict:
10054 * @URL: the location of the schema
10055 * @dict: the dictionary to be used
10056 *
10057 * Create an XML Schemas parse context for that file/resource expected
10058 * to contain an XML Schemas file.
10059 *
10060 * Returns the parser context or NULL in case of error
10061 */
10062 static xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxtUseDict(const char * URL,xmlDictPtr dict)10063 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10064 {
10065 xmlSchemaParserCtxtPtr ret;
10066
10067 ret = xmlSchemaParserCtxtCreate();
10068 if (ret == NULL)
10069 return (NULL);
10070 ret->dict = dict;
10071 xmlDictReference(dict);
10072 if (URL != NULL)
10073 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
10074 return (ret);
10075 }
10076
10077 static int
xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)10078 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
10079 {
10080 if (vctxt->pctxt == NULL) {
10081 if (vctxt->schema != NULL)
10082 vctxt->pctxt =
10083 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
10084 else
10085 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
10086 if (vctxt->pctxt == NULL) {
10087 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
10088 "failed to create a temp. parser context");
10089 return (-1);
10090 }
10091 /* TODO: Pass user data. */
10092 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10093 vctxt->warning, vctxt->errCtxt);
10094 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10095 vctxt->errCtxt);
10096 }
10097 return (0);
10098 }
10099
10100 /**
10101 * xmlSchemaGetSchemaBucket:
10102 * @pctxt: the schema parser context
10103 * @schemaLocation: the URI of the schema document
10104 *
10105 * Returns a schema bucket if it was already parsed.
10106 *
10107 * Returns a schema bucket if it was already parsed from
10108 * @schemaLocation, NULL otherwise.
10109 */
10110 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation)10111 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10112 const xmlChar *schemaLocation)
10113 {
10114 xmlSchemaBucketPtr cur;
10115 xmlSchemaItemListPtr list;
10116
10117 list = pctxt->constructor->buckets;
10118 if (list->nbItems == 0)
10119 return(NULL);
10120 else {
10121 int i;
10122 for (i = 0; i < list->nbItems; i++) {
10123 cur = (xmlSchemaBucketPtr) list->items[i];
10124 /* Pointer comparison! */
10125 if (cur->schemaLocation == schemaLocation)
10126 return(cur);
10127 }
10128 }
10129 return(NULL);
10130 }
10131
10132 static xmlSchemaBucketPtr
xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation,const xmlChar * targetNamespace)10133 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10134 const xmlChar *schemaLocation,
10135 const xmlChar *targetNamespace)
10136 {
10137 xmlSchemaBucketPtr cur;
10138 xmlSchemaItemListPtr list;
10139
10140 list = pctxt->constructor->buckets;
10141 if (list->nbItems == 0)
10142 return(NULL);
10143 else {
10144 int i;
10145 for (i = 0; i < list->nbItems; i++) {
10146 cur = (xmlSchemaBucketPtr) list->items[i];
10147 /* Pointer comparison! */
10148 if ((cur->origTargetNamespace == NULL) &&
10149 (cur->schemaLocation == schemaLocation) &&
10150 (cur->targetNamespace == targetNamespace))
10151 return(cur);
10152 }
10153 }
10154 return(NULL);
10155 }
10156
10157
10158 #define IS_BAD_SCHEMA_DOC(b) \
10159 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10160
10161 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,const xmlChar * targetNamespace,int imported)10162 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10163 const xmlChar *targetNamespace,
10164 int imported)
10165 {
10166 xmlSchemaBucketPtr cur;
10167 xmlSchemaItemListPtr list;
10168
10169 list = pctxt->constructor->buckets;
10170 if (list->nbItems == 0)
10171 return(NULL);
10172 else {
10173 int i;
10174 for (i = 0; i < list->nbItems; i++) {
10175 cur = (xmlSchemaBucketPtr) list->items[i];
10176 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10177 (cur->origTargetNamespace == targetNamespace) &&
10178 ((imported && cur->imported) ||
10179 ((!imported) && (!cur->imported))))
10180 return(cur);
10181 }
10182 }
10183 return(NULL);
10184 }
10185
10186 static int
xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10187 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10188 xmlSchemaPtr schema,
10189 xmlSchemaBucketPtr bucket)
10190 {
10191 int oldFlags;
10192 xmlDocPtr oldDoc;
10193 xmlNodePtr node;
10194 int ret, oldErrs;
10195 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10196
10197 /*
10198 * Save old values; reset the *main* schema.
10199 * URGENT TODO: This is not good; move the per-document information
10200 * to the parser. Get rid of passing the main schema to the
10201 * parsing functions.
10202 */
10203 oldFlags = schema->flags;
10204 oldDoc = schema->doc;
10205 if (schema->flags != 0)
10206 xmlSchemaClearSchemaDefaults(schema);
10207 schema->doc = bucket->doc;
10208 pctxt->schema = schema;
10209 /*
10210 * Keep the current target namespace on the parser *not* on the
10211 * main schema.
10212 */
10213 pctxt->targetNamespace = bucket->targetNamespace;
10214 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10215
10216 if ((bucket->targetNamespace != NULL) &&
10217 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10218 /*
10219 * We are parsing the schema for schemas!
10220 */
10221 pctxt->isS4S = 1;
10222 }
10223 /* Mark it as parsed, even if parsing fails. */
10224 bucket->parsed++;
10225 /* Compile the schema doc. */
10226 node = xmlDocGetRootElement(bucket->doc);
10227 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10228 if (ret != 0)
10229 goto exit;
10230 /* An empty schema; just get out. */
10231 if (node->children == NULL)
10232 goto exit;
10233 oldErrs = pctxt->nberrors;
10234 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10235 if (ret != 0)
10236 goto exit;
10237 /*
10238 * TODO: Not nice, but I'm not 100% sure we will get always an error
10239 * as a result of the above functions; so better rely on pctxt->err
10240 * as well.
10241 */
10242 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10243 ret = pctxt->err;
10244 goto exit;
10245 }
10246
10247 exit:
10248 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10249 /* Restore schema values. */
10250 schema->doc = oldDoc;
10251 schema->flags = oldFlags;
10252 return(ret);
10253 }
10254
10255 static int
xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10256 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10257 xmlSchemaPtr schema,
10258 xmlSchemaBucketPtr bucket)
10259 {
10260 xmlSchemaParserCtxtPtr newpctxt;
10261 int res = 0;
10262
10263 if (bucket == NULL)
10264 return(0);
10265 if (bucket->parsed) {
10266 PERROR_INT("xmlSchemaParseNewDoc",
10267 "reparsing a schema doc");
10268 return(-1);
10269 }
10270 if (bucket->doc == NULL) {
10271 PERROR_INT("xmlSchemaParseNewDoc",
10272 "parsing a schema doc, but there's no doc");
10273 return(-1);
10274 }
10275 if (pctxt->constructor == NULL) {
10276 PERROR_INT("xmlSchemaParseNewDoc",
10277 "no constructor");
10278 return(-1);
10279 }
10280 /* Create and init the temporary parser context. */
10281 newpctxt = xmlSchemaNewParserCtxtUseDict(
10282 (const char *) bucket->schemaLocation, pctxt->dict);
10283 if (newpctxt == NULL)
10284 return(-1);
10285 newpctxt->constructor = pctxt->constructor;
10286 /*
10287 * TODO: Can we avoid that the parser knows about the main schema?
10288 * It would be better if he knows about the current schema bucket
10289 * only.
10290 */
10291 newpctxt->schema = schema;
10292 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10293 pctxt->errCtxt);
10294 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10295 pctxt->errCtxt);
10296 newpctxt->counter = pctxt->counter;
10297
10298
10299 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10300
10301 /* Channel back errors and cleanup the temporary parser context. */
10302 if (res != 0)
10303 pctxt->err = res;
10304 pctxt->nberrors += newpctxt->nberrors;
10305 pctxt->counter = newpctxt->counter;
10306 newpctxt->constructor = NULL;
10307 /* Free the parser context. */
10308 xmlSchemaFreeParserCtxt(newpctxt);
10309 return(res);
10310 }
10311
10312 static void
xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,xmlSchemaSchemaRelationPtr rel)10313 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10314 xmlSchemaSchemaRelationPtr rel)
10315 {
10316 xmlSchemaSchemaRelationPtr cur = bucket->relations;
10317
10318 if (cur == NULL) {
10319 bucket->relations = rel;
10320 return;
10321 }
10322 while (cur->next != NULL)
10323 cur = cur->next;
10324 cur->next = rel;
10325 }
10326
10327
10328 static const xmlChar *
xmlSchemaBuildAbsoluteURI(xmlDictPtr dict,const xmlChar * location,xmlNodePtr ctxtNode)10329 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10330 xmlNodePtr ctxtNode)
10331 {
10332 /*
10333 * Build an absolute location URI.
10334 */
10335 if (location != NULL) {
10336 if (ctxtNode == NULL)
10337 return(location);
10338 else {
10339 xmlChar *base, *URI;
10340 const xmlChar *ret = NULL;
10341
10342 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10343 if (base == NULL) {
10344 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10345 } else {
10346 URI = xmlBuildURI(location, base);
10347 xmlFree(base);
10348 }
10349 if (URI != NULL) {
10350 ret = xmlDictLookup(dict, URI, -1);
10351 xmlFree(URI);
10352 return(ret);
10353 }
10354 }
10355 }
10356 return(NULL);
10357 }
10358
10359
10360
10361 /**
10362 * xmlSchemaAddSchemaDoc:
10363 * @pctxt: a schema validation context
10364 * @schema: the schema being built
10365 * @node: a subtree containing XML Schema information
10366 *
10367 * Parse an included (and to-be-redefined) XML schema document.
10368 *
10369 * Returns 0 on success, a positive error code on errors and
10370 * -1 in case of an internal or API error.
10371 */
10372
10373 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)10374 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10375 int type, /* import or include or redefine */
10376 const xmlChar *schemaLocation,
10377 xmlDocPtr schemaDoc,
10378 const char *schemaBuffer,
10379 int schemaBufferLen,
10380 xmlNodePtr invokingNode,
10381 const xmlChar *sourceTargetNamespace,
10382 const xmlChar *importNamespace,
10383 xmlSchemaBucketPtr *bucket)
10384 {
10385 const xmlChar *targetNamespace = NULL;
10386 xmlSchemaSchemaRelationPtr relation = NULL;
10387 xmlDocPtr doc = NULL;
10388 int res = 0, err = 0, located = 0, preserveDoc = 0;
10389 xmlSchemaBucketPtr bkt = NULL;
10390
10391 if (bucket != NULL)
10392 *bucket = NULL;
10393
10394 switch (type) {
10395 case XML_SCHEMA_SCHEMA_IMPORT:
10396 case XML_SCHEMA_SCHEMA_MAIN:
10397 err = XML_SCHEMAP_SRC_IMPORT;
10398 break;
10399 case XML_SCHEMA_SCHEMA_INCLUDE:
10400 err = XML_SCHEMAP_SRC_INCLUDE;
10401 break;
10402 case XML_SCHEMA_SCHEMA_REDEFINE:
10403 err = XML_SCHEMAP_SRC_REDEFINE;
10404 break;
10405 }
10406
10407
10408 /* Special handling for the main schema:
10409 * skip the location and relation logic and just parse the doc.
10410 * We need just a bucket to be returned in this case.
10411 */
10412 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10413 goto doc_load;
10414
10415 /* Note that we expect the location to be an absolute URI. */
10416 if (schemaLocation != NULL) {
10417 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10418 if ((bkt != NULL) &&
10419 (pctxt->constructor->bucket == bkt)) {
10420 /* Report self-imports/inclusions/redefinitions. */
10421
10422 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10423 invokingNode, NULL,
10424 "The schema must not import/include/redefine itself",
10425 NULL, NULL);
10426 goto exit;
10427 }
10428 }
10429 /*
10430 * Create a relation for the graph of schemas.
10431 */
10432 relation = xmlSchemaSchemaRelationCreate();
10433 if (relation == NULL)
10434 return(-1);
10435 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10436 relation);
10437 relation->type = type;
10438
10439 /*
10440 * Save the namespace import information.
10441 */
10442 if (WXS_IS_BUCKET_IMPMAIN(type)) {
10443 relation->importNamespace = importNamespace;
10444 if (schemaLocation == NULL) {
10445 /*
10446 * No location; this is just an import of the namespace.
10447 * Note that we don't assign a bucket to the relation
10448 * in this case.
10449 */
10450 goto exit;
10451 }
10452 targetNamespace = importNamespace;
10453 }
10454
10455 /* Did we already fetch the doc? */
10456 if (bkt != NULL) {
10457 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10458 /*
10459 * We included/redefined and then try to import a schema,
10460 * but the new location provided for import was different.
10461 */
10462 if (schemaLocation == NULL)
10463 schemaLocation = BAD_CAST "in_memory_buffer";
10464 if (!xmlStrEqual(schemaLocation,
10465 bkt->schemaLocation)) {
10466 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10467 invokingNode, NULL,
10468 "The schema document '%s' cannot be imported, since "
10469 "it was already included or redefined",
10470 schemaLocation, NULL);
10471 goto exit;
10472 }
10473 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10474 /*
10475 * We imported and then try to include/redefine a schema,
10476 * but the new location provided for the include/redefine
10477 * was different.
10478 */
10479 if (schemaLocation == NULL)
10480 schemaLocation = BAD_CAST "in_memory_buffer";
10481 if (!xmlStrEqual(schemaLocation,
10482 bkt->schemaLocation)) {
10483 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10484 invokingNode, NULL,
10485 "The schema document '%s' cannot be included or "
10486 "redefined, since it was already imported",
10487 schemaLocation, NULL);
10488 goto exit;
10489 }
10490 }
10491 }
10492
10493 if (WXS_IS_BUCKET_IMPMAIN(type)) {
10494 /*
10495 * Given that the schemaLocation [attribute] is only a hint, it is open
10496 * to applications to ignore all but the first <import> for a given
10497 * namespace, regardless of the `actual value` of schemaLocation, but
10498 * such a strategy risks missing useful information when new
10499 * schemaLocations are offered.
10500 *
10501 * We will use the first <import> that comes with a location.
10502 * Further <import>s *with* a location, will result in an error.
10503 * TODO: Better would be to just report a warning here, but
10504 * we'll try it this way until someone complains.
10505 *
10506 * Schema Document Location Strategy:
10507 * 3 Based on the namespace name, identify an existing schema document,
10508 * either as a resource which is an XML document or a <schema> element
10509 * information item, in some local schema repository;
10510 * 5 Attempt to resolve the namespace name to locate such a resource.
10511 *
10512 * NOTE: (3) and (5) are not supported.
10513 */
10514 if (bkt != NULL) {
10515 relation->bucket = bkt;
10516 goto exit;
10517 }
10518 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10519 importNamespace, 1);
10520
10521 if (bkt != NULL) {
10522 relation->bucket = bkt;
10523 if (bkt->schemaLocation == NULL) {
10524 /* First given location of the schema; load the doc. */
10525 bkt->schemaLocation = schemaLocation;
10526 } else {
10527 if (!xmlStrEqual(schemaLocation,
10528 bkt->schemaLocation)) {
10529 /*
10530 * Additional location given; just skip it.
10531 * URGENT TODO: We should report a warning here.
10532 * res = XML_SCHEMAP_SRC_IMPORT;
10533 */
10534 if (schemaLocation == NULL)
10535 schemaLocation = BAD_CAST "in_memory_buffer";
10536
10537 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10538 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10539 invokingNode, NULL,
10540 "Skipping import of schema located at '%s' for the "
10541 "namespace '%s', since this namespace was already "
10542 "imported with the schema located at '%s'",
10543 schemaLocation, importNamespace, bkt->schemaLocation);
10544 }
10545 goto exit;
10546 }
10547 }
10548 /*
10549 * No bucket + first location: load the doc and create a
10550 * bucket.
10551 */
10552 } else {
10553 /* <include> and <redefine> */
10554 if (bkt != NULL) {
10555
10556 if ((bkt->origTargetNamespace == NULL) &&
10557 (bkt->targetNamespace != sourceTargetNamespace)) {
10558 xmlSchemaBucketPtr chamel;
10559
10560 /*
10561 * Chameleon include/redefine: skip loading only if it was
10562 * already build for the targetNamespace of the including
10563 * schema.
10564 */
10565 /*
10566 * URGENT TODO: If the schema is a chameleon-include then copy
10567 * the components into the including schema and modify the
10568 * targetNamespace of those components, do nothing otherwise.
10569 * NOTE: This is currently worked-around by compiling the
10570 * chameleon for every distinct including targetNamespace; thus
10571 * not performant at the moment.
10572 * TODO: Check when the namespace in wildcards for chameleons
10573 * needs to be converted: before we built wildcard intersections
10574 * or after.
10575 * Answer: after!
10576 */
10577 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10578 schemaLocation, sourceTargetNamespace);
10579 if (chamel != NULL) {
10580 /* A fitting chameleon was already parsed; NOP. */
10581 relation->bucket = chamel;
10582 goto exit;
10583 }
10584 /*
10585 * We need to parse the chameleon again for a different
10586 * targetNamespace.
10587 * CHAMELEON TODO: Optimize this by only parsing the
10588 * chameleon once, and then copying the components to
10589 * the new targetNamespace.
10590 */
10591 bkt = NULL;
10592 } else {
10593 relation->bucket = bkt;
10594 goto exit;
10595 }
10596 }
10597 }
10598 if ((bkt != NULL) && (bkt->doc != NULL)) {
10599 PERROR_INT("xmlSchemaAddSchemaDoc",
10600 "trying to load a schema doc, but a doc is already "
10601 "assigned to the schema bucket");
10602 goto exit_failure;
10603 }
10604
10605 doc_load:
10606 /*
10607 * Load the document.
10608 */
10609 if (schemaDoc != NULL) {
10610 doc = schemaDoc;
10611 /* Don' free this one, since it was provided by the caller. */
10612 preserveDoc = 1;
10613 /* TODO: Does the context or the doc hold the location? */
10614 if (schemaDoc->URL != NULL)
10615 schemaLocation = xmlDictLookup(pctxt->dict,
10616 schemaDoc->URL, -1);
10617 else
10618 schemaLocation = BAD_CAST "in_memory_buffer";
10619 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10620 xmlParserCtxtPtr parserCtxt;
10621
10622 parserCtxt = xmlNewParserCtxt();
10623 if (parserCtxt == NULL) {
10624 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10625 "allocating a parser context", NULL);
10626 goto exit_failure;
10627 }
10628 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10629 /*
10630 * TODO: Do we have to burden the schema parser dict with all
10631 * the content of the schema doc?
10632 */
10633 xmlDictFree(parserCtxt->dict);
10634 parserCtxt->dict = pctxt->dict;
10635 xmlDictReference(parserCtxt->dict);
10636 }
10637 if (schemaLocation != NULL) {
10638 /* Parse from file. */
10639 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10640 NULL, SCHEMAS_PARSE_OPTIONS);
10641 } else if (schemaBuffer != NULL) {
10642 /* Parse from memory buffer. */
10643 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10644 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10645 schemaLocation = BAD_CAST "in_memory_buffer";
10646 if (doc != NULL)
10647 doc->URL = xmlStrdup(schemaLocation);
10648 }
10649 /*
10650 * For <import>:
10651 * 2.1 The referent is (a fragment of) a resource which is an
10652 * XML document (see clause 1.1), which in turn corresponds to
10653 * a <schema> element information item in a well-formed information
10654 * set, which in turn corresponds to a valid schema.
10655 * TODO: (2.1) fragments of XML documents are not supported.
10656 *
10657 * 2.2 The referent is a <schema> element information item in
10658 * a well-formed information set, which in turn corresponds
10659 * to a valid schema.
10660 * TODO: (2.2) is not supported.
10661 */
10662 if (doc == NULL) {
10663 xmlErrorPtr lerr;
10664 lerr = xmlGetLastError();
10665 /*
10666 * Check if this a parser error, or if the document could
10667 * just not be located.
10668 * TODO: Try to find specific error codes to react only on
10669 * localisation failures.
10670 */
10671 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10672 /*
10673 * We assume a parser error here.
10674 */
10675 located = 1;
10676 /* TODO: Error code ?? */
10677 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10678 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10679 invokingNode, NULL,
10680 "Failed to parse the XML resource '%s'",
10681 schemaLocation, NULL);
10682 }
10683 }
10684 xmlFreeParserCtxt(parserCtxt);
10685 if ((doc == NULL) && located)
10686 goto exit_error;
10687 } else {
10688 xmlSchemaPErr(pctxt, NULL,
10689 XML_SCHEMAP_NOTHING_TO_PARSE,
10690 "No information for parsing was provided with the "
10691 "given schema parser context.\n",
10692 NULL, NULL);
10693 goto exit_failure;
10694 }
10695 /*
10696 * Preprocess the document.
10697 */
10698 if (doc != NULL) {
10699 xmlNodePtr docElem = NULL;
10700
10701 located = 1;
10702 docElem = xmlDocGetRootElement(doc);
10703 if (docElem == NULL) {
10704 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10705 invokingNode, NULL,
10706 "The document '%s' has no document element",
10707 schemaLocation, NULL);
10708 goto exit_error;
10709 }
10710 /*
10711 * Remove all the blank text nodes.
10712 */
10713 xmlSchemaCleanupDoc(pctxt, docElem);
10714 /*
10715 * Check the schema's top level element.
10716 */
10717 if (!IS_SCHEMA(docElem, "schema")) {
10718 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10719 invokingNode, NULL,
10720 "The XML document '%s' is not a schema document",
10721 schemaLocation, NULL);
10722 goto exit_error;
10723 }
10724 /*
10725 * Note that we don't apply a type check for the
10726 * targetNamespace value here.
10727 */
10728 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10729 "targetNamespace");
10730 }
10731
10732 /* after_doc_loading: */
10733 if ((bkt == NULL) && located) {
10734 /* Only create a bucket if the schema was located. */
10735 bkt = xmlSchemaBucketCreate(pctxt, type,
10736 targetNamespace);
10737 if (bkt == NULL)
10738 goto exit_failure;
10739 }
10740 if (bkt != NULL) {
10741 bkt->schemaLocation = schemaLocation;
10742 bkt->located = located;
10743 if (doc != NULL) {
10744 bkt->doc = doc;
10745 bkt->targetNamespace = targetNamespace;
10746 bkt->origTargetNamespace = targetNamespace;
10747 if (preserveDoc)
10748 bkt->preserveDoc = 1;
10749 }
10750 if (WXS_IS_BUCKET_IMPMAIN(type))
10751 bkt->imported++;
10752 /*
10753 * Add it to the graph of schemas.
10754 */
10755 if (relation != NULL)
10756 relation->bucket = bkt;
10757 }
10758
10759 exit:
10760 /*
10761 * Return the bucket explicitly; this is needed for the
10762 * main schema.
10763 */
10764 if (bucket != NULL)
10765 *bucket = bkt;
10766 return (0);
10767
10768 exit_error:
10769 if ((doc != NULL) && (! preserveDoc)) {
10770 xmlFreeDoc(doc);
10771 if (bkt != NULL)
10772 bkt->doc = NULL;
10773 }
10774 return(pctxt->err);
10775
10776 exit_failure:
10777 if ((doc != NULL) && (! preserveDoc)) {
10778 xmlFreeDoc(doc);
10779 if (bkt != NULL)
10780 bkt->doc = NULL;
10781 }
10782 return (-1);
10783 }
10784
10785 /**
10786 * xmlSchemaParseImport:
10787 * @ctxt: a schema validation context
10788 * @schema: the schema being built
10789 * @node: a subtree containing XML Schema information
10790 *
10791 * parse a XML schema Import definition
10792 * *WARNING* this interface is highly subject to change
10793 *
10794 * Returns 0 in case of success, a positive error code if
10795 * not valid and -1 in case of an internal error.
10796 */
10797 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)10798 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10799 xmlNodePtr node)
10800 {
10801 xmlNodePtr child;
10802 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10803 const xmlChar *thisTargetNamespace;
10804 xmlAttrPtr attr;
10805 int ret = 0;
10806 xmlSchemaBucketPtr bucket = NULL;
10807
10808 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10809 return (-1);
10810
10811 /*
10812 * Check for illegal attributes.
10813 */
10814 attr = node->properties;
10815 while (attr != NULL) {
10816 if (attr->ns == NULL) {
10817 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10818 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10819 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10820 xmlSchemaPIllegalAttrErr(pctxt,
10821 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10822 }
10823 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10824 xmlSchemaPIllegalAttrErr(pctxt,
10825 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10826 }
10827 attr = attr->next;
10828 }
10829 /*
10830 * Extract and validate attributes.
10831 */
10832 if (xmlSchemaPValAttr(pctxt, NULL, node,
10833 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10834 &namespaceName) != 0) {
10835 xmlSchemaPSimpleTypeErr(pctxt,
10836 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10837 NULL, node,
10838 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10839 NULL, namespaceName, NULL, NULL, NULL);
10840 return (pctxt->err);
10841 }
10842
10843 if (xmlSchemaPValAttr(pctxt, NULL, node,
10844 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10845 &schemaLocation) != 0) {
10846 xmlSchemaPSimpleTypeErr(pctxt,
10847 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10848 NULL, node,
10849 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10850 NULL, schemaLocation, NULL, NULL, NULL);
10851 return (pctxt->err);
10852 }
10853 /*
10854 * And now for the children...
10855 */
10856 child = node->children;
10857 if (IS_SCHEMA(child, "annotation")) {
10858 /*
10859 * the annotation here is simply discarded ...
10860 * TODO: really?
10861 */
10862 child = child->next;
10863 }
10864 if (child != NULL) {
10865 xmlSchemaPContentErr(pctxt,
10866 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10867 NULL, node, child, NULL,
10868 "(annotation?)");
10869 }
10870 /*
10871 * Apply additional constraints.
10872 *
10873 * Note that it is important to use the original @targetNamespace
10874 * (or none at all), to rule out imports of schemas _with_ a
10875 * @targetNamespace if the importing schema is a chameleon schema
10876 * (with no @targetNamespace).
10877 */
10878 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10879 if (namespaceName != NULL) {
10880 /*
10881 * 1.1 If the namespace [attribute] is present, then its `actual value`
10882 * must not match the `actual value` of the enclosing <schema>'s
10883 * targetNamespace [attribute].
10884 */
10885 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10886 xmlSchemaPCustomErr(pctxt,
10887 XML_SCHEMAP_SRC_IMPORT_1_1,
10888 NULL, node,
10889 "The value of the attribute 'namespace' must not match "
10890 "the target namespace '%s' of the importing schema",
10891 thisTargetNamespace);
10892 return (pctxt->err);
10893 }
10894 } else {
10895 /*
10896 * 1.2 If the namespace [attribute] is not present, then the enclosing
10897 * <schema> must have a targetNamespace [attribute].
10898 */
10899 if (thisTargetNamespace == NULL) {
10900 xmlSchemaPCustomErr(pctxt,
10901 XML_SCHEMAP_SRC_IMPORT_1_2,
10902 NULL, node,
10903 "The attribute 'namespace' must be existent if "
10904 "the importing schema has no target namespace",
10905 NULL);
10906 return (pctxt->err);
10907 }
10908 }
10909 /*
10910 * Locate and acquire the schema document.
10911 */
10912 if (schemaLocation != NULL)
10913 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10914 schemaLocation, node);
10915 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10916 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10917 namespaceName, &bucket);
10918
10919 if (ret != 0)
10920 return(ret);
10921
10922 /*
10923 * For <import>: "It is *not* an error for the application
10924 * schema reference strategy to fail."
10925 * So just don't parse if no schema document was found.
10926 * Note that we will get no bucket if the schema could not be
10927 * located or if there was no schemaLocation.
10928 */
10929 if ((bucket == NULL) && (schemaLocation != NULL)) {
10930 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10931 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10932 node, NULL,
10933 "Failed to locate a schema at location '%s'. "
10934 "Skipping the import", schemaLocation, NULL, NULL);
10935 }
10936
10937 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10938 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10939 }
10940
10941 return (ret);
10942 }
10943
10944 static int
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlChar ** schemaLocation,int type)10945 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10946 xmlSchemaPtr schema,
10947 xmlNodePtr node,
10948 xmlChar **schemaLocation,
10949 int type)
10950 {
10951 xmlAttrPtr attr;
10952
10953 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10954 (schemaLocation == NULL))
10955 return (-1);
10956
10957 *schemaLocation = NULL;
10958 /*
10959 * Check for illegal attributes.
10960 * Applies for both <include> and <redefine>.
10961 */
10962 attr = node->properties;
10963 while (attr != NULL) {
10964 if (attr->ns == NULL) {
10965 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10966 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10967 xmlSchemaPIllegalAttrErr(pctxt,
10968 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10969 }
10970 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10971 xmlSchemaPIllegalAttrErr(pctxt,
10972 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10973 }
10974 attr = attr->next;
10975 }
10976 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10977 /*
10978 * Preliminary step, extract the URI-Reference and make an URI
10979 * from the base.
10980 */
10981 /*
10982 * Attribute "schemaLocation" is mandatory.
10983 */
10984 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10985 if (attr != NULL) {
10986 xmlChar *base = NULL;
10987 xmlChar *uri = NULL;
10988
10989 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10990 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10991 (const xmlChar **) schemaLocation) != 0)
10992 goto exit_error;
10993 base = xmlNodeGetBase(node->doc, node);
10994 if (base == NULL) {
10995 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10996 } else {
10997 uri = xmlBuildURI(*schemaLocation, base);
10998 xmlFree(base);
10999 }
11000 if (uri == NULL) {
11001 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
11002 "could not build an URI from the schemaLocation")
11003 goto exit_failure;
11004 }
11005 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
11006 xmlFree(uri);
11007 } else {
11008 xmlSchemaPMissingAttrErr(pctxt,
11009 XML_SCHEMAP_S4S_ATTR_MISSING,
11010 NULL, node, "schemaLocation", NULL);
11011 goto exit_error;
11012 }
11013 /*
11014 * Report self-inclusion and self-redefinition.
11015 */
11016 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
11017 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11018 xmlSchemaPCustomErr(pctxt,
11019 XML_SCHEMAP_SRC_REDEFINE,
11020 NULL, node,
11021 "The schema document '%s' cannot redefine itself.",
11022 *schemaLocation);
11023 } else {
11024 xmlSchemaPCustomErr(pctxt,
11025 XML_SCHEMAP_SRC_INCLUDE,
11026 NULL, node,
11027 "The schema document '%s' cannot include itself.",
11028 *schemaLocation);
11029 }
11030 goto exit_error;
11031 }
11032
11033 return(0);
11034 exit_error:
11035 return(pctxt->err);
11036 exit_failure:
11037 return(-1);
11038 }
11039
11040 static int
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,int type)11041 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
11042 xmlSchemaPtr schema,
11043 xmlNodePtr node,
11044 int type)
11045 {
11046 xmlNodePtr child = NULL;
11047 const xmlChar *schemaLocation = NULL;
11048 int res = 0; /* hasRedefinitions = 0 */
11049 int isChameleon = 0, wasChameleon = 0;
11050 xmlSchemaBucketPtr bucket = NULL;
11051
11052 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
11053 return (-1);
11054
11055 /*
11056 * Parse attributes. Note that the returned schemaLocation will
11057 * be already converted to an absolute URI.
11058 */
11059 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
11060 node, (xmlChar **) (&schemaLocation), type);
11061 if (res != 0)
11062 return(res);
11063 /*
11064 * Load and add the schema document.
11065 */
11066 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
11067 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
11068 if (res != 0)
11069 return(res);
11070 /*
11071 * If we get no schema bucket back, then this means that the schema
11072 * document could not be located or was broken XML or was not
11073 * a schema document.
11074 */
11075 if ((bucket == NULL) || (bucket->doc == NULL)) {
11076 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
11077 /*
11078 * WARNING for <include>:
11079 * We will raise an error if the schema cannot be located
11080 * for inclusions, since the that was the feedback from the
11081 * schema people. I.e. the following spec piece will *not* be
11082 * satisfied:
11083 * SPEC src-include: "It is not an error for the `actual value` of the
11084 * schemaLocation [attribute] to fail to resolve it all, in which
11085 * case no corresponding inclusion is performed.
11086 * So do we need a warning report here?"
11087 */
11088 res = XML_SCHEMAP_SRC_INCLUDE;
11089 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11090 node, NULL,
11091 "Failed to load the document '%s' for inclusion",
11092 schemaLocation, NULL);
11093 } else {
11094 /*
11095 * NOTE: This was changed to raise an error even if no redefinitions
11096 * are specified.
11097 *
11098 * SPEC src-redefine (1)
11099 * "If there are any element information items among the [children]
11100 * other than <annotation> then the `actual value` of the
11101 * schemaLocation [attribute] must successfully resolve."
11102 * TODO: Ask the WG if a the location has always to resolve
11103 * here as well!
11104 */
11105 res = XML_SCHEMAP_SRC_REDEFINE;
11106 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11107 node, NULL,
11108 "Failed to load the document '%s' for redefinition",
11109 schemaLocation, NULL);
11110 }
11111 } else {
11112 /*
11113 * Check targetNamespace sanity before parsing the new schema.
11114 * TODO: Note that we won't check further content if the
11115 * targetNamespace was bad.
11116 */
11117 if (bucket->origTargetNamespace != NULL) {
11118 /*
11119 * SPEC src-include (2.1)
11120 * "SII has a targetNamespace [attribute], and its `actual
11121 * value` is identical to the `actual value` of the targetNamespace
11122 * [attribute] of SII' (which must have such an [attribute])."
11123 */
11124 if (pctxt->targetNamespace == NULL) {
11125 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11126 XML_SCHEMAP_SRC_INCLUDE,
11127 node, NULL,
11128 "The target namespace of the included/redefined schema "
11129 "'%s' has to be absent, since the including/redefining "
11130 "schema has no target namespace",
11131 schemaLocation, NULL);
11132 goto exit_error;
11133 } else if (!xmlStrEqual(bucket->origTargetNamespace,
11134 pctxt->targetNamespace)) {
11135 /* TODO: Change error function. */
11136 xmlSchemaPCustomErrExt(pctxt,
11137 XML_SCHEMAP_SRC_INCLUDE,
11138 NULL, node,
11139 "The target namespace '%s' of the included/redefined "
11140 "schema '%s' differs from '%s' of the "
11141 "including/redefining schema",
11142 bucket->origTargetNamespace, schemaLocation,
11143 pctxt->targetNamespace);
11144 goto exit_error;
11145 }
11146 } else if (pctxt->targetNamespace != NULL) {
11147 /*
11148 * Chameleons: the original target namespace will
11149 * differ from the resulting namespace.
11150 */
11151 isChameleon = 1;
11152 if (bucket->parsed &&
11153 bucket->origTargetNamespace != NULL) {
11154 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11155 XML_SCHEMAP_SRC_INCLUDE,
11156 node, NULL,
11157 "The target namespace of the included/redefined schema "
11158 "'%s' has to be absent or the same as the "
11159 "including/redefining schema's target namespace",
11160 schemaLocation, NULL);
11161 goto exit_error;
11162 }
11163 bucket->targetNamespace = pctxt->targetNamespace;
11164 }
11165 }
11166 /*
11167 * Parse the schema.
11168 */
11169 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11170 if (isChameleon) {
11171 /* TODO: Get rid of this flag on the schema itself. */
11172 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11173 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11174 } else
11175 wasChameleon = 1;
11176 }
11177 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11178 /* Restore chameleon flag. */
11179 if (isChameleon && (!wasChameleon))
11180 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11181 }
11182 /*
11183 * And now for the children...
11184 */
11185 child = node->children;
11186 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11187 /*
11188 * Parse (simpleType | complexType | group | attributeGroup))*
11189 */
11190 pctxt->redefined = bucket;
11191 /*
11192 * How to proceed if the redefined schema was not located?
11193 */
11194 pctxt->isRedefine = 1;
11195 while (IS_SCHEMA(child, "annotation") ||
11196 IS_SCHEMA(child, "simpleType") ||
11197 IS_SCHEMA(child, "complexType") ||
11198 IS_SCHEMA(child, "group") ||
11199 IS_SCHEMA(child, "attributeGroup")) {
11200 if (IS_SCHEMA(child, "annotation")) {
11201 /*
11202 * TODO: discard or not?
11203 */
11204 } else if (IS_SCHEMA(child, "simpleType")) {
11205 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11206 } else if (IS_SCHEMA(child, "complexType")) {
11207 xmlSchemaParseComplexType(pctxt, schema, child, 1);
11208 /* hasRedefinitions = 1; */
11209 } else if (IS_SCHEMA(child, "group")) {
11210 /* hasRedefinitions = 1; */
11211 xmlSchemaParseModelGroupDefinition(pctxt,
11212 schema, child);
11213 } else if (IS_SCHEMA(child, "attributeGroup")) {
11214 /* hasRedefinitions = 1; */
11215 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11216 child);
11217 }
11218 child = child->next;
11219 }
11220 pctxt->redefined = NULL;
11221 pctxt->isRedefine = 0;
11222 } else {
11223 if (IS_SCHEMA(child, "annotation")) {
11224 /*
11225 * TODO: discard or not?
11226 */
11227 child = child->next;
11228 }
11229 }
11230 if (child != NULL) {
11231 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11232 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11233 xmlSchemaPContentErr(pctxt, res,
11234 NULL, node, child, NULL,
11235 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11236 } else {
11237 xmlSchemaPContentErr(pctxt, res,
11238 NULL, node, child, NULL,
11239 "(annotation?)");
11240 }
11241 }
11242 return(res);
11243
11244 exit_error:
11245 return(pctxt->err);
11246 }
11247
11248 static int
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11249 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11250 xmlNodePtr node)
11251 {
11252 int res;
11253 #ifndef ENABLE_REDEFINE
11254 TODO
11255 return(0);
11256 #endif
11257 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11258 XML_SCHEMA_SCHEMA_REDEFINE);
11259 if (res != 0)
11260 return(res);
11261 return(0);
11262 }
11263
11264 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11265 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11266 xmlNodePtr node)
11267 {
11268 int res;
11269
11270 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11271 XML_SCHEMA_SCHEMA_INCLUDE);
11272 if (res != 0)
11273 return(res);
11274 return(0);
11275 }
11276
11277 /**
11278 * xmlSchemaParseModelGroup:
11279 * @ctxt: a schema validation context
11280 * @schema: the schema being built
11281 * @node: a subtree containing XML Schema information
11282 * @type: the "compositor" type
11283 * @particleNeeded: if a a model group with a particle
11284 *
11285 * parse a XML schema Sequence definition.
11286 * Applies parts of:
11287 * Schema Representation Constraint:
11288 * Redefinition Constraints and Semantics (src-redefine)
11289 * (6.1), (6.1.1), (6.1.2)
11290 *
11291 * Schema Component Constraint:
11292 * All Group Limited (cos-all-limited) (2)
11293 * TODO: Actually this should go to component-level checks,
11294 * but is done here due to performance. Move it to an other layer
11295 * is schema construction via an API is implemented.
11296 *
11297 * *WARNING* this interface is highly subject to change
11298 *
11299 * Returns -1 in case of error, 0 if the declaration is improper and
11300 * 1 in case of success.
11301 */
11302 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType type,int withParticle)11303 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11304 xmlNodePtr node, xmlSchemaTypeType type,
11305 int withParticle)
11306 {
11307 xmlSchemaModelGroupPtr item;
11308 xmlSchemaParticlePtr particle = NULL;
11309 xmlNodePtr child = NULL;
11310 xmlAttrPtr attr;
11311 int min = 1, max = 1, isElemRef, hasRefs = 0;
11312
11313 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11314 return (NULL);
11315 /*
11316 * Create a model group with the given compositor.
11317 */
11318 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11319 if (item == NULL)
11320 return (NULL);
11321
11322 if (withParticle) {
11323 if (type == XML_SCHEMA_TYPE_ALL) {
11324 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11325 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11326 } else {
11327 /* choice + sequence */
11328 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11329 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11330 "(xs:nonNegativeInteger | unbounded)");
11331 }
11332 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11333 /*
11334 * Create a particle
11335 */
11336 particle = xmlSchemaAddParticle(ctxt, node, min, max);
11337 if (particle == NULL)
11338 return (NULL);
11339 particle->children = (xmlSchemaTreeItemPtr) item;
11340 /*
11341 * Check for illegal attributes.
11342 */
11343 attr = node->properties;
11344 while (attr != NULL) {
11345 if (attr->ns == NULL) {
11346 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11347 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11348 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11349 xmlSchemaPIllegalAttrErr(ctxt,
11350 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11351 }
11352 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11353 xmlSchemaPIllegalAttrErr(ctxt,
11354 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11355 }
11356 attr = attr->next;
11357 }
11358 } else {
11359 /*
11360 * Check for illegal attributes.
11361 */
11362 attr = node->properties;
11363 while (attr != NULL) {
11364 if (attr->ns == NULL) {
11365 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11366 xmlSchemaPIllegalAttrErr(ctxt,
11367 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11368 }
11369 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11370 xmlSchemaPIllegalAttrErr(ctxt,
11371 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11372 }
11373 attr = attr->next;
11374 }
11375 }
11376
11377 /*
11378 * Extract and validate attributes.
11379 */
11380 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11381 /*
11382 * And now for the children...
11383 */
11384 child = node->children;
11385 if (IS_SCHEMA(child, "annotation")) {
11386 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11387 child = child->next;
11388 }
11389 if (type == XML_SCHEMA_TYPE_ALL) {
11390 xmlSchemaParticlePtr part, last = NULL;
11391
11392 while (IS_SCHEMA(child, "element")) {
11393 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11394 schema, child, &isElemRef, 0);
11395 /*
11396 * SPEC cos-all-limited (2)
11397 * "The {max occurs} of all the particles in the {particles}
11398 * of the ('all') group must be 0 or 1.
11399 */
11400 if (part != NULL) {
11401 if (isElemRef)
11402 hasRefs++;
11403 if (part->minOccurs > 1) {
11404 xmlSchemaPCustomErr(ctxt,
11405 XML_SCHEMAP_COS_ALL_LIMITED,
11406 NULL, child,
11407 "Invalid value for minOccurs (must be 0 or 1)",
11408 NULL);
11409 /* Reset to 1. */
11410 part->minOccurs = 1;
11411 }
11412 if (part->maxOccurs > 1) {
11413 xmlSchemaPCustomErr(ctxt,
11414 XML_SCHEMAP_COS_ALL_LIMITED,
11415 NULL, child,
11416 "Invalid value for maxOccurs (must be 0 or 1)",
11417 NULL);
11418 /* Reset to 1. */
11419 part->maxOccurs = 1;
11420 }
11421 if (last == NULL)
11422 item->children = (xmlSchemaTreeItemPtr) part;
11423 else
11424 last->next = (xmlSchemaTreeItemPtr) part;
11425 last = part;
11426 }
11427 child = child->next;
11428 }
11429 if (child != NULL) {
11430 xmlSchemaPContentErr(ctxt,
11431 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11432 NULL, node, child, NULL,
11433 "(annotation?, (annotation?, element*)");
11434 }
11435 } else {
11436 /* choice + sequence */
11437 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11438
11439 while ((IS_SCHEMA(child, "element")) ||
11440 (IS_SCHEMA(child, "group")) ||
11441 (IS_SCHEMA(child, "any")) ||
11442 (IS_SCHEMA(child, "choice")) ||
11443 (IS_SCHEMA(child, "sequence"))) {
11444
11445 if (IS_SCHEMA(child, "element")) {
11446 part = (xmlSchemaTreeItemPtr)
11447 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11448 if (part && isElemRef)
11449 hasRefs++;
11450 } else if (IS_SCHEMA(child, "group")) {
11451 part =
11452 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11453 if (part != NULL)
11454 hasRefs++;
11455 /*
11456 * Handle redefinitions.
11457 */
11458 if (ctxt->isRedefine && ctxt->redef &&
11459 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11460 part && part->children)
11461 {
11462 if ((xmlSchemaGetQNameRefName(part->children) ==
11463 ctxt->redef->refName) &&
11464 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11465 ctxt->redef->refTargetNs))
11466 {
11467 /*
11468 * SPEC src-redefine:
11469 * (6.1) "If it has a <group> among its contents at
11470 * some level the `actual value` of whose ref
11471 * [attribute] is the same as the `actual value` of
11472 * its own name attribute plus target namespace, then
11473 * all of the following must be true:"
11474 * (6.1.1) "It must have exactly one such group."
11475 */
11476 if (ctxt->redefCounter != 0) {
11477 xmlChar *str = NULL;
11478
11479 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11480 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11481 "The redefining model group definition "
11482 "'%s' must not contain more than one "
11483 "reference to the redefined definition",
11484 xmlSchemaFormatQName(&str,
11485 ctxt->redef->refTargetNs,
11486 ctxt->redef->refName),
11487 NULL);
11488 FREE_AND_NULL(str)
11489 part = NULL;
11490 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11491 ((WXS_PARTICLE(part))->maxOccurs != 1))
11492 {
11493 xmlChar *str = NULL;
11494 /*
11495 * SPEC src-redefine:
11496 * (6.1.2) "The `actual value` of both that
11497 * group's minOccurs and maxOccurs [attribute]
11498 * must be 1 (or `absent`).
11499 */
11500 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11501 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11502 "The redefining model group definition "
11503 "'%s' must not contain a reference to the "
11504 "redefined definition with a "
11505 "maxOccurs/minOccurs other than 1",
11506 xmlSchemaFormatQName(&str,
11507 ctxt->redef->refTargetNs,
11508 ctxt->redef->refName),
11509 NULL);
11510 FREE_AND_NULL(str)
11511 part = NULL;
11512 }
11513 ctxt->redef->reference = WXS_BASIC_CAST part;
11514 ctxt->redefCounter++;
11515 }
11516 }
11517 } else if (IS_SCHEMA(child, "any")) {
11518 part = (xmlSchemaTreeItemPtr)
11519 xmlSchemaParseAny(ctxt, schema, child);
11520 } else if (IS_SCHEMA(child, "choice")) {
11521 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11522 XML_SCHEMA_TYPE_CHOICE, 1);
11523 } else if (IS_SCHEMA(child, "sequence")) {
11524 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11525 XML_SCHEMA_TYPE_SEQUENCE, 1);
11526 }
11527 if (part != NULL) {
11528 if (last == NULL)
11529 item->children = part;
11530 else
11531 last->next = part;
11532 last = part;
11533 }
11534 child = child->next;
11535 }
11536 if (child != NULL) {
11537 xmlSchemaPContentErr(ctxt,
11538 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11539 NULL, node, child, NULL,
11540 "(annotation?, (element | group | choice | sequence | any)*)");
11541 }
11542 }
11543 if ((max == 0) && (min == 0))
11544 return (NULL);
11545 if (hasRefs) {
11546 /*
11547 * We need to resolve references.
11548 */
11549 WXS_ADD_PENDING(ctxt, item);
11550 }
11551 if (withParticle)
11552 return ((xmlSchemaTreeItemPtr) particle);
11553 else
11554 return ((xmlSchemaTreeItemPtr) item);
11555 }
11556
11557 /**
11558 * xmlSchemaParseRestriction:
11559 * @ctxt: a schema validation context
11560 * @schema: the schema being built
11561 * @node: a subtree containing XML Schema information
11562 *
11563 * parse a XML schema Restriction definition
11564 * *WARNING* this interface is highly subject to change
11565 *
11566 * Returns the type definition or NULL in case of error
11567 */
11568 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11569 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11570 xmlNodePtr node, xmlSchemaTypeType parentType)
11571 {
11572 xmlSchemaTypePtr type;
11573 xmlNodePtr child = NULL;
11574 xmlAttrPtr attr;
11575
11576 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11577 return (NULL);
11578 /* Not a component, don't create it. */
11579 type = ctxt->ctxtType;
11580 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11581
11582 /*
11583 * Check for illegal attributes.
11584 */
11585 attr = node->properties;
11586 while (attr != NULL) {
11587 if (attr->ns == NULL) {
11588 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11589 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11590 xmlSchemaPIllegalAttrErr(ctxt,
11591 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11592 }
11593 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11594 xmlSchemaPIllegalAttrErr(ctxt,
11595 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11596 }
11597 attr = attr->next;
11598 }
11599 /*
11600 * Extract and validate attributes.
11601 */
11602 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11603 /*
11604 * Attribute
11605 */
11606 /*
11607 * Extract the base type. The "base" attribute is mandatory if inside
11608 * a complex type or if redefining.
11609 *
11610 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11611 * among its [children]), the simple type definition which is
11612 * the {content type} of the type definition `resolved` to by
11613 * the `actual value` of the base [attribute]"
11614 */
11615 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11616 &(type->baseNs), &(type->base)) == 0)
11617 {
11618 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11619 xmlSchemaPMissingAttrErr(ctxt,
11620 XML_SCHEMAP_S4S_ATTR_MISSING,
11621 NULL, node, "base", NULL);
11622 } else if ((ctxt->isRedefine) &&
11623 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11624 {
11625 if (type->base == NULL) {
11626 xmlSchemaPMissingAttrErr(ctxt,
11627 XML_SCHEMAP_S4S_ATTR_MISSING,
11628 NULL, node, "base", NULL);
11629 } else if ((! xmlStrEqual(type->base, type->name)) ||
11630 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11631 {
11632 xmlChar *str1 = NULL, *str2 = NULL;
11633 /*
11634 * REDEFINE: SPEC src-redefine (5)
11635 * "Within the [children], each <simpleType> must have a
11636 * <restriction> among its [children] ... the `actual value` of
11637 * whose base [attribute] must be the same as the `actual value`
11638 * of its own name attribute plus target namespace;"
11639 */
11640 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11641 NULL, node, "This is a redefinition, but the QName "
11642 "value '%s' of the 'base' attribute does not match the "
11643 "type's designation '%s'",
11644 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11645 xmlSchemaFormatQName(&str2, type->targetNamespace,
11646 type->name), NULL);
11647 FREE_AND_NULL(str1);
11648 FREE_AND_NULL(str2);
11649 /* Avoid confusion and erase the values. */
11650 type->base = NULL;
11651 type->baseNs = NULL;
11652 }
11653 }
11654 }
11655 /*
11656 * And now for the children...
11657 */
11658 child = node->children;
11659 if (IS_SCHEMA(child, "annotation")) {
11660 /*
11661 * Add the annotation to the simple type ancestor.
11662 */
11663 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11664 xmlSchemaParseAnnotation(ctxt, child, 1));
11665 child = child->next;
11666 }
11667 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11668 /*
11669 * Corresponds to <simpleType><restriction><simpleType>.
11670 */
11671 if (IS_SCHEMA(child, "simpleType")) {
11672 if (type->base != NULL) {
11673 /*
11674 * src-restriction-base-or-simpleType
11675 * Either the base [attribute] or the simpleType [child] of the
11676 * <restriction> element must be present, but not both.
11677 */
11678 xmlSchemaPContentErr(ctxt,
11679 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11680 NULL, node, child,
11681 "The attribute 'base' and the <simpleType> child are "
11682 "mutually exclusive", NULL);
11683 } else {
11684 type->baseType = (xmlSchemaTypePtr)
11685 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11686 }
11687 child = child->next;
11688 } else if (type->base == NULL) {
11689 xmlSchemaPContentErr(ctxt,
11690 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11691 NULL, node, child,
11692 "Either the attribute 'base' or a <simpleType> child "
11693 "must be present", NULL);
11694 }
11695 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11696 /*
11697 * Corresponds to <complexType><complexContent><restriction>...
11698 * followed by:
11699 *
11700 * Model groups <all>, <choice> and <sequence>.
11701 */
11702 if (IS_SCHEMA(child, "all")) {
11703 type->subtypes = (xmlSchemaTypePtr)
11704 xmlSchemaParseModelGroup(ctxt, schema, child,
11705 XML_SCHEMA_TYPE_ALL, 1);
11706 child = child->next;
11707 } else if (IS_SCHEMA(child, "choice")) {
11708 type->subtypes = (xmlSchemaTypePtr)
11709 xmlSchemaParseModelGroup(ctxt,
11710 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11711 child = child->next;
11712 } else if (IS_SCHEMA(child, "sequence")) {
11713 type->subtypes = (xmlSchemaTypePtr)
11714 xmlSchemaParseModelGroup(ctxt, schema, child,
11715 XML_SCHEMA_TYPE_SEQUENCE, 1);
11716 child = child->next;
11717 /*
11718 * Model group reference <group>.
11719 */
11720 } else if (IS_SCHEMA(child, "group")) {
11721 type->subtypes = (xmlSchemaTypePtr)
11722 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11723 /*
11724 * Note that the reference will be resolved in
11725 * xmlSchemaResolveTypeReferences();
11726 */
11727 child = child->next;
11728 }
11729 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11730 /*
11731 * Corresponds to <complexType><simpleContent><restriction>...
11732 *
11733 * "1.1 the simple type definition corresponding to the <simpleType>
11734 * among the [children] of <restriction> if there is one;"
11735 */
11736 if (IS_SCHEMA(child, "simpleType")) {
11737 /*
11738 * We will store the to-be-restricted simple type in
11739 * type->contentTypeDef *temporarily*.
11740 */
11741 type->contentTypeDef = (xmlSchemaTypePtr)
11742 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11743 if ( type->contentTypeDef == NULL)
11744 return (NULL);
11745 child = child->next;
11746 }
11747 }
11748
11749 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11750 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11751 xmlSchemaFacetPtr facet, lastfacet = NULL;
11752 /*
11753 * Corresponds to <complexType><simpleContent><restriction>...
11754 * <simpleType><restriction>...
11755 */
11756
11757 /*
11758 * Add the facets to the simple type ancestor.
11759 */
11760 /*
11761 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11762 * Simple Type Definition Schema Representation Constraint:
11763 * *Single Facet Value*
11764 */
11765 while ((IS_SCHEMA(child, "minInclusive")) ||
11766 (IS_SCHEMA(child, "minExclusive")) ||
11767 (IS_SCHEMA(child, "maxInclusive")) ||
11768 (IS_SCHEMA(child, "maxExclusive")) ||
11769 (IS_SCHEMA(child, "totalDigits")) ||
11770 (IS_SCHEMA(child, "fractionDigits")) ||
11771 (IS_SCHEMA(child, "pattern")) ||
11772 (IS_SCHEMA(child, "enumeration")) ||
11773 (IS_SCHEMA(child, "whiteSpace")) ||
11774 (IS_SCHEMA(child, "length")) ||
11775 (IS_SCHEMA(child, "maxLength")) ||
11776 (IS_SCHEMA(child, "minLength"))) {
11777 facet = xmlSchemaParseFacet(ctxt, schema, child);
11778 if (facet != NULL) {
11779 if (lastfacet == NULL)
11780 type->facets = facet;
11781 else
11782 lastfacet->next = facet;
11783 lastfacet = facet;
11784 lastfacet->next = NULL;
11785 }
11786 child = child->next;
11787 }
11788 /*
11789 * Create links for derivation and validation.
11790 */
11791 if (type->facets != NULL) {
11792 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11793
11794 facet = type->facets;
11795 do {
11796 facetLink = (xmlSchemaFacetLinkPtr)
11797 xmlMalloc(sizeof(xmlSchemaFacetLink));
11798 if (facetLink == NULL) {
11799 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11800 xmlFree(facetLink);
11801 return (NULL);
11802 }
11803 facetLink->facet = facet;
11804 facetLink->next = NULL;
11805 if (lastFacetLink == NULL)
11806 type->facetSet = facetLink;
11807 else
11808 lastFacetLink->next = facetLink;
11809 lastFacetLink = facetLink;
11810 facet = facet->next;
11811 } while (facet != NULL);
11812 }
11813 }
11814 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11815 /*
11816 * Attribute uses/declarations.
11817 */
11818 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11819 (xmlSchemaItemListPtr *) &(type->attrUses),
11820 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11821 return(NULL);
11822 /*
11823 * Attribute wildcard.
11824 */
11825 if (IS_SCHEMA(child, "anyAttribute")) {
11826 type->attributeWildcard =
11827 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11828 child = child->next;
11829 }
11830 }
11831 if (child != NULL) {
11832 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11833 xmlSchemaPContentErr(ctxt,
11834 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11835 NULL, node, child, NULL,
11836 "annotation?, (group | all | choice | sequence)?, "
11837 "((attribute | attributeGroup)*, anyAttribute?))");
11838 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11839 xmlSchemaPContentErr(ctxt,
11840 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11841 NULL, node, child, NULL,
11842 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11843 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11844 "length | minLength | maxLength | enumeration | whiteSpace | "
11845 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11846 } else {
11847 /* Simple type */
11848 xmlSchemaPContentErr(ctxt,
11849 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11850 NULL, node, child, NULL,
11851 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11852 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11853 "length | minLength | maxLength | enumeration | whiteSpace | "
11854 "pattern)*))");
11855 }
11856 }
11857 return (NULL);
11858 }
11859
11860 /**
11861 * xmlSchemaParseExtension:
11862 * @ctxt: a schema validation context
11863 * @schema: the schema being built
11864 * @node: a subtree containing XML Schema information
11865 *
11866 * Parses an <extension>, which is found inside a
11867 * <simpleContent> or <complexContent>.
11868 * *WARNING* this interface is highly subject to change.
11869 *
11870 * TODO: Returns the type definition or NULL in case of error
11871 */
11872 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11873 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11874 xmlNodePtr node, xmlSchemaTypeType parentType)
11875 {
11876 xmlSchemaTypePtr type;
11877 xmlNodePtr child = NULL;
11878 xmlAttrPtr attr;
11879
11880 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11881 return (NULL);
11882 /* Not a component, don't create it. */
11883 type = ctxt->ctxtType;
11884 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11885
11886 /*
11887 * Check for illegal attributes.
11888 */
11889 attr = node->properties;
11890 while (attr != NULL) {
11891 if (attr->ns == NULL) {
11892 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11893 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11894 xmlSchemaPIllegalAttrErr(ctxt,
11895 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11896 }
11897 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11898 xmlSchemaPIllegalAttrErr(ctxt,
11899 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11900 }
11901 attr = attr->next;
11902 }
11903
11904 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11905
11906 /*
11907 * Attribute "base" - mandatory.
11908 */
11909 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11910 "base", &(type->baseNs), &(type->base)) == 0) &&
11911 (type->base == NULL)) {
11912 xmlSchemaPMissingAttrErr(ctxt,
11913 XML_SCHEMAP_S4S_ATTR_MISSING,
11914 NULL, node, "base", NULL);
11915 }
11916 /*
11917 * And now for the children...
11918 */
11919 child = node->children;
11920 if (IS_SCHEMA(child, "annotation")) {
11921 /*
11922 * Add the annotation to the type ancestor.
11923 */
11924 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11925 xmlSchemaParseAnnotation(ctxt, child, 1));
11926 child = child->next;
11927 }
11928 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11929 /*
11930 * Corresponds to <complexType><complexContent><extension>... and:
11931 *
11932 * Model groups <all>, <choice>, <sequence> and <group>.
11933 */
11934 if (IS_SCHEMA(child, "all")) {
11935 type->subtypes = (xmlSchemaTypePtr)
11936 xmlSchemaParseModelGroup(ctxt, schema,
11937 child, XML_SCHEMA_TYPE_ALL, 1);
11938 child = child->next;
11939 } else if (IS_SCHEMA(child, "choice")) {
11940 type->subtypes = (xmlSchemaTypePtr)
11941 xmlSchemaParseModelGroup(ctxt, schema,
11942 child, XML_SCHEMA_TYPE_CHOICE, 1);
11943 child = child->next;
11944 } else if (IS_SCHEMA(child, "sequence")) {
11945 type->subtypes = (xmlSchemaTypePtr)
11946 xmlSchemaParseModelGroup(ctxt, schema,
11947 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11948 child = child->next;
11949 } else if (IS_SCHEMA(child, "group")) {
11950 type->subtypes = (xmlSchemaTypePtr)
11951 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11952 /*
11953 * Note that the reference will be resolved in
11954 * xmlSchemaResolveTypeReferences();
11955 */
11956 child = child->next;
11957 }
11958 }
11959 if (child != NULL) {
11960 /*
11961 * Attribute uses/declarations.
11962 */
11963 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11964 (xmlSchemaItemListPtr *) &(type->attrUses),
11965 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11966 return(NULL);
11967 /*
11968 * Attribute wildcard.
11969 */
11970 if (IS_SCHEMA(child, "anyAttribute")) {
11971 ctxt->ctxtType->attributeWildcard =
11972 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11973 child = child->next;
11974 }
11975 }
11976 if (child != NULL) {
11977 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11978 /* Complex content extension. */
11979 xmlSchemaPContentErr(ctxt,
11980 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11981 NULL, node, child, NULL,
11982 "(annotation?, ((group | all | choice | sequence)?, "
11983 "((attribute | attributeGroup)*, anyAttribute?)))");
11984 } else {
11985 /* Simple content extension. */
11986 xmlSchemaPContentErr(ctxt,
11987 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11988 NULL, node, child, NULL,
11989 "(annotation?, ((attribute | attributeGroup)*, "
11990 "anyAttribute?))");
11991 }
11992 }
11993 return (NULL);
11994 }
11995
11996 /**
11997 * xmlSchemaParseSimpleContent:
11998 * @ctxt: a schema validation context
11999 * @schema: the schema being built
12000 * @node: a subtree containing XML Schema information
12001 *
12002 * parse a XML schema SimpleContent definition
12003 * *WARNING* this interface is highly subject to change
12004 *
12005 * Returns the type definition or NULL in case of error
12006 */
12007 static int
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)12008 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
12009 xmlSchemaPtr schema, xmlNodePtr node,
12010 int *hasRestrictionOrExtension)
12011 {
12012 xmlSchemaTypePtr type;
12013 xmlNodePtr child = NULL;
12014 xmlAttrPtr attr;
12015
12016 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12017 (hasRestrictionOrExtension == NULL))
12018 return (-1);
12019 *hasRestrictionOrExtension = 0;
12020 /* Not a component, don't create it. */
12021 type = ctxt->ctxtType;
12022 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12023 /*
12024 * Check for illegal attributes.
12025 */
12026 attr = node->properties;
12027 while (attr != NULL) {
12028 if (attr->ns == NULL) {
12029 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
12030 xmlSchemaPIllegalAttrErr(ctxt,
12031 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12032 }
12033 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12034 xmlSchemaPIllegalAttrErr(ctxt,
12035 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12036 }
12037 attr = attr->next;
12038 }
12039
12040 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12041
12042 /*
12043 * And now for the children...
12044 */
12045 child = node->children;
12046 if (IS_SCHEMA(child, "annotation")) {
12047 /*
12048 * Add the annotation to the complex type ancestor.
12049 */
12050 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12051 xmlSchemaParseAnnotation(ctxt, child, 1));
12052 child = child->next;
12053 }
12054 if (child == NULL) {
12055 xmlSchemaPContentErr(ctxt,
12056 XML_SCHEMAP_S4S_ELEM_MISSING,
12057 NULL, node, NULL, NULL,
12058 "(annotation?, (restriction | extension))");
12059 }
12060 if (child == NULL) {
12061 xmlSchemaPContentErr(ctxt,
12062 XML_SCHEMAP_S4S_ELEM_MISSING,
12063 NULL, node, NULL, NULL,
12064 "(annotation?, (restriction | extension))");
12065 }
12066 if (IS_SCHEMA(child, "restriction")) {
12067 xmlSchemaParseRestriction(ctxt, schema, child,
12068 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12069 (*hasRestrictionOrExtension) = 1;
12070 child = child->next;
12071 } else if (IS_SCHEMA(child, "extension")) {
12072 xmlSchemaParseExtension(ctxt, schema, child,
12073 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12074 (*hasRestrictionOrExtension) = 1;
12075 child = child->next;
12076 }
12077 if (child != NULL) {
12078 xmlSchemaPContentErr(ctxt,
12079 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12080 NULL, node, child, NULL,
12081 "(annotation?, (restriction | extension))");
12082 }
12083 return (0);
12084 }
12085
12086 /**
12087 * xmlSchemaParseComplexContent:
12088 * @ctxt: a schema validation context
12089 * @schema: the schema being built
12090 * @node: a subtree containing XML Schema information
12091 *
12092 * parse a XML schema ComplexContent definition
12093 * *WARNING* this interface is highly subject to change
12094 *
12095 * Returns the type definition or NULL in case of error
12096 */
12097 static int
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)12098 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12099 xmlSchemaPtr schema, xmlNodePtr node,
12100 int *hasRestrictionOrExtension)
12101 {
12102 xmlSchemaTypePtr type;
12103 xmlNodePtr child = NULL;
12104 xmlAttrPtr attr;
12105
12106 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12107 (hasRestrictionOrExtension == NULL))
12108 return (-1);
12109 *hasRestrictionOrExtension = 0;
12110 /* Not a component, don't create it. */
12111 type = ctxt->ctxtType;
12112 /*
12113 * Check for illegal attributes.
12114 */
12115 attr = node->properties;
12116 while (attr != NULL) {
12117 if (attr->ns == NULL) {
12118 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12119 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12120 {
12121 xmlSchemaPIllegalAttrErr(ctxt,
12122 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12123 }
12124 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12125 xmlSchemaPIllegalAttrErr(ctxt,
12126 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12127 }
12128 attr = attr->next;
12129 }
12130
12131 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12132
12133 /*
12134 * Set the 'mixed' on the complex type ancestor.
12135 */
12136 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
12137 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12138 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12139 }
12140 child = node->children;
12141 if (IS_SCHEMA(child, "annotation")) {
12142 /*
12143 * Add the annotation to the complex type ancestor.
12144 */
12145 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12146 xmlSchemaParseAnnotation(ctxt, child, 1));
12147 child = child->next;
12148 }
12149 if (child == NULL) {
12150 xmlSchemaPContentErr(ctxt,
12151 XML_SCHEMAP_S4S_ELEM_MISSING,
12152 NULL, node, NULL,
12153 NULL, "(annotation?, (restriction | extension))");
12154 }
12155 if (child == NULL) {
12156 xmlSchemaPContentErr(ctxt,
12157 XML_SCHEMAP_S4S_ELEM_MISSING,
12158 NULL, node, NULL,
12159 NULL, "(annotation?, (restriction | extension))");
12160 }
12161 if (IS_SCHEMA(child, "restriction")) {
12162 xmlSchemaParseRestriction(ctxt, schema, child,
12163 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12164 (*hasRestrictionOrExtension) = 1;
12165 child = child->next;
12166 } else if (IS_SCHEMA(child, "extension")) {
12167 xmlSchemaParseExtension(ctxt, schema, child,
12168 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12169 (*hasRestrictionOrExtension) = 1;
12170 child = child->next;
12171 }
12172 if (child != NULL) {
12173 xmlSchemaPContentErr(ctxt,
12174 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12175 NULL, node, child,
12176 NULL, "(annotation?, (restriction | extension))");
12177 }
12178 return (0);
12179 }
12180
12181 /**
12182 * xmlSchemaParseComplexType:
12183 * @ctxt: a schema validation context
12184 * @schema: the schema being built
12185 * @node: a subtree containing XML Schema information
12186 *
12187 * parse a XML schema Complex Type definition
12188 * *WARNING* this interface is highly subject to change
12189 *
12190 * Returns the type definition or NULL in case of error
12191 */
12192 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)12193 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12194 xmlNodePtr node, int topLevel)
12195 {
12196 xmlSchemaTypePtr type, ctxtType;
12197 xmlNodePtr child = NULL;
12198 const xmlChar *name = NULL;
12199 xmlAttrPtr attr;
12200 const xmlChar *attrValue;
12201 #ifdef ENABLE_NAMED_LOCALS
12202 char buf[40];
12203 #endif
12204 int final = 0, block = 0, hasRestrictionOrExtension = 0;
12205
12206
12207 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12208 return (NULL);
12209
12210 ctxtType = ctxt->ctxtType;
12211
12212 if (topLevel) {
12213 attr = xmlSchemaGetPropNode(node, "name");
12214 if (attr == NULL) {
12215 xmlSchemaPMissingAttrErr(ctxt,
12216 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12217 return (NULL);
12218 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12219 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12220 return (NULL);
12221 }
12222 }
12223
12224 if (topLevel == 0) {
12225 /*
12226 * Parse as local complex type definition.
12227 */
12228 #ifdef ENABLE_NAMED_LOCALS
12229 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12230 type = xmlSchemaAddType(ctxt, schema,
12231 XML_SCHEMA_TYPE_COMPLEX,
12232 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12233 ctxt->targetNamespace, node, 0);
12234 #else
12235 type = xmlSchemaAddType(ctxt, schema,
12236 XML_SCHEMA_TYPE_COMPLEX,
12237 NULL, ctxt->targetNamespace, node, 0);
12238 #endif
12239 if (type == NULL)
12240 return (NULL);
12241 name = type->name;
12242 type->node = node;
12243 type->type = XML_SCHEMA_TYPE_COMPLEX;
12244 /*
12245 * TODO: We need the target namespace.
12246 */
12247 } else {
12248 /*
12249 * Parse as global complex type definition.
12250 */
12251 type = xmlSchemaAddType(ctxt, schema,
12252 XML_SCHEMA_TYPE_COMPLEX,
12253 name, ctxt->targetNamespace, node, 1);
12254 if (type == NULL)
12255 return (NULL);
12256 type->node = node;
12257 type->type = XML_SCHEMA_TYPE_COMPLEX;
12258 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12259 }
12260 type->targetNamespace = ctxt->targetNamespace;
12261 /*
12262 * Handle attributes.
12263 */
12264 attr = node->properties;
12265 while (attr != NULL) {
12266 if (attr->ns == NULL) {
12267 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12268 /*
12269 * Attribute "id".
12270 */
12271 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12272 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12273 /*
12274 * Attribute "mixed".
12275 */
12276 if (xmlSchemaPGetBoolNodeValue(ctxt,
12277 NULL, (xmlNodePtr) attr))
12278 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12279 } else if (topLevel) {
12280 /*
12281 * Attributes of global complex type definitions.
12282 */
12283 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12284 /* Pass. */
12285 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12286 /*
12287 * Attribute "abstract".
12288 */
12289 if (xmlSchemaPGetBoolNodeValue(ctxt,
12290 NULL, (xmlNodePtr) attr))
12291 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12292 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12293 /*
12294 * Attribute "final".
12295 */
12296 attrValue = xmlSchemaGetNodeContent(ctxt,
12297 (xmlNodePtr) attr);
12298 if (xmlSchemaPValAttrBlockFinal(attrValue,
12299 &(type->flags),
12300 -1,
12301 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12302 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12303 -1, -1, -1) != 0)
12304 {
12305 xmlSchemaPSimpleTypeErr(ctxt,
12306 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12307 NULL, (xmlNodePtr) attr, NULL,
12308 "(#all | List of (extension | restriction))",
12309 attrValue, NULL, NULL, NULL);
12310 } else
12311 final = 1;
12312 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12313 /*
12314 * Attribute "block".
12315 */
12316 attrValue = xmlSchemaGetNodeContent(ctxt,
12317 (xmlNodePtr) attr);
12318 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12319 -1,
12320 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12321 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12322 -1, -1, -1) != 0) {
12323 xmlSchemaPSimpleTypeErr(ctxt,
12324 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12325 NULL, (xmlNodePtr) attr, NULL,
12326 "(#all | List of (extension | restriction)) ",
12327 attrValue, NULL, NULL, NULL);
12328 } else
12329 block = 1;
12330 } else {
12331 xmlSchemaPIllegalAttrErr(ctxt,
12332 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12333 }
12334 } else {
12335 xmlSchemaPIllegalAttrErr(ctxt,
12336 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12337 }
12338 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12339 xmlSchemaPIllegalAttrErr(ctxt,
12340 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12341 }
12342 attr = attr->next;
12343 }
12344 if (! block) {
12345 /*
12346 * Apply default "block" values.
12347 */
12348 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12349 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12350 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12351 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12352 }
12353 if (! final) {
12354 /*
12355 * Apply default "block" values.
12356 */
12357 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12358 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12359 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12360 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12361 }
12362 /*
12363 * And now for the children...
12364 */
12365 child = node->children;
12366 if (IS_SCHEMA(child, "annotation")) {
12367 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12368 child = child->next;
12369 }
12370 ctxt->ctxtType = type;
12371 if (IS_SCHEMA(child, "simpleContent")) {
12372 /*
12373 * <complexType><simpleContent>...
12374 * 3.4.3 : 2.2
12375 * Specifying mixed='true' when the <simpleContent>
12376 * alternative is chosen has no effect
12377 */
12378 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12379 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12380 xmlSchemaParseSimpleContent(ctxt, schema, child,
12381 &hasRestrictionOrExtension);
12382 child = child->next;
12383 } else if (IS_SCHEMA(child, "complexContent")) {
12384 /*
12385 * <complexType><complexContent>...
12386 */
12387 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12388 xmlSchemaParseComplexContent(ctxt, schema, child,
12389 &hasRestrictionOrExtension);
12390 child = child->next;
12391 } else {
12392 /*
12393 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12394 *
12395 * SPEC
12396 * "...the third alternative (neither <simpleContent> nor
12397 * <complexContent>) is chosen. This case is understood as shorthand
12398 * for complex content restricting the `ur-type definition`, and the
12399 * details of the mappings should be modified as necessary.
12400 */
12401 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12402 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12403 /*
12404 * Parse model groups.
12405 */
12406 if (IS_SCHEMA(child, "all")) {
12407 type->subtypes = (xmlSchemaTypePtr)
12408 xmlSchemaParseModelGroup(ctxt, schema, child,
12409 XML_SCHEMA_TYPE_ALL, 1);
12410 child = child->next;
12411 } else if (IS_SCHEMA(child, "choice")) {
12412 type->subtypes = (xmlSchemaTypePtr)
12413 xmlSchemaParseModelGroup(ctxt, schema, child,
12414 XML_SCHEMA_TYPE_CHOICE, 1);
12415 child = child->next;
12416 } else if (IS_SCHEMA(child, "sequence")) {
12417 type->subtypes = (xmlSchemaTypePtr)
12418 xmlSchemaParseModelGroup(ctxt, schema, child,
12419 XML_SCHEMA_TYPE_SEQUENCE, 1);
12420 child = child->next;
12421 } else if (IS_SCHEMA(child, "group")) {
12422 type->subtypes = (xmlSchemaTypePtr)
12423 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12424 /*
12425 * Note that the reference will be resolved in
12426 * xmlSchemaResolveTypeReferences();
12427 */
12428 child = child->next;
12429 }
12430 /*
12431 * Parse attribute decls/refs.
12432 */
12433 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12434 (xmlSchemaItemListPtr *) &(type->attrUses),
12435 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12436 return(NULL);
12437 /*
12438 * Parse attribute wildcard.
12439 */
12440 if (IS_SCHEMA(child, "anyAttribute")) {
12441 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12442 child = child->next;
12443 }
12444 }
12445 if (child != NULL) {
12446 xmlSchemaPContentErr(ctxt,
12447 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12448 NULL, node, child,
12449 NULL, "(annotation?, (simpleContent | complexContent | "
12450 "((group | all | choice | sequence)?, ((attribute | "
12451 "attributeGroup)*, anyAttribute?))))");
12452 }
12453 /*
12454 * REDEFINE: SPEC src-redefine (5)
12455 */
12456 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12457 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12458 NULL, node, "This is a redefinition, thus the "
12459 "<complexType> must have a <restriction> or <extension> "
12460 "grand-child", NULL);
12461 }
12462 ctxt->ctxtType = ctxtType;
12463 return (type);
12464 }
12465
12466 /************************************************************************
12467 * *
12468 * Validating using Schemas *
12469 * *
12470 ************************************************************************/
12471
12472 /************************************************************************
12473 * *
12474 * Reading/Writing Schemas *
12475 * *
12476 ************************************************************************/
12477
12478 #if 0 /* Will be enabled if it is clear what options are needed. */
12479 /**
12480 * xmlSchemaParserCtxtSetOptions:
12481 * @ctxt: a schema parser context
12482 * @options: a combination of xmlSchemaParserOption
12483 *
12484 * Sets the options to be used during the parse.
12485 *
12486 * Returns 0 in case of success, -1 in case of an
12487 * API error.
12488 */
12489 static int
12490 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12491 int options)
12492
12493 {
12494 int i;
12495
12496 if (ctxt == NULL)
12497 return (-1);
12498 /*
12499 * WARNING: Change the start value if adding to the
12500 * xmlSchemaParseOption.
12501 */
12502 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12503 if (options & 1<<i) {
12504 return (-1);
12505 }
12506 }
12507 ctxt->options = options;
12508 return (0);
12509 }
12510
12511 /**
12512 * xmlSchemaValidCtxtGetOptions:
12513 * @ctxt: a schema parser context
12514 *
12515 * Returns the option combination of the parser context.
12516 */
12517 static int
12518 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12519
12520 {
12521 if (ctxt == NULL)
12522 return (-1);
12523 else
12524 return (ctxt->options);
12525 }
12526 #endif
12527
12528 /**
12529 * xmlSchemaNewParserCtxt:
12530 * @URL: the location of the schema
12531 *
12532 * Create an XML Schemas parse context for that file/resource expected
12533 * to contain an XML Schemas file.
12534 *
12535 * Returns the parser context or NULL in case of error
12536 */
12537 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)12538 xmlSchemaNewParserCtxt(const char *URL)
12539 {
12540 xmlSchemaParserCtxtPtr ret;
12541
12542 if (URL == NULL)
12543 return (NULL);
12544
12545 ret = xmlSchemaParserCtxtCreate();
12546 if (ret == NULL)
12547 return(NULL);
12548 ret->dict = xmlDictCreate();
12549 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12550 return (ret);
12551 }
12552
12553 /**
12554 * xmlSchemaNewMemParserCtxt:
12555 * @buffer: a pointer to a char array containing the schemas
12556 * @size: the size of the array
12557 *
12558 * Create an XML Schemas parse context for that memory buffer expected
12559 * to contain an XML Schemas file.
12560 *
12561 * Returns the parser context or NULL in case of error
12562 */
12563 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)12564 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12565 {
12566 xmlSchemaParserCtxtPtr ret;
12567
12568 if ((buffer == NULL) || (size <= 0))
12569 return (NULL);
12570 ret = xmlSchemaParserCtxtCreate();
12571 if (ret == NULL)
12572 return(NULL);
12573 ret->buffer = buffer;
12574 ret->size = size;
12575 ret->dict = xmlDictCreate();
12576 return (ret);
12577 }
12578
12579 /**
12580 * xmlSchemaNewDocParserCtxt:
12581 * @doc: a preparsed document tree
12582 *
12583 * Create an XML Schemas parse context for that document.
12584 * NB. The document may be modified during the parsing process.
12585 *
12586 * Returns the parser context or NULL in case of error
12587 */
12588 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)12589 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12590 {
12591 xmlSchemaParserCtxtPtr ret;
12592
12593 if (doc == NULL)
12594 return (NULL);
12595 ret = xmlSchemaParserCtxtCreate();
12596 if (ret == NULL)
12597 return(NULL);
12598 ret->doc = doc;
12599 ret->dict = xmlDictCreate();
12600 /* The application has responsibility for the document */
12601 ret->preserve = 1;
12602
12603 return (ret);
12604 }
12605
12606 /**
12607 * xmlSchemaFreeParserCtxt:
12608 * @ctxt: the schema parser context
12609 *
12610 * Free the resources associated to the schema parser context
12611 */
12612 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)12613 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12614 {
12615 if (ctxt == NULL)
12616 return;
12617 if (ctxt->doc != NULL && !ctxt->preserve)
12618 xmlFreeDoc(ctxt->doc);
12619 if (ctxt->vctxt != NULL) {
12620 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12621 }
12622 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12623 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12624 ctxt->constructor = NULL;
12625 ctxt->ownsConstructor = 0;
12626 }
12627 if (ctxt->attrProhibs != NULL)
12628 xmlSchemaItemListFree(ctxt->attrProhibs);
12629 xmlDictFree(ctxt->dict);
12630 xmlFree(ctxt);
12631 }
12632
12633 /************************************************************************
12634 * *
12635 * Building the content models *
12636 * *
12637 ************************************************************************/
12638
12639 /**
12640 * xmlSchemaBuildContentModelForSubstGroup:
12641 *
12642 * Returns 1 if nillable, 0 otherwise
12643 */
12644 static int
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle,int counter,xmlAutomataStatePtr end)12645 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12646 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12647 {
12648 xmlAutomataStatePtr start, tmp;
12649 xmlSchemaElementPtr elemDecl, member;
12650 xmlSchemaSubstGroupPtr substGroup;
12651 int i;
12652 int ret = 0;
12653
12654 elemDecl = (xmlSchemaElementPtr) particle->children;
12655 /*
12656 * Wrap the substitution group with a CHOICE.
12657 */
12658 start = pctxt->state;
12659 if (end == NULL)
12660 end = xmlAutomataNewState(pctxt->am);
12661 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12662 if (substGroup == NULL) {
12663 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12664 XML_SCHEMAP_INTERNAL,
12665 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12666 "declaration is marked having a subst. group but none "
12667 "available.\n", elemDecl->name, NULL);
12668 return(0);
12669 }
12670 if (counter >= 0) {
12671 /*
12672 * NOTE that we put the declaration in, even if it's abstract.
12673 * However, an error will be raised during *validation* if an element
12674 * information item shall be validated against an abstract element
12675 * declaration.
12676 */
12677 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12678 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12679 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12680 /*
12681 * Add subst. group members.
12682 */
12683 for (i = 0; i < substGroup->members->nbItems; i++) {
12684 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12685 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12686 member->name, member->targetNamespace, member);
12687 }
12688 } else if (particle->maxOccurs == 1) {
12689 /*
12690 * NOTE that we put the declaration in, even if it's abstract,
12691 */
12692 xmlAutomataNewEpsilon(pctxt->am,
12693 xmlAutomataNewTransition2(pctxt->am,
12694 start, NULL,
12695 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12696 /*
12697 * Add subst. group members.
12698 */
12699 for (i = 0; i < substGroup->members->nbItems; i++) {
12700 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12701 /*
12702 * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12703 * was incorrectly used instead of xmlAutomataNewTransition2()
12704 * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12705 * section in xmlSchemaBuildAContentModel() ).
12706 * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12707 * intended for the above "counter" section originally. I.e.,
12708 * check xs:all with subst-groups.
12709 *
12710 * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12711 * member->name, member->targetNamespace,
12712 * 1, 1, member);
12713 */
12714 tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12715 member->name, member->targetNamespace, member);
12716 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12717 }
12718 } else {
12719 xmlAutomataStatePtr hop;
12720 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12721 UNBOUNDED : particle->maxOccurs - 1;
12722 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12723
12724 counter =
12725 xmlAutomataNewCounter(pctxt->am, minOccurs,
12726 maxOccurs);
12727 hop = xmlAutomataNewState(pctxt->am);
12728
12729 xmlAutomataNewEpsilon(pctxt->am,
12730 xmlAutomataNewTransition2(pctxt->am,
12731 start, NULL,
12732 elemDecl->name, elemDecl->targetNamespace, elemDecl),
12733 hop);
12734 /*
12735 * Add subst. group members.
12736 */
12737 for (i = 0; i < substGroup->members->nbItems; i++) {
12738 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12739 xmlAutomataNewEpsilon(pctxt->am,
12740 xmlAutomataNewTransition2(pctxt->am,
12741 start, NULL,
12742 member->name, member->targetNamespace, member),
12743 hop);
12744 }
12745 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12746 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12747 }
12748 if (particle->minOccurs == 0) {
12749 xmlAutomataNewEpsilon(pctxt->am, start, end);
12750 ret = 1;
12751 }
12752 pctxt->state = end;
12753 return(ret);
12754 }
12755
12756 /**
12757 * xmlSchemaBuildContentModelForElement:
12758 *
12759 * Returns 1 if nillable, 0 otherwise
12760 */
12761 static int
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr particle)12762 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12763 xmlSchemaParticlePtr particle)
12764 {
12765 int ret = 0;
12766
12767 if (((xmlSchemaElementPtr) particle->children)->flags &
12768 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12769 /*
12770 * Substitution groups.
12771 */
12772 ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12773 } else {
12774 xmlSchemaElementPtr elemDecl;
12775 xmlAutomataStatePtr start;
12776
12777 elemDecl = (xmlSchemaElementPtr) particle->children;
12778
12779 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12780 return(0);
12781 if (particle->maxOccurs == 1) {
12782 start = ctxt->state;
12783 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12784 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12785 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12786 (particle->minOccurs < 2)) {
12787 /* Special case. */
12788 start = ctxt->state;
12789 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12790 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12791 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12792 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12793 } else {
12794 int counter;
12795 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12796 UNBOUNDED : particle->maxOccurs - 1;
12797 int minOccurs = particle->minOccurs < 1 ?
12798 0 : particle->minOccurs - 1;
12799
12800 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12801 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12802 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12803 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12804 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12805 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12806 NULL, counter);
12807 }
12808 if (particle->minOccurs == 0) {
12809 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12810 ret = 1;
12811 }
12812 }
12813 return(ret);
12814 }
12815
12816 /**
12817 * xmlSchemaBuildAContentModel:
12818 * @ctxt: the schema parser context
12819 * @particle: the particle component
12820 * @name: the complex type's name whose content is being built
12821 *
12822 * Create the automaton for the {content type} of a complex type.
12823 *
12824 * Returns 1 if the content is nillable, 0 otherwise
12825 */
12826 static int
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle)12827 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12828 xmlSchemaParticlePtr particle)
12829 {
12830 int ret = 0, tmp2;
12831
12832 if (particle == NULL) {
12833 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12834 return(1);
12835 }
12836 if (particle->children == NULL) {
12837 /*
12838 * Just return in this case. A missing "term" of the particle
12839 * might arise due to an invalid "term" component.
12840 */
12841 return(1);
12842 }
12843
12844 switch (particle->children->type) {
12845 case XML_SCHEMA_TYPE_ANY: {
12846 xmlAutomataStatePtr start, end;
12847 xmlSchemaWildcardPtr wild;
12848 xmlSchemaWildcardNsPtr ns;
12849
12850 wild = (xmlSchemaWildcardPtr) particle->children;
12851
12852 start = pctxt->state;
12853 end = xmlAutomataNewState(pctxt->am);
12854
12855 if (particle->maxOccurs == 1) {
12856 if (wild->any == 1) {
12857 /*
12858 * We need to add both transitions:
12859 *
12860 * 1. the {"*", "*"} for elements in a namespace.
12861 */
12862 pctxt->state =
12863 xmlAutomataNewTransition2(pctxt->am,
12864 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12865 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12866 /*
12867 * 2. the {"*"} for elements in no namespace.
12868 */
12869 pctxt->state =
12870 xmlAutomataNewTransition2(pctxt->am,
12871 start, NULL, BAD_CAST "*", NULL, wild);
12872 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12873
12874 } else if (wild->nsSet != NULL) {
12875 ns = wild->nsSet;
12876 do {
12877 pctxt->state = start;
12878 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12879 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12880 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12881 ns = ns->next;
12882 } while (ns != NULL);
12883
12884 } else if (wild->negNsSet != NULL) {
12885 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12886 start, end, BAD_CAST "*", wild->negNsSet->value,
12887 wild);
12888 }
12889 } else {
12890 int counter;
12891 xmlAutomataStatePtr hop;
12892 int maxOccurs =
12893 particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12894 particle->maxOccurs - 1;
12895 int minOccurs =
12896 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12897
12898 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12899 hop = xmlAutomataNewState(pctxt->am);
12900 if (wild->any == 1) {
12901 pctxt->state =
12902 xmlAutomataNewTransition2(pctxt->am,
12903 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12904 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12905 pctxt->state =
12906 xmlAutomataNewTransition2(pctxt->am,
12907 start, NULL, BAD_CAST "*", NULL, wild);
12908 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12909 } else if (wild->nsSet != NULL) {
12910 ns = wild->nsSet;
12911 do {
12912 pctxt->state =
12913 xmlAutomataNewTransition2(pctxt->am,
12914 start, NULL, BAD_CAST "*", ns->value, wild);
12915 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12916 ns = ns->next;
12917 } while (ns != NULL);
12918
12919 } else if (wild->negNsSet != NULL) {
12920 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12921 start, hop, BAD_CAST "*", wild->negNsSet->value,
12922 wild);
12923 }
12924 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12925 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12926 }
12927 if (particle->minOccurs == 0) {
12928 xmlAutomataNewEpsilon(pctxt->am, start, end);
12929 ret = 1;
12930 }
12931 pctxt->state = end;
12932 break;
12933 }
12934 case XML_SCHEMA_TYPE_ELEMENT:
12935 ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12936 break;
12937 case XML_SCHEMA_TYPE_SEQUENCE:{
12938 xmlSchemaTreeItemPtr sub;
12939
12940 ret = 1;
12941 /*
12942 * If max and min occurrences are default (1) then
12943 * simply iterate over the particles of the <sequence>.
12944 */
12945 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12946 sub = particle->children->children;
12947
12948 while (sub != NULL) {
12949 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12950 (xmlSchemaParticlePtr) sub);
12951 if (tmp2 != 1) ret = 0;
12952 sub = sub->next;
12953 }
12954 } else {
12955 xmlAutomataStatePtr oldstate = pctxt->state;
12956
12957 if (particle->maxOccurs >= UNBOUNDED) {
12958 if (particle->minOccurs > 1) {
12959 xmlAutomataStatePtr tmp;
12960 int counter;
12961
12962 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12963 oldstate, NULL);
12964 oldstate = pctxt->state;
12965
12966 counter = xmlAutomataNewCounter(pctxt->am,
12967 particle->minOccurs - 1, UNBOUNDED);
12968
12969 sub = particle->children->children;
12970 while (sub != NULL) {
12971 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12972 (xmlSchemaParticlePtr) sub);
12973 if (tmp2 != 1) ret = 0;
12974 sub = sub->next;
12975 }
12976 tmp = pctxt->state;
12977 xmlAutomataNewCountedTrans(pctxt->am, tmp,
12978 oldstate, counter);
12979 pctxt->state =
12980 xmlAutomataNewCounterTrans(pctxt->am, tmp,
12981 NULL, counter);
12982 if (ret == 1)
12983 xmlAutomataNewEpsilon(pctxt->am,
12984 oldstate, pctxt->state);
12985
12986 } else {
12987 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12988 oldstate, NULL);
12989 oldstate = pctxt->state;
12990
12991 sub = particle->children->children;
12992 while (sub != NULL) {
12993 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12994 (xmlSchemaParticlePtr) sub);
12995 if (tmp2 != 1) ret = 0;
12996 sub = sub->next;
12997 }
12998 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12999 oldstate);
13000 /*
13001 * epsilon needed to block previous trans from
13002 * being allowed to enter back from another
13003 * construct
13004 */
13005 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13006 pctxt->state, NULL);
13007 if (particle->minOccurs == 0) {
13008 xmlAutomataNewEpsilon(pctxt->am,
13009 oldstate, pctxt->state);
13010 ret = 1;
13011 }
13012 }
13013 } else if ((particle->maxOccurs > 1)
13014 || (particle->minOccurs > 1)) {
13015 xmlAutomataStatePtr tmp;
13016 int counter;
13017
13018 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13019 oldstate, NULL);
13020 oldstate = pctxt->state;
13021
13022 counter = xmlAutomataNewCounter(pctxt->am,
13023 particle->minOccurs - 1,
13024 particle->maxOccurs - 1);
13025
13026 sub = particle->children->children;
13027 while (sub != NULL) {
13028 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13029 (xmlSchemaParticlePtr) sub);
13030 if (tmp2 != 1) ret = 0;
13031 sub = sub->next;
13032 }
13033 tmp = pctxt->state;
13034 xmlAutomataNewCountedTrans(pctxt->am,
13035 tmp, oldstate, counter);
13036 pctxt->state =
13037 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
13038 counter);
13039 if ((particle->minOccurs == 0) || (ret == 1)) {
13040 xmlAutomataNewEpsilon(pctxt->am,
13041 oldstate, pctxt->state);
13042 ret = 1;
13043 }
13044 } else {
13045 sub = particle->children->children;
13046 while (sub != NULL) {
13047 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13048 (xmlSchemaParticlePtr) sub);
13049 if (tmp2 != 1) ret = 0;
13050 sub = sub->next;
13051 }
13052
13053 /*
13054 * epsilon needed to block previous trans from
13055 * being allowed to enter back from another
13056 * construct
13057 */
13058 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13059 pctxt->state, NULL);
13060
13061 if (particle->minOccurs == 0) {
13062 xmlAutomataNewEpsilon(pctxt->am, oldstate,
13063 pctxt->state);
13064 ret = 1;
13065 }
13066 }
13067 }
13068 break;
13069 }
13070 case XML_SCHEMA_TYPE_CHOICE:{
13071 xmlSchemaTreeItemPtr sub;
13072 xmlAutomataStatePtr start, end;
13073
13074 ret = 0;
13075 start = pctxt->state;
13076 end = xmlAutomataNewState(pctxt->am);
13077
13078 /*
13079 * iterate over the subtypes and remerge the end with an
13080 * epsilon transition
13081 */
13082 if (particle->maxOccurs == 1) {
13083 sub = particle->children->children;
13084 while (sub != NULL) {
13085 pctxt->state = start;
13086 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13087 (xmlSchemaParticlePtr) sub);
13088 if (tmp2 == 1) ret = 1;
13089 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13090 sub = sub->next;
13091 }
13092 } else {
13093 int counter;
13094 xmlAutomataStatePtr hop, base;
13095 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13096 UNBOUNDED : particle->maxOccurs - 1;
13097 int minOccurs =
13098 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13099
13100 /*
13101 * use a counter to keep track of the number of transitions
13102 * which went through the choice.
13103 */
13104 counter =
13105 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13106 hop = xmlAutomataNewState(pctxt->am);
13107 base = xmlAutomataNewState(pctxt->am);
13108
13109 sub = particle->children->children;
13110 while (sub != NULL) {
13111 pctxt->state = base;
13112 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13113 (xmlSchemaParticlePtr) sub);
13114 if (tmp2 == 1) ret = 1;
13115 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13116 sub = sub->next;
13117 }
13118 xmlAutomataNewEpsilon(pctxt->am, start, base);
13119 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13120 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13121 if (ret == 1)
13122 xmlAutomataNewEpsilon(pctxt->am, base, end);
13123 }
13124 if (particle->minOccurs == 0) {
13125 xmlAutomataNewEpsilon(pctxt->am, start, end);
13126 ret = 1;
13127 }
13128 pctxt->state = end;
13129 break;
13130 }
13131 case XML_SCHEMA_TYPE_ALL:{
13132 xmlAutomataStatePtr start, tmp;
13133 xmlSchemaParticlePtr sub;
13134 xmlSchemaElementPtr elemDecl;
13135
13136 ret = 1;
13137
13138 sub = (xmlSchemaParticlePtr) particle->children->children;
13139 if (sub == NULL)
13140 break;
13141
13142 ret = 0;
13143
13144 start = pctxt->state;
13145 tmp = xmlAutomataNewState(pctxt->am);
13146 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13147 pctxt->state = tmp;
13148 while (sub != NULL) {
13149 pctxt->state = tmp;
13150
13151 elemDecl = (xmlSchemaElementPtr) sub->children;
13152 if (elemDecl == NULL) {
13153 PERROR_INT("xmlSchemaBuildAContentModel",
13154 "<element> particle has no term");
13155 return(ret);
13156 };
13157 /*
13158 * NOTE: The {max occurs} of all the particles in the
13159 * {particles} of the group must be 0 or 1; this is
13160 * already ensured during the parse of the content of
13161 * <all>.
13162 */
13163 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13164 int counter;
13165
13166 /*
13167 * This is an abstract group, we need to share
13168 * the same counter for all the element transitions
13169 * derived from the group
13170 */
13171 counter = xmlAutomataNewCounter(pctxt->am,
13172 sub->minOccurs, sub->maxOccurs);
13173 xmlSchemaBuildContentModelForSubstGroup(pctxt,
13174 sub, counter, pctxt->state);
13175 } else {
13176 if ((sub->minOccurs == 1) &&
13177 (sub->maxOccurs == 1)) {
13178 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13179 pctxt->state,
13180 elemDecl->name,
13181 elemDecl->targetNamespace,
13182 1, 1, elemDecl);
13183 } else if ((sub->minOccurs == 0) &&
13184 (sub->maxOccurs == 1)) {
13185
13186 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13187 pctxt->state,
13188 elemDecl->name,
13189 elemDecl->targetNamespace,
13190 0,
13191 1,
13192 elemDecl);
13193 }
13194 }
13195 sub = (xmlSchemaParticlePtr) sub->next;
13196 }
13197 pctxt->state =
13198 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13199 if (particle->minOccurs == 0) {
13200 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13201 ret = 1;
13202 }
13203 break;
13204 }
13205 case XML_SCHEMA_TYPE_GROUP:
13206 /*
13207 * If we hit a model group definition, then this means that
13208 * it was empty, thus was not substituted for the containing
13209 * model group. Just do nothing in this case.
13210 * TODO: But the group should be substituted and not occur at
13211 * all in the content model at this point. Fix this.
13212 */
13213 ret = 1;
13214 break;
13215 default:
13216 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13217 "xmlSchemaBuildAContentModel",
13218 "found unexpected term of type '%s' in content model",
13219 WXS_ITEM_TYPE_NAME(particle->children), NULL);
13220 return(ret);
13221 }
13222 return(ret);
13223 }
13224
13225 /**
13226 * xmlSchemaBuildContentModel:
13227 * @ctxt: the schema parser context
13228 * @type: the complex type definition
13229 * @name: the element name
13230 *
13231 * Builds the content model of the complex type.
13232 */
13233 static void
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)13234 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13235 xmlSchemaParserCtxtPtr ctxt)
13236 {
13237 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13238 (type->contModel != NULL) ||
13239 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13240 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13241 return;
13242
13243 #ifdef DEBUG_CONTENT
13244 xmlGenericError(xmlGenericErrorContext,
13245 "Building content model for %s\n", name);
13246 #endif
13247 ctxt->am = NULL;
13248 ctxt->am = xmlNewAutomata();
13249 if (ctxt->am == NULL) {
13250 xmlGenericError(xmlGenericErrorContext,
13251 "Cannot create automata for complex type %s\n", type->name);
13252 return;
13253 }
13254 ctxt->state = xmlAutomataGetInitState(ctxt->am);
13255 /*
13256 * Build the automaton.
13257 */
13258 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13259 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13260 type->contModel = xmlAutomataCompile(ctxt->am);
13261 if (type->contModel == NULL) {
13262 xmlSchemaPCustomErr(ctxt,
13263 XML_SCHEMAP_INTERNAL,
13264 WXS_BASIC_CAST type, type->node,
13265 "Failed to compile the content model", NULL);
13266 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13267 xmlSchemaPCustomErr(ctxt,
13268 XML_SCHEMAP_NOT_DETERMINISTIC,
13269 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13270 WXS_BASIC_CAST type, type->node,
13271 "The content model is not determinist", NULL);
13272 } else {
13273 #ifdef DEBUG_CONTENT_REGEXP
13274 xmlGenericError(xmlGenericErrorContext,
13275 "Content model of %s:\n", type->name);
13276 xmlRegexpPrint(stderr, type->contModel);
13277 #endif
13278 }
13279 ctxt->state = NULL;
13280 xmlFreeAutomata(ctxt->am);
13281 ctxt->am = NULL;
13282 }
13283
13284 /**
13285 * xmlSchemaResolveElementReferences:
13286 * @elem: the schema element context
13287 * @ctxt: the schema parser context
13288 *
13289 * Resolves the references of an element declaration
13290 * or particle, which has an element declaration as it's
13291 * term.
13292 */
13293 static void
xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)13294 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13295 xmlSchemaParserCtxtPtr ctxt)
13296 {
13297 if ((ctxt == NULL) || (elemDecl == NULL) ||
13298 ((elemDecl != NULL) &&
13299 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13300 return;
13301 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13302
13303 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13304 xmlSchemaTypePtr type;
13305
13306 /* (type definition) ... otherwise the type definition `resolved`
13307 * to by the `actual value` of the type [attribute] ...
13308 */
13309 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13310 elemDecl->namedTypeNs);
13311 if (type == NULL) {
13312 xmlSchemaPResCompAttrErr(ctxt,
13313 XML_SCHEMAP_SRC_RESOLVE,
13314 WXS_BASIC_CAST elemDecl, elemDecl->node,
13315 "type", elemDecl->namedType, elemDecl->namedTypeNs,
13316 XML_SCHEMA_TYPE_BASIC, "type definition");
13317 } else
13318 elemDecl->subtypes = type;
13319 }
13320 if (elemDecl->substGroup != NULL) {
13321 xmlSchemaElementPtr substHead;
13322
13323 /*
13324 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13325 * substitutionGroup?
13326 */
13327 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13328 elemDecl->substGroupNs);
13329 if (substHead == NULL) {
13330 xmlSchemaPResCompAttrErr(ctxt,
13331 XML_SCHEMAP_SRC_RESOLVE,
13332 WXS_BASIC_CAST elemDecl, NULL,
13333 "substitutionGroup", elemDecl->substGroup,
13334 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13335 } else {
13336 xmlSchemaResolveElementReferences(substHead, ctxt);
13337 /*
13338 * Set the "substitution group affiliation".
13339 * NOTE that now we use the "refDecl" field for this.
13340 */
13341 WXS_SUBST_HEAD(elemDecl) = substHead;
13342 /*
13343 * The type definitions is set to:
13344 * SPEC "...the {type definition} of the element
13345 * declaration `resolved` to by the `actual value`
13346 * of the substitutionGroup [attribute], if present"
13347 */
13348 if (elemDecl->subtypes == NULL) {
13349 if (substHead->subtypes == NULL) {
13350 /*
13351 * This can happen with self-referencing substitution
13352 * groups. The cycle will be detected later, but we have
13353 * to set subtypes to avoid null-pointer dereferences.
13354 */
13355 elemDecl->subtypes = xmlSchemaGetBuiltInType(
13356 XML_SCHEMAS_ANYTYPE);
13357 } else {
13358 elemDecl->subtypes = substHead->subtypes;
13359 }
13360 }
13361 }
13362 }
13363 /*
13364 * SPEC "The definition of anyType serves as the default type definition
13365 * for element declarations whose XML representation does not specify one."
13366 */
13367 if ((elemDecl->subtypes == NULL) &&
13368 (elemDecl->namedType == NULL) &&
13369 (elemDecl->substGroup == NULL))
13370 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13371 }
13372
13373 /**
13374 * xmlSchemaResolveUnionMemberTypes:
13375 * @ctxt: the schema parser context
13376 * @type: the schema simple type definition
13377 *
13378 * Checks and builds the "member type definitions" property of the union
13379 * simple type. This handles part (1), part (2) is done in
13380 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13381 *
13382 * Returns -1 in case of an internal error, 0 otherwise.
13383 */
13384 static int
xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)13385 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13386 xmlSchemaTypePtr type)
13387 {
13388
13389 xmlSchemaTypeLinkPtr link, lastLink, newLink;
13390 xmlSchemaTypePtr memberType;
13391
13392 /*
13393 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13394 * define the explicit members as the type definitions `resolved`
13395 * to by the items in the `actual value` of the memberTypes [attribute],
13396 * if any, followed by the type definitions corresponding to the
13397 * <simpleType>s among the [children] of <union>, if any."
13398 */
13399 /*
13400 * Resolve references.
13401 */
13402 link = type->memberTypes;
13403 lastLink = NULL;
13404 while (link != NULL) {
13405 const xmlChar *name, *nsName;
13406
13407 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13408 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13409
13410 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13411 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13412 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13413 WXS_BASIC_CAST type, type->node, "memberTypes",
13414 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13415 /*
13416 * Remove the member type link.
13417 */
13418 if (lastLink == NULL)
13419 type->memberTypes = link->next;
13420 else
13421 lastLink->next = link->next;
13422 newLink = link;
13423 link = link->next;
13424 xmlFree(newLink);
13425 } else {
13426 link->type = memberType;
13427 lastLink = link;
13428 link = link->next;
13429 }
13430 }
13431 /*
13432 * Add local simple types,
13433 */
13434 memberType = type->subtypes;
13435 while (memberType != NULL) {
13436 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13437 if (link == NULL) {
13438 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13439 return (-1);
13440 }
13441 link->type = memberType;
13442 link->next = NULL;
13443 if (lastLink == NULL)
13444 type->memberTypes = link;
13445 else
13446 lastLink->next = link;
13447 lastLink = link;
13448 memberType = memberType->next;
13449 }
13450 return (0);
13451 }
13452
13453 /**
13454 * xmlSchemaIsDerivedFromBuiltInType:
13455 * @ctxt: the schema parser context
13456 * @type: the type definition
13457 * @valType: the value type
13458 *
13459 *
13460 * Returns 1 if the type has the given value type, or
13461 * is derived from such a type.
13462 */
13463 static int
xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type,int valType)13464 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13465 {
13466 if (type == NULL)
13467 return (0);
13468 if (WXS_IS_COMPLEX(type))
13469 return (0);
13470 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13471 if (type->builtInType == valType)
13472 return(1);
13473 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13474 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13475 return (0);
13476 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13477 }
13478 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13479 }
13480
13481 #if 0
13482 /**
13483 * xmlSchemaIsDerivedFromBuiltInType:
13484 * @ctxt: the schema parser context
13485 * @type: the type definition
13486 * @valType: the value type
13487 *
13488 *
13489 * Returns 1 if the type has the given value type, or
13490 * is derived from such a type.
13491 */
13492 static int
13493 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13494 {
13495 if (type == NULL)
13496 return (0);
13497 if (WXS_IS_COMPLEX(type))
13498 return (0);
13499 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13500 if (type->builtInType == valType)
13501 return(1);
13502 return (0);
13503 } else
13504 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13505
13506 return (0);
13507 }
13508
13509 static xmlSchemaTypePtr
13510 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13511 {
13512 if (type == NULL)
13513 return (NULL);
13514 if (WXS_IS_COMPLEX(type))
13515 return (NULL);
13516 if (type->type == XML_SCHEMA_TYPE_BASIC)
13517 return(type);
13518 return(xmlSchemaQueryBuiltInType(type->subtypes));
13519 }
13520 #endif
13521
13522 /**
13523 * xmlSchemaGetPrimitiveType:
13524 * @type: the simpleType definition
13525 *
13526 * Returns the primitive type of the given type or
13527 * NULL in case of error.
13528 */
13529 static xmlSchemaTypePtr
xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)13530 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13531 {
13532
13533 while (type != NULL) {
13534 /*
13535 * Note that anySimpleType is actually not a primitive type
13536 * but we need that here.
13537 */
13538 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13539 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13540 return (type);
13541 type = type->baseType;
13542 }
13543
13544 return (NULL);
13545 }
13546
13547 #if 0
13548 /**
13549 * xmlSchemaGetBuiltInTypeAncestor:
13550 * @type: the simpleType definition
13551 *
13552 * Returns the primitive type of the given type or
13553 * NULL in case of error.
13554 */
13555 static xmlSchemaTypePtr
13556 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13557 {
13558 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13559 return (0);
13560 while (type != NULL) {
13561 if (type->type == XML_SCHEMA_TYPE_BASIC)
13562 return (type);
13563 type = type->baseType;
13564 }
13565
13566 return (NULL);
13567 }
13568 #endif
13569
13570 /**
13571 * xmlSchemaCloneWildcardNsConstraints:
13572 * @ctxt: the schema parser context
13573 * @dest: the destination wildcard
13574 * @source: the source wildcard
13575 *
13576 * Clones the namespace constraints of source
13577 * and assigns them to dest.
13578 * Returns -1 on internal error, 0 otherwise.
13579 */
13580 static int
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr dest,xmlSchemaWildcardPtr source)13581 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13582 xmlSchemaWildcardPtr dest,
13583 xmlSchemaWildcardPtr source)
13584 {
13585 xmlSchemaWildcardNsPtr cur, tmp, last;
13586
13587 if ((source == NULL) || (dest == NULL))
13588 return(-1);
13589 dest->any = source->any;
13590 cur = source->nsSet;
13591 last = NULL;
13592 while (cur != NULL) {
13593 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13594 if (tmp == NULL)
13595 return(-1);
13596 tmp->value = cur->value;
13597 if (last == NULL)
13598 dest->nsSet = tmp;
13599 else
13600 last->next = tmp;
13601 last = tmp;
13602 cur = cur->next;
13603 }
13604 if (dest->negNsSet != NULL)
13605 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13606 if (source->negNsSet != NULL) {
13607 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13608 if (dest->negNsSet == NULL)
13609 return(-1);
13610 dest->negNsSet->value = source->negNsSet->value;
13611 } else
13612 dest->negNsSet = NULL;
13613 return(0);
13614 }
13615
13616 /**
13617 * xmlSchemaUnionWildcards:
13618 * @ctxt: the schema parser context
13619 * @completeWild: the first wildcard
13620 * @curWild: the second wildcard
13621 *
13622 * Unions the namespace constraints of the given wildcards.
13623 * @completeWild will hold the resulting union.
13624 * Returns a positive error code on failure, -1 in case of an
13625 * internal error, 0 otherwise.
13626 */
13627 static int
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13628 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13629 xmlSchemaWildcardPtr completeWild,
13630 xmlSchemaWildcardPtr curWild)
13631 {
13632 xmlSchemaWildcardNsPtr cur, curB, tmp;
13633
13634 /*
13635 * 1 If O1 and O2 are the same value, then that value must be the
13636 * value.
13637 */
13638 if ((completeWild->any == curWild->any) &&
13639 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13640 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13641
13642 if ((completeWild->negNsSet == NULL) ||
13643 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13644
13645 if (completeWild->nsSet != NULL) {
13646 int found = 0;
13647
13648 /*
13649 * Check equality of sets.
13650 */
13651 cur = completeWild->nsSet;
13652 while (cur != NULL) {
13653 found = 0;
13654 curB = curWild->nsSet;
13655 while (curB != NULL) {
13656 if (cur->value == curB->value) {
13657 found = 1;
13658 break;
13659 }
13660 curB = curB->next;
13661 }
13662 if (!found)
13663 break;
13664 cur = cur->next;
13665 }
13666 if (found)
13667 return(0);
13668 } else
13669 return(0);
13670 }
13671 }
13672 /*
13673 * 2 If either O1 or O2 is any, then any must be the value
13674 */
13675 if (completeWild->any != curWild->any) {
13676 if (completeWild->any == 0) {
13677 completeWild->any = 1;
13678 if (completeWild->nsSet != NULL) {
13679 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13680 completeWild->nsSet = NULL;
13681 }
13682 if (completeWild->negNsSet != NULL) {
13683 xmlFree(completeWild->negNsSet);
13684 completeWild->negNsSet = NULL;
13685 }
13686 }
13687 return (0);
13688 }
13689 /*
13690 * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13691 * then the union of those sets must be the value.
13692 */
13693 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13694 int found;
13695 xmlSchemaWildcardNsPtr start;
13696
13697 cur = curWild->nsSet;
13698 start = completeWild->nsSet;
13699 while (cur != NULL) {
13700 found = 0;
13701 curB = start;
13702 while (curB != NULL) {
13703 if (cur->value == curB->value) {
13704 found = 1;
13705 break;
13706 }
13707 curB = curB->next;
13708 }
13709 if (!found) {
13710 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13711 if (tmp == NULL)
13712 return (-1);
13713 tmp->value = cur->value;
13714 tmp->next = completeWild->nsSet;
13715 completeWild->nsSet = tmp;
13716 }
13717 cur = cur->next;
13718 }
13719
13720 return(0);
13721 }
13722 /*
13723 * 4 If the two are negations of different values (namespace names
13724 * or `absent`), then a pair of not and `absent` must be the value.
13725 */
13726 if ((completeWild->negNsSet != NULL) &&
13727 (curWild->negNsSet != NULL) &&
13728 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13729 completeWild->negNsSet->value = NULL;
13730
13731 return(0);
13732 }
13733 /*
13734 * 5.
13735 */
13736 if (((completeWild->negNsSet != NULL) &&
13737 (completeWild->negNsSet->value != NULL) &&
13738 (curWild->nsSet != NULL)) ||
13739 ((curWild->negNsSet != NULL) &&
13740 (curWild->negNsSet->value != NULL) &&
13741 (completeWild->nsSet != NULL))) {
13742
13743 int nsFound, absentFound = 0;
13744
13745 if (completeWild->nsSet != NULL) {
13746 cur = completeWild->nsSet;
13747 curB = curWild->negNsSet;
13748 } else {
13749 cur = curWild->nsSet;
13750 curB = completeWild->negNsSet;
13751 }
13752 nsFound = 0;
13753 while (cur != NULL) {
13754 if (cur->value == NULL)
13755 absentFound = 1;
13756 else if (cur->value == curB->value)
13757 nsFound = 1;
13758 if (nsFound && absentFound)
13759 break;
13760 cur = cur->next;
13761 }
13762
13763 if (nsFound && absentFound) {
13764 /*
13765 * 5.1 If the set S includes both the negated namespace
13766 * name and `absent`, then any must be the value.
13767 */
13768 completeWild->any = 1;
13769 if (completeWild->nsSet != NULL) {
13770 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13771 completeWild->nsSet = NULL;
13772 }
13773 if (completeWild->negNsSet != NULL) {
13774 xmlFree(completeWild->negNsSet);
13775 completeWild->negNsSet = NULL;
13776 }
13777 } else if (nsFound && (!absentFound)) {
13778 /*
13779 * 5.2 If the set S includes the negated namespace name
13780 * but not `absent`, then a pair of not and `absent` must
13781 * be the value.
13782 */
13783 if (completeWild->nsSet != NULL) {
13784 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13785 completeWild->nsSet = NULL;
13786 }
13787 if (completeWild->negNsSet == NULL) {
13788 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13789 if (completeWild->negNsSet == NULL)
13790 return (-1);
13791 }
13792 completeWild->negNsSet->value = NULL;
13793 } else if ((!nsFound) && absentFound) {
13794 /*
13795 * 5.3 If the set S includes `absent` but not the negated
13796 * namespace name, then the union is not expressible.
13797 */
13798 xmlSchemaPErr(ctxt, completeWild->node,
13799 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13800 "The union of the wildcard is not expressible.\n",
13801 NULL, NULL);
13802 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13803 } else if ((!nsFound) && (!absentFound)) {
13804 /*
13805 * 5.4 If the set S does not include either the negated namespace
13806 * name or `absent`, then whichever of O1 or O2 is a pair of not
13807 * and a namespace name must be the value.
13808 */
13809 if (completeWild->negNsSet == NULL) {
13810 if (completeWild->nsSet != NULL) {
13811 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13812 completeWild->nsSet = NULL;
13813 }
13814 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13815 if (completeWild->negNsSet == NULL)
13816 return (-1);
13817 completeWild->negNsSet->value = curWild->negNsSet->value;
13818 }
13819 }
13820 return (0);
13821 }
13822 /*
13823 * 6.
13824 */
13825 if (((completeWild->negNsSet != NULL) &&
13826 (completeWild->negNsSet->value == NULL) &&
13827 (curWild->nsSet != NULL)) ||
13828 ((curWild->negNsSet != NULL) &&
13829 (curWild->negNsSet->value == NULL) &&
13830 (completeWild->nsSet != NULL))) {
13831
13832 if (completeWild->nsSet != NULL) {
13833 cur = completeWild->nsSet;
13834 } else {
13835 cur = curWild->nsSet;
13836 }
13837 while (cur != NULL) {
13838 if (cur->value == NULL) {
13839 /*
13840 * 6.1 If the set S includes `absent`, then any must be the
13841 * value.
13842 */
13843 completeWild->any = 1;
13844 if (completeWild->nsSet != NULL) {
13845 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13846 completeWild->nsSet = NULL;
13847 }
13848 if (completeWild->negNsSet != NULL) {
13849 xmlFree(completeWild->negNsSet);
13850 completeWild->negNsSet = NULL;
13851 }
13852 return (0);
13853 }
13854 cur = cur->next;
13855 }
13856 if (completeWild->negNsSet == NULL) {
13857 /*
13858 * 6.2 If the set S does not include `absent`, then a pair of not
13859 * and `absent` must be the value.
13860 */
13861 if (completeWild->nsSet != NULL) {
13862 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13863 completeWild->nsSet = NULL;
13864 }
13865 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13866 if (completeWild->negNsSet == NULL)
13867 return (-1);
13868 completeWild->negNsSet->value = NULL;
13869 }
13870 return (0);
13871 }
13872 return (0);
13873
13874 }
13875
13876 /**
13877 * xmlSchemaIntersectWildcards:
13878 * @ctxt: the schema parser context
13879 * @completeWild: the first wildcard
13880 * @curWild: the second wildcard
13881 *
13882 * Intersects the namespace constraints of the given wildcards.
13883 * @completeWild will hold the resulting intersection.
13884 * Returns a positive error code on failure, -1 in case of an
13885 * internal error, 0 otherwise.
13886 */
13887 static int
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13888 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13889 xmlSchemaWildcardPtr completeWild,
13890 xmlSchemaWildcardPtr curWild)
13891 {
13892 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
13893
13894 /*
13895 * 1 If O1 and O2 are the same value, then that value must be the
13896 * value.
13897 */
13898 if ((completeWild->any == curWild->any) &&
13899 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13900 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13901
13902 if ((completeWild->negNsSet == NULL) ||
13903 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13904
13905 if (completeWild->nsSet != NULL) {
13906 int found = 0;
13907
13908 /*
13909 * Check equality of sets.
13910 */
13911 cur = completeWild->nsSet;
13912 while (cur != NULL) {
13913 found = 0;
13914 curB = curWild->nsSet;
13915 while (curB != NULL) {
13916 if (cur->value == curB->value) {
13917 found = 1;
13918 break;
13919 }
13920 curB = curB->next;
13921 }
13922 if (!found)
13923 break;
13924 cur = cur->next;
13925 }
13926 if (found)
13927 return(0);
13928 } else
13929 return(0);
13930 }
13931 }
13932 /*
13933 * 2 If either O1 or O2 is any, then the other must be the value.
13934 */
13935 if ((completeWild->any != curWild->any) && (completeWild->any)) {
13936 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13937 return(-1);
13938 return(0);
13939 }
13940 /*
13941 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13942 * name or `absent`) and the other is a set of (namespace names or
13943 * `absent`), then that set, minus the negated value if it was in
13944 * the set, minus `absent` if it was in the set, must be the value.
13945 */
13946 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13947 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13948 const xmlChar *neg;
13949
13950 if (completeWild->nsSet == NULL) {
13951 neg = completeWild->negNsSet->value;
13952 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13953 return(-1);
13954 } else
13955 neg = curWild->negNsSet->value;
13956 /*
13957 * Remove absent and negated.
13958 */
13959 prev = NULL;
13960 cur = completeWild->nsSet;
13961 while (cur != NULL) {
13962 if (cur->value == NULL) {
13963 if (prev == NULL)
13964 completeWild->nsSet = cur->next;
13965 else
13966 prev->next = cur->next;
13967 xmlFree(cur);
13968 break;
13969 }
13970 prev = cur;
13971 cur = cur->next;
13972 }
13973 if (neg != NULL) {
13974 prev = NULL;
13975 cur = completeWild->nsSet;
13976 while (cur != NULL) {
13977 if (cur->value == neg) {
13978 if (prev == NULL)
13979 completeWild->nsSet = cur->next;
13980 else
13981 prev->next = cur->next;
13982 xmlFree(cur);
13983 break;
13984 }
13985 prev = cur;
13986 cur = cur->next;
13987 }
13988 }
13989
13990 return(0);
13991 }
13992 /*
13993 * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13994 * then the intersection of those sets must be the value.
13995 */
13996 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13997 int found;
13998
13999 cur = completeWild->nsSet;
14000 prev = NULL;
14001 while (cur != NULL) {
14002 found = 0;
14003 curB = curWild->nsSet;
14004 while (curB != NULL) {
14005 if (cur->value == curB->value) {
14006 found = 1;
14007 break;
14008 }
14009 curB = curB->next;
14010 }
14011 if (!found) {
14012 if (prev == NULL)
14013 completeWild->nsSet = cur->next;
14014 else
14015 prev->next = cur->next;
14016 tmp = cur->next;
14017 xmlFree(cur);
14018 cur = tmp;
14019 continue;
14020 }
14021 prev = cur;
14022 cur = cur->next;
14023 }
14024
14025 return(0);
14026 }
14027 /* 5 If the two are negations of different namespace names,
14028 * then the intersection is not expressible
14029 */
14030 if ((completeWild->negNsSet != NULL) &&
14031 (curWild->negNsSet != NULL) &&
14032 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
14033 (completeWild->negNsSet->value != NULL) &&
14034 (curWild->negNsSet->value != NULL)) {
14035
14036 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
14037 "The intersection of the wildcard is not expressible.\n",
14038 NULL, NULL);
14039 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
14040 }
14041 /*
14042 * 6 If the one is a negation of a namespace name and the other
14043 * is a negation of `absent`, then the one which is the negation
14044 * of a namespace name must be the value.
14045 */
14046 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
14047 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
14048 (completeWild->negNsSet->value == NULL)) {
14049 completeWild->negNsSet->value = curWild->negNsSet->value;
14050 }
14051 return(0);
14052 }
14053
14054 /**
14055 * xmlSchemaIsWildcardNsConstraintSubset:
14056 * @ctxt: the schema parser context
14057 * @sub: the first wildcard
14058 * @super: the second wildcard
14059 *
14060 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
14061 *
14062 * Returns 0 if the namespace constraint of @sub is an intensional
14063 * subset of @super, 1 otherwise.
14064 */
14065 static int
xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,xmlSchemaWildcardPtr super)14066 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
14067 xmlSchemaWildcardPtr super)
14068 {
14069 /*
14070 * 1 super must be any.
14071 */
14072 if (super->any)
14073 return (0);
14074 /*
14075 * 2.1 sub must be a pair of not and a namespace name or `absent`.
14076 * 2.2 super must be a pair of not and the same value.
14077 */
14078 if ((sub->negNsSet != NULL) &&
14079 (super->negNsSet != NULL) &&
14080 (sub->negNsSet->value == super->negNsSet->value))
14081 return (0);
14082 /*
14083 * 3.1 sub must be a set whose members are either namespace names or `absent`.
14084 */
14085 if (sub->nsSet != NULL) {
14086 /*
14087 * 3.2.1 super must be the same set or a superset thereof.
14088 */
14089 if (super->nsSet != NULL) {
14090 xmlSchemaWildcardNsPtr cur, curB;
14091 int found = 0;
14092
14093 cur = sub->nsSet;
14094 while (cur != NULL) {
14095 found = 0;
14096 curB = super->nsSet;
14097 while (curB != NULL) {
14098 if (cur->value == curB->value) {
14099 found = 1;
14100 break;
14101 }
14102 curB = curB->next;
14103 }
14104 if (!found)
14105 return (1);
14106 cur = cur->next;
14107 }
14108 if (found)
14109 return (0);
14110 } else if (super->negNsSet != NULL) {
14111 xmlSchemaWildcardNsPtr cur;
14112 /*
14113 * 3.2.2 super must be a pair of not and a namespace name or
14114 * `absent` and that value must not be in sub's set.
14115 */
14116 cur = sub->nsSet;
14117 while (cur != NULL) {
14118 if (cur->value == super->negNsSet->value)
14119 return (1);
14120 cur = cur->next;
14121 }
14122 return (0);
14123 }
14124 }
14125 return (1);
14126 }
14127
14128 static int
xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,int * fixed,const xmlChar ** value,xmlSchemaValPtr * val)14129 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14130 int *fixed,
14131 const xmlChar **value,
14132 xmlSchemaValPtr *val)
14133 {
14134 *fixed = 0;
14135 *value = NULL;
14136 if (val != 0)
14137 *val = NULL;
14138
14139 if (attruse->defValue != NULL) {
14140 *value = attruse->defValue;
14141 if (val != NULL)
14142 *val = attruse->defVal;
14143 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14144 *fixed = 1;
14145 return(1);
14146 } else if ((attruse->attrDecl != NULL) &&
14147 (attruse->attrDecl->defValue != NULL)) {
14148 *value = attruse->attrDecl->defValue;
14149 if (val != NULL)
14150 *val = attruse->attrDecl->defVal;
14151 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14152 *fixed = 1;
14153 return(1);
14154 }
14155 return(0);
14156 }
14157 /**
14158 * xmlSchemaCheckCVCWildcardNamespace:
14159 * @wild: the wildcard
14160 * @ns: the namespace
14161 *
14162 * Validation Rule: Wildcard allows Namespace Name
14163 * (cvc-wildcard-namespace)
14164 *
14165 * Returns 0 if the given namespace matches the wildcard,
14166 * 1 otherwise and -1 on API errors.
14167 */
14168 static int
xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,const xmlChar * ns)14169 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14170 const xmlChar* ns)
14171 {
14172 if (wild == NULL)
14173 return(-1);
14174
14175 if (wild->any)
14176 return(0);
14177 else if (wild->nsSet != NULL) {
14178 xmlSchemaWildcardNsPtr cur;
14179
14180 cur = wild->nsSet;
14181 while (cur != NULL) {
14182 if (xmlStrEqual(cur->value, ns))
14183 return(0);
14184 cur = cur->next;
14185 }
14186 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14187 (!xmlStrEqual(wild->negNsSet->value, ns)))
14188 return(0);
14189
14190 return(1);
14191 }
14192
14193 #define XML_SCHEMA_ACTION_DERIVE 0
14194 #define XML_SCHEMA_ACTION_REDEFINE 1
14195
14196 #define WXS_ACTION_STR(a) \
14197 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14198
14199 /*
14200 * Schema Component Constraint:
14201 * Derivation Valid (Restriction, Complex)
14202 * derivation-ok-restriction (2) - (4)
14203 *
14204 * ATTENTION:
14205 * In XML Schema 1.1 this will be:
14206 * Validation Rule:
14207 * Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14208 *
14209 */
14210 static int
xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,int action,xmlSchemaBasicItemPtr item,xmlSchemaBasicItemPtr baseItem,xmlSchemaItemListPtr uses,xmlSchemaItemListPtr baseUses,xmlSchemaWildcardPtr wild,xmlSchemaWildcardPtr baseWild)14211 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14212 int action,
14213 xmlSchemaBasicItemPtr item,
14214 xmlSchemaBasicItemPtr baseItem,
14215 xmlSchemaItemListPtr uses,
14216 xmlSchemaItemListPtr baseUses,
14217 xmlSchemaWildcardPtr wild,
14218 xmlSchemaWildcardPtr baseWild)
14219 {
14220 xmlSchemaAttributeUsePtr cur = NULL, bcur;
14221 int i, j, found; /* err = 0; */
14222 const xmlChar *bEffValue;
14223 int effFixed;
14224
14225 if (uses != NULL) {
14226 for (i = 0; i < uses->nbItems; i++) {
14227 cur = uses->items[i];
14228 found = 0;
14229 if (baseUses == NULL)
14230 goto not_found;
14231 for (j = 0; j < baseUses->nbItems; j++) {
14232 bcur = baseUses->items[j];
14233 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14234 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14235 (WXS_ATTRUSE_DECL_TNS(cur) ==
14236 WXS_ATTRUSE_DECL_TNS(bcur)))
14237 {
14238 /*
14239 * (2.1) "If there is an attribute use in the {attribute
14240 * uses} of the {base type definition} (call this B) whose
14241 * {attribute declaration} has the same {name} and {target
14242 * namespace}, then all of the following must be true:"
14243 */
14244 found = 1;
14245
14246 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14247 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14248 {
14249 xmlChar *str = NULL;
14250 /*
14251 * (2.1.1) "one of the following must be true:"
14252 * (2.1.1.1) "B's {required} is false."
14253 * (2.1.1.2) "R's {required} is true."
14254 */
14255 xmlSchemaPAttrUseErr4(pctxt,
14256 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14257 WXS_ITEM_NODE(item), item, cur,
14258 "The 'optional' attribute use is inconsistent "
14259 "with the corresponding 'required' attribute use of "
14260 "the %s %s",
14261 WXS_ACTION_STR(action),
14262 xmlSchemaGetComponentDesignation(&str, baseItem),
14263 NULL, NULL);
14264 FREE_AND_NULL(str);
14265 /* err = pctxt->err; */
14266 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14267 WXS_ATTRUSE_TYPEDEF(cur),
14268 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14269 {
14270 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14271
14272 /*
14273 * SPEC (2.1.2) "R's {attribute declaration}'s
14274 * {type definition} must be validly derived from
14275 * B's {type definition} given the empty set as
14276 * defined in Type Derivation OK (Simple) ($3.14.6)."
14277 */
14278 xmlSchemaPAttrUseErr4(pctxt,
14279 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14280 WXS_ITEM_NODE(item), item, cur,
14281 "The attribute declaration's %s "
14282 "is not validly derived from "
14283 "the corresponding %s of the "
14284 "attribute declaration in the %s %s",
14285 xmlSchemaGetComponentDesignation(&strA,
14286 WXS_ATTRUSE_TYPEDEF(cur)),
14287 xmlSchemaGetComponentDesignation(&strB,
14288 WXS_ATTRUSE_TYPEDEF(bcur)),
14289 WXS_ACTION_STR(action),
14290 xmlSchemaGetComponentDesignation(&strC, baseItem));
14291 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14292 FREE_AND_NULL(strA);
14293 FREE_AND_NULL(strB);
14294 FREE_AND_NULL(strC);
14295 /* err = pctxt->err; */
14296 } else {
14297 /*
14298 * 2.1.3 [Definition:] Let the effective value
14299 * constraint of an attribute use be its {value
14300 * constraint}, if present, otherwise its {attribute
14301 * declaration}'s {value constraint} .
14302 */
14303 xmlSchemaGetEffectiveValueConstraint(bcur,
14304 &effFixed, &bEffValue, NULL);
14305 /*
14306 * 2.1.3 ... one of the following must be true
14307 *
14308 * 2.1.3.1 B's `effective value constraint` is
14309 * `absent` or default.
14310 */
14311 if ((bEffValue != NULL) &&
14312 (effFixed == 1)) {
14313 const xmlChar *rEffValue = NULL;
14314
14315 xmlSchemaGetEffectiveValueConstraint(bcur,
14316 &effFixed, &rEffValue, NULL);
14317 /*
14318 * 2.1.3.2 R's `effective value constraint` is
14319 * fixed with the same string as B's.
14320 * MAYBE TODO: Compare the computed values.
14321 * Hmm, it says "same string" so
14322 * string-equality might really be sufficient.
14323 */
14324 if ((effFixed == 0) ||
14325 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14326 {
14327 xmlChar *str = NULL;
14328
14329 xmlSchemaPAttrUseErr4(pctxt,
14330 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14331 WXS_ITEM_NODE(item), item, cur,
14332 "The effective value constraint of the "
14333 "attribute use is inconsistent with "
14334 "its correspondent in the %s %s",
14335 WXS_ACTION_STR(action),
14336 xmlSchemaGetComponentDesignation(&str,
14337 baseItem),
14338 NULL, NULL);
14339 FREE_AND_NULL(str);
14340 /* err = pctxt->err; */
14341 }
14342 }
14343 }
14344 break;
14345 }
14346 }
14347 not_found:
14348 if (!found) {
14349 /*
14350 * (2.2) "otherwise the {base type definition} must have an
14351 * {attribute wildcard} and the {target namespace} of the
14352 * R's {attribute declaration} must be `valid` with respect
14353 * to that wildcard, as defined in Wildcard allows Namespace
14354 * Name ($3.10.4)."
14355 */
14356 if ((baseWild == NULL) ||
14357 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14358 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14359 {
14360 xmlChar *str = NULL;
14361
14362 xmlSchemaPAttrUseErr4(pctxt,
14363 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14364 WXS_ITEM_NODE(item), item, cur,
14365 "Neither a matching attribute use, "
14366 "nor a matching wildcard exists in the %s %s",
14367 WXS_ACTION_STR(action),
14368 xmlSchemaGetComponentDesignation(&str, baseItem),
14369 NULL, NULL);
14370 FREE_AND_NULL(str);
14371 /* err = pctxt->err; */
14372 }
14373 }
14374 }
14375 }
14376 /*
14377 * SPEC derivation-ok-restriction (3):
14378 * (3) "For each attribute use in the {attribute uses} of the {base type
14379 * definition} whose {required} is true, there must be an attribute
14380 * use with an {attribute declaration} with the same {name} and
14381 * {target namespace} as its {attribute declaration} in the {attribute
14382 * uses} of the complex type definition itself whose {required} is true.
14383 */
14384 if (baseUses != NULL) {
14385 for (j = 0; j < baseUses->nbItems; j++) {
14386 bcur = baseUses->items[j];
14387 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14388 continue;
14389 found = 0;
14390 if (uses != NULL) {
14391 for (i = 0; i < uses->nbItems; i++) {
14392 cur = uses->items[i];
14393 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14394 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14395 (WXS_ATTRUSE_DECL_TNS(cur) ==
14396 WXS_ATTRUSE_DECL_TNS(bcur))) {
14397 found = 1;
14398 break;
14399 }
14400 }
14401 }
14402 if (!found) {
14403 xmlChar *strA = NULL, *strB = NULL;
14404
14405 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14406 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14407 NULL, item,
14408 "A matching attribute use for the "
14409 "'required' %s of the %s %s is missing",
14410 xmlSchemaGetComponentDesignation(&strA, bcur),
14411 WXS_ACTION_STR(action),
14412 xmlSchemaGetComponentDesignation(&strB, baseItem),
14413 NULL);
14414 FREE_AND_NULL(strA);
14415 FREE_AND_NULL(strB);
14416 }
14417 }
14418 }
14419 /*
14420 * derivation-ok-restriction (4)
14421 */
14422 if (wild != NULL) {
14423 /*
14424 * (4) "If there is an {attribute wildcard}, all of the
14425 * following must be true:"
14426 */
14427 if (baseWild == NULL) {
14428 xmlChar *str = NULL;
14429
14430 /*
14431 * (4.1) "The {base type definition} must also have one."
14432 */
14433 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14434 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14435 NULL, item,
14436 "The %s has an attribute wildcard, "
14437 "but the %s %s '%s' does not have one",
14438 WXS_ITEM_TYPE_NAME(item),
14439 WXS_ACTION_STR(action),
14440 WXS_ITEM_TYPE_NAME(baseItem),
14441 xmlSchemaGetComponentQName(&str, baseItem));
14442 FREE_AND_NULL(str);
14443 return(pctxt->err);
14444 } else if ((baseWild->any == 0) &&
14445 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14446 {
14447 xmlChar *str = NULL;
14448 /*
14449 * (4.2) "The complex type definition's {attribute wildcard}'s
14450 * {namespace constraint} must be a subset of the {base type
14451 * definition}'s {attribute wildcard}'s {namespace constraint},
14452 * as defined by Wildcard Subset ($3.10.6)."
14453 */
14454 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14455 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14456 NULL, item,
14457 "The attribute wildcard is not a valid "
14458 "subset of the wildcard in the %s %s '%s'",
14459 WXS_ACTION_STR(action),
14460 WXS_ITEM_TYPE_NAME(baseItem),
14461 xmlSchemaGetComponentQName(&str, baseItem),
14462 NULL);
14463 FREE_AND_NULL(str);
14464 return(pctxt->err);
14465 }
14466 /* 4.3 Unless the {base type definition} is the `ur-type
14467 * definition`, the complex type definition's {attribute
14468 * wildcard}'s {process contents} must be identical to or
14469 * stronger than the {base type definition}'s {attribute
14470 * wildcard}'s {process contents}, where strict is stronger
14471 * than lax is stronger than skip.
14472 */
14473 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14474 (wild->processContents < baseWild->processContents)) {
14475 xmlChar *str = NULL;
14476 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14477 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14478 NULL, baseItem,
14479 "The {process contents} of the attribute wildcard is "
14480 "weaker than the one in the %s %s '%s'",
14481 WXS_ACTION_STR(action),
14482 WXS_ITEM_TYPE_NAME(baseItem),
14483 xmlSchemaGetComponentQName(&str, baseItem),
14484 NULL);
14485 FREE_AND_NULL(str)
14486 return(pctxt->err);
14487 }
14488 }
14489 return(0);
14490 }
14491
14492
14493 static int
14494 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14495 xmlSchemaBasicItemPtr item,
14496 xmlSchemaWildcardPtr *completeWild,
14497 xmlSchemaItemListPtr list,
14498 xmlSchemaItemListPtr prohibs);
14499 /**
14500 * xmlSchemaFixupTypeAttributeUses:
14501 * @ctxt: the schema parser context
14502 * @type: the complex type definition
14503 *
14504 *
14505 * Builds the wildcard and the attribute uses on the given complex type.
14506 * Returns -1 if an internal error occurs, 0 otherwise.
14507 *
14508 * ATTENTION TODO: Experimentally this uses pointer comparisons for
14509 * strings, so recheck this if we start to hardcode some schemata, since
14510 * they might not be in the same dict.
14511 * NOTE: It is allowed to "extend" the xs:anyType type.
14512 */
14513 static int
xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14514 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14515 xmlSchemaTypePtr type)
14516 {
14517 xmlSchemaTypePtr baseType = NULL;
14518 xmlSchemaAttributeUsePtr use;
14519 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14520
14521 if (type->baseType == NULL) {
14522 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14523 "no base type");
14524 return (-1);
14525 }
14526 baseType = type->baseType;
14527 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14528 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14529 return(-1);
14530
14531 uses = type->attrUses;
14532 baseUses = baseType->attrUses;
14533 /*
14534 * Expand attribute group references. And build the 'complete'
14535 * wildcard, i.e. intersect multiple wildcards.
14536 * Move attribute prohibitions into a separate list.
14537 */
14538 if (uses != NULL) {
14539 if (WXS_IS_RESTRICTION(type)) {
14540 /*
14541 * This one will transfer all attr. prohibitions
14542 * into pctxt->attrProhibs.
14543 */
14544 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14545 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14546 pctxt->attrProhibs) == -1)
14547 {
14548 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14549 "failed to expand attributes");
14550 }
14551 if (pctxt->attrProhibs->nbItems != 0)
14552 prohibs = pctxt->attrProhibs;
14553 } else {
14554 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14555 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14556 NULL) == -1)
14557 {
14558 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14559 "failed to expand attributes");
14560 }
14561 }
14562 }
14563 /*
14564 * Inherit the attribute uses of the base type.
14565 */
14566 if (baseUses != NULL) {
14567 int i, j;
14568 xmlSchemaAttributeUseProhibPtr pro;
14569
14570 if (WXS_IS_RESTRICTION(type)) {
14571 int usesCount;
14572 xmlSchemaAttributeUsePtr tmp;
14573
14574 if (uses != NULL)
14575 usesCount = uses->nbItems;
14576 else
14577 usesCount = 0;
14578
14579 /* Restriction. */
14580 for (i = 0; i < baseUses->nbItems; i++) {
14581 use = baseUses->items[i];
14582 if (prohibs) {
14583 /*
14584 * Filter out prohibited uses.
14585 */
14586 for (j = 0; j < prohibs->nbItems; j++) {
14587 pro = prohibs->items[j];
14588 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14589 (WXS_ATTRUSE_DECL_TNS(use) ==
14590 pro->targetNamespace))
14591 {
14592 goto inherit_next;
14593 }
14594 }
14595 }
14596 if (usesCount) {
14597 /*
14598 * Filter out existing uses.
14599 */
14600 for (j = 0; j < usesCount; j++) {
14601 tmp = uses->items[j];
14602 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14603 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14604 (WXS_ATTRUSE_DECL_TNS(use) ==
14605 WXS_ATTRUSE_DECL_TNS(tmp)))
14606 {
14607 goto inherit_next;
14608 }
14609 }
14610 }
14611 if (uses == NULL) {
14612 type->attrUses = xmlSchemaItemListCreate();
14613 if (type->attrUses == NULL)
14614 goto exit_failure;
14615 uses = type->attrUses;
14616 }
14617 xmlSchemaItemListAddSize(uses, 2, use);
14618 inherit_next: {}
14619 }
14620 } else {
14621 /* Extension. */
14622 for (i = 0; i < baseUses->nbItems; i++) {
14623 use = baseUses->items[i];
14624 if (uses == NULL) {
14625 type->attrUses = xmlSchemaItemListCreate();
14626 if (type->attrUses == NULL)
14627 goto exit_failure;
14628 uses = type->attrUses;
14629 }
14630 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14631 }
14632 }
14633 }
14634 /*
14635 * Shrink attr. uses.
14636 */
14637 if (uses) {
14638 if (uses->nbItems == 0) {
14639 xmlSchemaItemListFree(uses);
14640 type->attrUses = NULL;
14641 }
14642 /*
14643 * TODO: We could shrink the size of the array
14644 * to fit the actual number of items.
14645 */
14646 }
14647 /*
14648 * Compute the complete wildcard.
14649 */
14650 if (WXS_IS_EXTENSION(type)) {
14651 if (baseType->attributeWildcard != NULL) {
14652 /*
14653 * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14654 * the appropriate case among the following:"
14655 */
14656 if (type->attributeWildcard != NULL) {
14657 /*
14658 * Union the complete wildcard with the base wildcard.
14659 * SPEC {attribute wildcard}
14660 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14661 * and {annotation} are those of the `complete wildcard`,
14662 * and whose {namespace constraint} is the intensional union
14663 * of the {namespace constraint} of the `complete wildcard`
14664 * and of the `base wildcard`, as defined in Attribute
14665 * Wildcard Union ($3.10.6)."
14666 */
14667 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14668 baseType->attributeWildcard) == -1)
14669 goto exit_failure;
14670 } else {
14671 /*
14672 * (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14673 * then the `base wildcard`."
14674 */
14675 type->attributeWildcard = baseType->attributeWildcard;
14676 }
14677 } else {
14678 /*
14679 * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14680 * `complete wildcard`"
14681 * NOOP
14682 */
14683 }
14684 } else {
14685 /*
14686 * SPEC {attribute wildcard}
14687 * (3.1) "If the <restriction> alternative is chosen, then the
14688 * `complete wildcard`;"
14689 * NOOP
14690 */
14691 }
14692
14693 return (0);
14694
14695 exit_failure:
14696 return(-1);
14697 }
14698
14699 /**
14700 * xmlSchemaTypeFinalContains:
14701 * @schema: the schema
14702 * @type: the type definition
14703 * @final: the final
14704 *
14705 * Evaluates if a type definition contains the given "final".
14706 * This does take "finalDefault" into account as well.
14707 *
14708 * Returns 1 if the type does contain the given "final",
14709 * 0 otherwise.
14710 */
14711 static int
xmlSchemaTypeFinalContains(xmlSchemaTypePtr type,int final)14712 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14713 {
14714 if (type == NULL)
14715 return (0);
14716 if (type->flags & final)
14717 return (1);
14718 else
14719 return (0);
14720 }
14721
14722 /**
14723 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14724 * @type: the Union Simple Type
14725 *
14726 * Returns a list of member types of @type if existing,
14727 * returns NULL otherwise.
14728 */
14729 static xmlSchemaTypeLinkPtr
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)14730 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14731 {
14732 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14733 if (type->memberTypes != NULL)
14734 return (type->memberTypes);
14735 else
14736 type = type->baseType;
14737 }
14738 return (NULL);
14739 }
14740
14741 #if 0
14742 /**
14743 * xmlSchemaGetParticleTotalRangeMin:
14744 * @particle: the particle
14745 *
14746 * Schema Component Constraint: Effective Total Range
14747 * (all and sequence) + (choice)
14748 *
14749 * Returns the minimum Effective Total Range.
14750 */
14751 static int
14752 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14753 {
14754 if ((particle->children == NULL) ||
14755 (particle->minOccurs == 0))
14756 return (0);
14757 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14758 int min = -1, cur;
14759 xmlSchemaParticlePtr part =
14760 (xmlSchemaParticlePtr) particle->children->children;
14761
14762 if (part == NULL)
14763 return (0);
14764 while (part != NULL) {
14765 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14766 (part->children->type == XML_SCHEMA_TYPE_ANY))
14767 cur = part->minOccurs;
14768 else
14769 cur = xmlSchemaGetParticleTotalRangeMin(part);
14770 if (cur == 0)
14771 return (0);
14772 if ((min > cur) || (min == -1))
14773 min = cur;
14774 part = (xmlSchemaParticlePtr) part->next;
14775 }
14776 return (particle->minOccurs * min);
14777 } else {
14778 /* <all> and <sequence> */
14779 int sum = 0;
14780 xmlSchemaParticlePtr part =
14781 (xmlSchemaParticlePtr) particle->children->children;
14782
14783 if (part == NULL)
14784 return (0);
14785 do {
14786 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14787 (part->children->type == XML_SCHEMA_TYPE_ANY))
14788 sum += part->minOccurs;
14789 else
14790 sum += xmlSchemaGetParticleTotalRangeMin(part);
14791 part = (xmlSchemaParticlePtr) part->next;
14792 } while (part != NULL);
14793 return (particle->minOccurs * sum);
14794 }
14795 }
14796
14797 /**
14798 * xmlSchemaGetParticleTotalRangeMax:
14799 * @particle: the particle
14800 *
14801 * Schema Component Constraint: Effective Total Range
14802 * (all and sequence) + (choice)
14803 *
14804 * Returns the maximum Effective Total Range.
14805 */
14806 static int
14807 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14808 {
14809 if ((particle->children == NULL) ||
14810 (particle->children->children == NULL))
14811 return (0);
14812 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14813 int max = -1, cur;
14814 xmlSchemaParticlePtr part =
14815 (xmlSchemaParticlePtr) particle->children->children;
14816
14817 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14818 if (part->children == NULL)
14819 continue;
14820 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14821 (part->children->type == XML_SCHEMA_TYPE_ANY))
14822 cur = part->maxOccurs;
14823 else
14824 cur = xmlSchemaGetParticleTotalRangeMax(part);
14825 if (cur == UNBOUNDED)
14826 return (UNBOUNDED);
14827 if ((max < cur) || (max == -1))
14828 max = cur;
14829 }
14830 /* TODO: Handle overflows? */
14831 return (particle->maxOccurs * max);
14832 } else {
14833 /* <all> and <sequence> */
14834 int sum = 0, cur;
14835 xmlSchemaParticlePtr part =
14836 (xmlSchemaParticlePtr) particle->children->children;
14837
14838 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14839 if (part->children == NULL)
14840 continue;
14841 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14842 (part->children->type == XML_SCHEMA_TYPE_ANY))
14843 cur = part->maxOccurs;
14844 else
14845 cur = xmlSchemaGetParticleTotalRangeMax(part);
14846 if (cur == UNBOUNDED)
14847 return (UNBOUNDED);
14848 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14849 return (UNBOUNDED);
14850 sum += cur;
14851 }
14852 /* TODO: Handle overflows? */
14853 return (particle->maxOccurs * sum);
14854 }
14855 }
14856 #endif
14857
14858 /**
14859 * xmlSchemaGetParticleEmptiable:
14860 * @particle: the particle
14861 *
14862 * Returns 1 if emptiable, 0 otherwise.
14863 */
14864 static int
xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)14865 xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
14866 {
14867 xmlSchemaParticlePtr part;
14868 int emptiable;
14869
14870 if ((particle->children == NULL) || (particle->minOccurs == 0))
14871 return (1);
14872
14873 part = (xmlSchemaParticlePtr) particle->children->children;
14874 if (part == NULL)
14875 return (1);
14876
14877 while (part != NULL) {
14878 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14879 (part->children->type == XML_SCHEMA_TYPE_ANY))
14880 emptiable = (part->minOccurs == 0);
14881 else
14882 emptiable = xmlSchemaGetParticleEmptiable(part);
14883 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14884 if (emptiable)
14885 return (1);
14886 } else {
14887 /* <all> and <sequence> */
14888 if (!emptiable)
14889 return (0);
14890 }
14891 part = (xmlSchemaParticlePtr) part->next;
14892 }
14893
14894 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
14895 return (0);
14896 else
14897 return (1);
14898 }
14899
14900 /**
14901 * xmlSchemaIsParticleEmptiable:
14902 * @particle: the particle
14903 *
14904 * Schema Component Constraint: Particle Emptiable
14905 * Checks whether the given particle is emptiable.
14906 *
14907 * Returns 1 if emptiable, 0 otherwise.
14908 */
14909 static int
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)14910 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14911 {
14912 /*
14913 * SPEC (1) "Its {min occurs} is 0."
14914 */
14915 if ((particle == NULL) || (particle->minOccurs == 0) ||
14916 (particle->children == NULL))
14917 return (1);
14918 /*
14919 * SPEC (2) "Its {term} is a group and the minimum part of the
14920 * effective total range of that group, [...] is 0."
14921 */
14922 if (WXS_IS_MODEL_GROUP(particle->children))
14923 return (xmlSchemaGetParticleEmptiable(particle));
14924 return (0);
14925 }
14926
14927 /**
14928 * xmlSchemaCheckCOSSTDerivedOK:
14929 * @actxt: a context
14930 * @type: the derived simple type definition
14931 * @baseType: the base type definition
14932 * @subset: the subset of ('restriction', etc.)
14933 *
14934 * Schema Component Constraint:
14935 * Type Derivation OK (Simple) (cos-st-derived-OK)
14936 *
14937 * Checks whether @type can be validly
14938 * derived from @baseType.
14939 *
14940 * Returns 0 on success, an positive error code otherwise.
14941 */
14942 static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int subset)14943 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14944 xmlSchemaTypePtr type,
14945 xmlSchemaTypePtr baseType,
14946 int subset)
14947 {
14948 /*
14949 * 1 They are the same type definition.
14950 * TODO: The identity check might have to be more complex than this.
14951 */
14952 if (type == baseType)
14953 return (0);
14954 /*
14955 * 2.1 restriction is not in the subset, or in the {final}
14956 * of its own {base type definition};
14957 *
14958 * NOTE that this will be used also via "xsi:type".
14959 *
14960 * TODO: Revise this, it looks strange. How can the "type"
14961 * not be fixed or *in* fixing?
14962 */
14963 if (WXS_IS_TYPE_NOT_FIXED(type))
14964 if (xmlSchemaTypeFixup(type, actxt) == -1)
14965 return(-1);
14966 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14967 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14968 return(-1);
14969 if ((subset & SUBSET_RESTRICTION) ||
14970 (xmlSchemaTypeFinalContains(type->baseType,
14971 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14972 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14973 }
14974 /* 2.2 */
14975 if (type->baseType == baseType) {
14976 /*
14977 * 2.2.1 D's `base type definition` is B.
14978 */
14979 return (0);
14980 }
14981 /*
14982 * 2.2.2 D's `base type definition` is not the `ur-type definition`
14983 * and is validly derived from B given the subset, as defined by this
14984 * constraint.
14985 */
14986 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14987 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14988 baseType, subset) == 0)) {
14989 return (0);
14990 }
14991 /*
14992 * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14993 * definition`.
14994 */
14995 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14996 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14997 return (0);
14998 }
14999 /*
15000 * 2.2.4 B's {variety} is union and D is validly derived from a type
15001 * definition in B's {member type definitions} given the subset, as
15002 * defined by this constraint.
15003 *
15004 * NOTE: This seems not to involve built-in types, since there is no
15005 * built-in Union Simple Type.
15006 */
15007 if (WXS_IS_UNION(baseType)) {
15008 xmlSchemaTypeLinkPtr cur;
15009
15010 cur = baseType->memberTypes;
15011 while (cur != NULL) {
15012 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
15013 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
15014 return(-1);
15015 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
15016 type, cur->type, subset) == 0)
15017 {
15018 /*
15019 * It just has to be validly derived from at least one
15020 * member-type.
15021 */
15022 return (0);
15023 }
15024 cur = cur->next;
15025 }
15026 }
15027 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
15028 }
15029
15030 /**
15031 * xmlSchemaCheckTypeDefCircularInternal:
15032 * @pctxt: the schema parser context
15033 * @ctxtType: the type definition
15034 * @ancestor: an ancestor of @ctxtType
15035 *
15036 * Checks st-props-correct (2) + ct-props-correct (3).
15037 * Circular type definitions are not allowed.
15038 *
15039 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
15040 * circular, 0 otherwise.
15041 */
15042 static int
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxtType,xmlSchemaTypePtr ancestor)15043 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
15044 xmlSchemaTypePtr ctxtType,
15045 xmlSchemaTypePtr ancestor)
15046 {
15047 int ret;
15048
15049 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
15050 return (0);
15051
15052 if (ctxtType == ancestor) {
15053 xmlSchemaPCustomErr(pctxt,
15054 XML_SCHEMAP_ST_PROPS_CORRECT_2,
15055 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
15056 "The definition is circular", NULL);
15057 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
15058 }
15059 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
15060 /*
15061 * Avoid infinite recursion on circular types not yet checked.
15062 */
15063 return (0);
15064 }
15065 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
15066 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
15067 ancestor->baseType);
15068 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
15069 return (ret);
15070 }
15071
15072 /**
15073 * xmlSchemaCheckTypeDefCircular:
15074 * @item: the complex/simple type definition
15075 * @ctxt: the parser context
15076 * @name: the name
15077 *
15078 * Checks for circular type definitions.
15079 */
15080 static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,xmlSchemaParserCtxtPtr ctxt)15081 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
15082 xmlSchemaParserCtxtPtr ctxt)
15083 {
15084 if ((item == NULL) ||
15085 (item->type == XML_SCHEMA_TYPE_BASIC) ||
15086 (item->baseType == NULL))
15087 return;
15088 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
15089 item->baseType);
15090 }
15091
15092 /*
15093 * Simple Type Definition Representation OK (src-simple-type) 4
15094 *
15095 * "4 Circular union type definition is disallowed. That is, if the
15096 * <union> alternative is chosen, there must not be any entries in the
15097 * memberTypes [attribute] at any depth which resolve to the component
15098 * corresponding to the <simpleType>."
15099 *
15100 * Note that this should work on the *representation* of a component,
15101 * thus assumes any union types in the member types not being yet
15102 * substituted. At this stage we need the variety of the types
15103 * to be already computed.
15104 */
15105 static int
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxType,xmlSchemaTypeLinkPtr members)15106 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
15107 xmlSchemaTypePtr ctxType,
15108 xmlSchemaTypeLinkPtr members)
15109 {
15110 xmlSchemaTypeLinkPtr member;
15111 xmlSchemaTypePtr memberType;
15112
15113 member = members;
15114 while (member != NULL) {
15115 memberType = member->type;
15116 while ((memberType != NULL) &&
15117 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
15118 if (memberType == ctxType) {
15119 xmlSchemaPCustomErr(pctxt,
15120 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
15121 WXS_BASIC_CAST ctxType, NULL,
15122 "The union type definition is circular", NULL);
15123 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
15124 }
15125 if ((WXS_IS_UNION(memberType)) &&
15126 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
15127 {
15128 int res;
15129 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
15130 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15131 ctxType,
15132 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15133 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15134 if (res != 0)
15135 return(res);
15136 }
15137 memberType = memberType->baseType;
15138 }
15139 member = member->next;
15140 }
15141 return(0);
15142 }
15143
15144 static int
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15145 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15146 xmlSchemaTypePtr type)
15147 {
15148 if (! WXS_IS_UNION(type))
15149 return(0);
15150 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15151 type->memberTypes));
15152 }
15153
15154 /**
15155 * xmlSchemaResolveTypeReferences:
15156 * @item: the complex/simple type definition
15157 * @ctxt: the parser context
15158 * @name: the name
15159 *
15160 * Resolves type definition references
15161 */
15162 static void
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,xmlSchemaParserCtxtPtr ctxt)15163 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15164 xmlSchemaParserCtxtPtr ctxt)
15165 {
15166 if (typeDef == NULL)
15167 return;
15168
15169 /*
15170 * Resolve the base type.
15171 */
15172 if (typeDef->baseType == NULL) {
15173 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15174 typeDef->base, typeDef->baseNs);
15175 if (typeDef->baseType == NULL) {
15176 xmlSchemaPResCompAttrErr(ctxt,
15177 XML_SCHEMAP_SRC_RESOLVE,
15178 WXS_BASIC_CAST typeDef, typeDef->node,
15179 "base", typeDef->base, typeDef->baseNs,
15180 XML_SCHEMA_TYPE_SIMPLE, NULL);
15181 return;
15182 }
15183 }
15184 if (WXS_IS_SIMPLE(typeDef)) {
15185 if (WXS_IS_UNION(typeDef)) {
15186 /*
15187 * Resolve the memberTypes.
15188 */
15189 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15190 return;
15191 } else if (WXS_IS_LIST(typeDef)) {
15192 /*
15193 * Resolve the itemType.
15194 */
15195 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15196
15197 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15198 typeDef->base, typeDef->baseNs);
15199
15200 if ((typeDef->subtypes == NULL) ||
15201 (! WXS_IS_SIMPLE(typeDef->subtypes)))
15202 {
15203 typeDef->subtypes = NULL;
15204 xmlSchemaPResCompAttrErr(ctxt,
15205 XML_SCHEMAP_SRC_RESOLVE,
15206 WXS_BASIC_CAST typeDef, typeDef->node,
15207 "itemType", typeDef->base, typeDef->baseNs,
15208 XML_SCHEMA_TYPE_SIMPLE, NULL);
15209 }
15210 }
15211 return;
15212 }
15213 }
15214 /*
15215 * The ball of letters below means, that if we have a particle
15216 * which has a QName-helper component as its {term}, we want
15217 * to resolve it...
15218 */
15219 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15220 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15221 XML_SCHEMA_TYPE_PARTICLE) &&
15222 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15223 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15224 XML_SCHEMA_EXTRA_QNAMEREF))
15225 {
15226 xmlSchemaQNameRefPtr ref =
15227 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15228 xmlSchemaModelGroupDefPtr groupDef;
15229
15230 /*
15231 * URGENT TODO: Test this.
15232 */
15233 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15234 /*
15235 * Resolve the MG definition reference.
15236 */
15237 groupDef =
15238 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15239 ref->itemType, ref->name, ref->targetNamespace);
15240 if (groupDef == NULL) {
15241 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15242 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15243 "ref", ref->name, ref->targetNamespace, ref->itemType,
15244 NULL);
15245 /* Remove the particle. */
15246 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15247 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15248 /* Remove the particle. */
15249 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15250 else {
15251 /*
15252 * Assign the MG definition's {model group} to the
15253 * particle's {term}.
15254 */
15255 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15256
15257 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15258 /*
15259 * SPEC cos-all-limited (1.2)
15260 * "1.2 the {term} property of a particle with
15261 * {max occurs}=1 which is part of a pair which constitutes
15262 * the {content type} of a complex type definition."
15263 */
15264 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15265 xmlSchemaCustomErr(ACTXT_CAST ctxt,
15266 /* TODO: error code */
15267 XML_SCHEMAP_COS_ALL_LIMITED,
15268 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15269 "The particle's {max occurs} must be 1, since the "
15270 "reference resolves to an 'all' model group",
15271 NULL, NULL);
15272 }
15273 }
15274 }
15275 }
15276 }
15277
15278
15279
15280 /**
15281 * xmlSchemaCheckSTPropsCorrect:
15282 * @ctxt: the schema parser context
15283 * @type: the simple type definition
15284 *
15285 * Checks st-props-correct.
15286 *
15287 * Returns 0 if the properties are correct,
15288 * if not, a positive error code and -1 on internal
15289 * errors.
15290 */
15291 static int
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)15292 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15293 xmlSchemaTypePtr type)
15294 {
15295 xmlSchemaTypePtr baseType = type->baseType;
15296 xmlChar *str = NULL;
15297
15298 /* STATE: error funcs converted. */
15299 /*
15300 * Schema Component Constraint: Simple Type Definition Properties Correct
15301 *
15302 * NOTE: This is somehow redundant, since we actually built a simple type
15303 * to have all the needed information; this acts as an self test.
15304 */
15305 /* Base type: If the datatype has been `derived` by `restriction`
15306 * then the Simple Type Definition component from which it is `derived`,
15307 * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15308 */
15309 if (baseType == NULL) {
15310 /*
15311 * TODO: Think about: "modulo the impact of Missing
15312 * Sub-components ($5.3)."
15313 */
15314 xmlSchemaPCustomErr(ctxt,
15315 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15316 WXS_BASIC_CAST type, NULL,
15317 "No base type existent", NULL);
15318 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15319
15320 }
15321 if (! WXS_IS_SIMPLE(baseType)) {
15322 xmlSchemaPCustomErr(ctxt,
15323 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15324 WXS_BASIC_CAST type, NULL,
15325 "The base type '%s' is not a simple type",
15326 xmlSchemaGetComponentQName(&str, baseType));
15327 FREE_AND_NULL(str)
15328 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15329 }
15330 if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15331 (WXS_IS_RESTRICTION(type) == 0) &&
15332 ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15333 (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15334 xmlSchemaPCustomErr(ctxt,
15335 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15336 WXS_BASIC_CAST type, NULL,
15337 "A type, derived by list or union, must have "
15338 "the simple ur-type definition as base type, not '%s'",
15339 xmlSchemaGetComponentQName(&str, baseType));
15340 FREE_AND_NULL(str)
15341 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15342 }
15343 /*
15344 * Variety: One of {atomic, list, union}.
15345 */
15346 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15347 (! WXS_IS_LIST(type))) {
15348 xmlSchemaPCustomErr(ctxt,
15349 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15350 WXS_BASIC_CAST type, NULL,
15351 "The variety is absent", NULL);
15352 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15353 }
15354 /* TODO: Finish this. Hmm, is this finished? */
15355
15356 /*
15357 * 3 The {final} of the {base type definition} must not contain restriction.
15358 */
15359 if (xmlSchemaTypeFinalContains(baseType,
15360 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15361 xmlSchemaPCustomErr(ctxt,
15362 XML_SCHEMAP_ST_PROPS_CORRECT_3,
15363 WXS_BASIC_CAST type, NULL,
15364 "The 'final' of its base type '%s' must not contain "
15365 "'restriction'",
15366 xmlSchemaGetComponentQName(&str, baseType));
15367 FREE_AND_NULL(str)
15368 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15369 }
15370
15371 /*
15372 * 2 All simple type definitions must be derived ultimately from the `simple
15373 * ur-type definition` (so circular definitions are disallowed). That is, it
15374 * must be possible to reach a built-in primitive datatype or the `simple
15375 * ur-type definition` by repeatedly following the {base type definition}.
15376 *
15377 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15378 */
15379 return (0);
15380 }
15381
15382 /**
15383 * xmlSchemaCheckCOSSTRestricts:
15384 * @ctxt: the schema parser context
15385 * @type: the simple type definition
15386 *
15387 * Schema Component Constraint:
15388 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15389
15390 * Checks if the given @type (simpleType) is derived validly by restriction.
15391 * STATUS:
15392 *
15393 * Returns -1 on internal errors, 0 if the type is validly derived,
15394 * a positive error code otherwise.
15395 */
15396 static int
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15397 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15398 xmlSchemaTypePtr type)
15399 {
15400 xmlChar *str = NULL;
15401
15402 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15403 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15404 "given type is not a user-derived simpleType");
15405 return (-1);
15406 }
15407
15408 if (WXS_IS_ATOMIC(type)) {
15409 xmlSchemaTypePtr primitive;
15410 /*
15411 * 1.1 The {base type definition} must be an atomic simple
15412 * type definition or a built-in primitive datatype.
15413 */
15414 if (! WXS_IS_ATOMIC(type->baseType)) {
15415 xmlSchemaPCustomErr(pctxt,
15416 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15417 WXS_BASIC_CAST type, NULL,
15418 "The base type '%s' is not an atomic simple type",
15419 xmlSchemaGetComponentQName(&str, type->baseType));
15420 FREE_AND_NULL(str)
15421 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15422 }
15423 /* 1.2 The {final} of the {base type definition} must not contain
15424 * restriction.
15425 */
15426 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15427 if (xmlSchemaTypeFinalContains(type->baseType,
15428 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15429 xmlSchemaPCustomErr(pctxt,
15430 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15431 WXS_BASIC_CAST type, NULL,
15432 "The final of its base type '%s' must not contain 'restriction'",
15433 xmlSchemaGetComponentQName(&str, type->baseType));
15434 FREE_AND_NULL(str)
15435 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15436 }
15437
15438 /*
15439 * 1.3.1 DF must be an allowed constraining facet for the {primitive
15440 * type definition}, as specified in the appropriate subsection of 3.2
15441 * Primitive datatypes.
15442 */
15443 if (type->facets != NULL) {
15444 xmlSchemaFacetPtr facet;
15445 int ok = 1;
15446
15447 primitive = xmlSchemaGetPrimitiveType(type);
15448 if (primitive == NULL) {
15449 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15450 "failed to get primitive type");
15451 return (-1);
15452 }
15453 facet = type->facets;
15454 do {
15455 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15456 ok = 0;
15457 xmlSchemaPIllegalFacetAtomicErr(pctxt,
15458 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15459 type, primitive, facet);
15460 }
15461 facet = facet->next;
15462 } while (facet != NULL);
15463 if (ok == 0)
15464 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15465 }
15466 /*
15467 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15468 * of the {base type definition} (call this BF),then the DF's {value}
15469 * must be a valid restriction of BF's {value} as defined in
15470 * [XML Schemas: Datatypes]."
15471 *
15472 * NOTE (1.3.2) Facet derivation constraints are currently handled in
15473 * xmlSchemaDeriveAndValidateFacets()
15474 */
15475 } else if (WXS_IS_LIST(type)) {
15476 xmlSchemaTypePtr itemType = NULL;
15477
15478 itemType = type->subtypes;
15479 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15480 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15481 "failed to evaluate the item type");
15482 return (-1);
15483 }
15484 if (WXS_IS_TYPE_NOT_FIXED(itemType))
15485 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15486 /*
15487 * 2.1 The {item type definition} must have a {variety} of atomic or
15488 * union (in which case all the {member type definitions}
15489 * must be atomic).
15490 */
15491 if ((! WXS_IS_ATOMIC(itemType)) &&
15492 (! WXS_IS_UNION(itemType))) {
15493 xmlSchemaPCustomErr(pctxt,
15494 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15495 WXS_BASIC_CAST type, NULL,
15496 "The item type '%s' does not have a variety of atomic or union",
15497 xmlSchemaGetComponentQName(&str, itemType));
15498 FREE_AND_NULL(str)
15499 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15500 } else if (WXS_IS_UNION(itemType)) {
15501 xmlSchemaTypeLinkPtr member;
15502
15503 member = itemType->memberTypes;
15504 while (member != NULL) {
15505 if (! WXS_IS_ATOMIC(member->type)) {
15506 xmlSchemaPCustomErr(pctxt,
15507 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15508 WXS_BASIC_CAST type, NULL,
15509 "The item type is a union type, but the "
15510 "member type '%s' of this item type is not atomic",
15511 xmlSchemaGetComponentQName(&str, member->type));
15512 FREE_AND_NULL(str)
15513 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15514 }
15515 member = member->next;
15516 }
15517 }
15518
15519 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15520 xmlSchemaFacetPtr facet;
15521 /*
15522 * This is the case if we have: <simpleType><list ..
15523 */
15524 /*
15525 * 2.3.1
15526 * 2.3.1.1 The {final} of the {item type definition} must not
15527 * contain list.
15528 */
15529 if (xmlSchemaTypeFinalContains(itemType,
15530 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15531 xmlSchemaPCustomErr(pctxt,
15532 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15533 WXS_BASIC_CAST type, NULL,
15534 "The final of its item type '%s' must not contain 'list'",
15535 xmlSchemaGetComponentQName(&str, itemType));
15536 FREE_AND_NULL(str)
15537 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15538 }
15539 /*
15540 * 2.3.1.2 The {facets} must only contain the whiteSpace
15541 * facet component.
15542 * OPTIMIZE TODO: the S4S already disallows any facet
15543 * to be specified.
15544 */
15545 if (type->facets != NULL) {
15546 facet = type->facets;
15547 do {
15548 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15549 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15550 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15551 type, facet);
15552 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15553 }
15554 facet = facet->next;
15555 } while (facet != NULL);
15556 }
15557 /*
15558 * MAYBE TODO: (Hmm, not really) Datatypes states:
15559 * A `list` datatype can be `derived` from an `atomic` datatype
15560 * whose `lexical space` allows space (such as string or anyURI)or
15561 * a `union` datatype any of whose {member type definitions}'s
15562 * `lexical space` allows space.
15563 */
15564 } else {
15565 /*
15566 * This is the case if we have: <simpleType><restriction ...
15567 * I.e. the variety of "list" is inherited.
15568 */
15569 /*
15570 * 2.3.2
15571 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15572 */
15573 if (! WXS_IS_LIST(type->baseType)) {
15574 xmlSchemaPCustomErr(pctxt,
15575 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15576 WXS_BASIC_CAST type, NULL,
15577 "The base type '%s' must be a list type",
15578 xmlSchemaGetComponentQName(&str, type->baseType));
15579 FREE_AND_NULL(str)
15580 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15581 }
15582 /*
15583 * 2.3.2.2 The {final} of the {base type definition} must not
15584 * contain restriction.
15585 */
15586 if (xmlSchemaTypeFinalContains(type->baseType,
15587 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15588 xmlSchemaPCustomErr(pctxt,
15589 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15590 WXS_BASIC_CAST type, NULL,
15591 "The 'final' of the base type '%s' must not contain 'restriction'",
15592 xmlSchemaGetComponentQName(&str, type->baseType));
15593 FREE_AND_NULL(str)
15594 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15595 }
15596 /*
15597 * 2.3.2.3 The {item type definition} must be validly derived
15598 * from the {base type definition}'s {item type definition} given
15599 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15600 */
15601 {
15602 xmlSchemaTypePtr baseItemType;
15603
15604 baseItemType = type->baseType->subtypes;
15605 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15606 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15607 "failed to eval the item type of a base type");
15608 return (-1);
15609 }
15610 if ((itemType != baseItemType) &&
15611 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15612 baseItemType, 0) != 0)) {
15613 xmlChar *strBIT = NULL, *strBT = NULL;
15614 xmlSchemaPCustomErrExt(pctxt,
15615 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15616 WXS_BASIC_CAST type, NULL,
15617 "The item type '%s' is not validly derived from "
15618 "the item type '%s' of the base type '%s'",
15619 xmlSchemaGetComponentQName(&str, itemType),
15620 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15621 xmlSchemaGetComponentQName(&strBT, type->baseType));
15622
15623 FREE_AND_NULL(str)
15624 FREE_AND_NULL(strBIT)
15625 FREE_AND_NULL(strBT)
15626 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15627 }
15628 }
15629
15630 if (type->facets != NULL) {
15631 xmlSchemaFacetPtr facet;
15632 int ok = 1;
15633 /*
15634 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15635 * and enumeration facet components are allowed among the {facets}.
15636 */
15637 facet = type->facets;
15638 do {
15639 switch (facet->type) {
15640 case XML_SCHEMA_FACET_LENGTH:
15641 case XML_SCHEMA_FACET_MINLENGTH:
15642 case XML_SCHEMA_FACET_MAXLENGTH:
15643 case XML_SCHEMA_FACET_WHITESPACE:
15644 /*
15645 * TODO: 2.5.1.2 List datatypes
15646 * The value of `whiteSpace` is fixed to the value collapse.
15647 */
15648 case XML_SCHEMA_FACET_PATTERN:
15649 case XML_SCHEMA_FACET_ENUMERATION:
15650 break;
15651 default: {
15652 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15653 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15654 type, facet);
15655 /*
15656 * We could return, but it's nicer to report all
15657 * invalid facets.
15658 */
15659 ok = 0;
15660 }
15661 }
15662 facet = facet->next;
15663 } while (facet != NULL);
15664 if (ok == 0)
15665 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15666 /*
15667 * SPEC (2.3.2.5) (same as 1.3.2)
15668 *
15669 * NOTE (2.3.2.5) This is currently done in
15670 * xmlSchemaDeriveAndValidateFacets()
15671 */
15672 }
15673 }
15674 } else if (WXS_IS_UNION(type)) {
15675 /*
15676 * 3.1 The {member type definitions} must all have {variety} of
15677 * atomic or list.
15678 */
15679 xmlSchemaTypeLinkPtr member;
15680
15681 member = type->memberTypes;
15682 while (member != NULL) {
15683 if (WXS_IS_TYPE_NOT_FIXED(member->type))
15684 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15685
15686 if ((! WXS_IS_ATOMIC(member->type)) &&
15687 (! WXS_IS_LIST(member->type))) {
15688 xmlSchemaPCustomErr(pctxt,
15689 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15690 WXS_BASIC_CAST type, NULL,
15691 "The member type '%s' is neither an atomic, nor a list type",
15692 xmlSchemaGetComponentQName(&str, member->type));
15693 FREE_AND_NULL(str)
15694 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15695 }
15696 member = member->next;
15697 }
15698 /*
15699 * 3.3.1 If the {base type definition} is the `simple ur-type
15700 * definition`
15701 */
15702 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15703 /*
15704 * 3.3.1.1 All of the {member type definitions} must have a
15705 * {final} which does not contain union.
15706 */
15707 member = type->memberTypes;
15708 while (member != NULL) {
15709 if (xmlSchemaTypeFinalContains(member->type,
15710 XML_SCHEMAS_TYPE_FINAL_UNION)) {
15711 xmlSchemaPCustomErr(pctxt,
15712 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15713 WXS_BASIC_CAST type, NULL,
15714 "The 'final' of member type '%s' contains 'union'",
15715 xmlSchemaGetComponentQName(&str, member->type));
15716 FREE_AND_NULL(str)
15717 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15718 }
15719 member = member->next;
15720 }
15721 /*
15722 * 3.3.1.2 The {facets} must be empty.
15723 */
15724 if (type->facetSet != NULL) {
15725 xmlSchemaPCustomErr(pctxt,
15726 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15727 WXS_BASIC_CAST type, NULL,
15728 "No facets allowed", NULL);
15729 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15730 }
15731 } else {
15732 /*
15733 * 3.3.2.1 The {base type definition} must have a {variety} of union.
15734 * I.e. the variety of "list" is inherited.
15735 */
15736 if (! WXS_IS_UNION(type->baseType)) {
15737 xmlSchemaPCustomErr(pctxt,
15738 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15739 WXS_BASIC_CAST type, NULL,
15740 "The base type '%s' is not a union type",
15741 xmlSchemaGetComponentQName(&str, type->baseType));
15742 FREE_AND_NULL(str)
15743 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15744 }
15745 /*
15746 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15747 */
15748 if (xmlSchemaTypeFinalContains(type->baseType,
15749 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15750 xmlSchemaPCustomErr(pctxt,
15751 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15752 WXS_BASIC_CAST type, NULL,
15753 "The 'final' of its base type '%s' must not contain 'restriction'",
15754 xmlSchemaGetComponentQName(&str, type->baseType));
15755 FREE_AND_NULL(str)
15756 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15757 }
15758 /*
15759 * 3.3.2.3 The {member type definitions}, in order, must be validly
15760 * derived from the corresponding type definitions in the {base
15761 * type definition}'s {member type definitions} given the empty set,
15762 * as defined in Type Derivation OK (Simple) ($3.14.6).
15763 */
15764 {
15765 xmlSchemaTypeLinkPtr baseMember;
15766
15767 /*
15768 * OPTIMIZE: if the type is restricting, it has no local defined
15769 * member types and inherits the member types of the base type;
15770 * thus a check for equality can be skipped.
15771 */
15772 /*
15773 * Even worse: I cannot see a scenario where a restricting
15774 * union simple type can have other member types as the member
15775 * types of it's base type. This check seems not necessary with
15776 * respect to the derivation process in libxml2.
15777 * But necessary if constructing types with an API.
15778 */
15779 if (type->memberTypes != NULL) {
15780 member = type->memberTypes;
15781 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15782 if ((member == NULL) && (baseMember != NULL)) {
15783 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15784 "different number of member types in base");
15785 }
15786 while (member != NULL) {
15787 if (baseMember == NULL) {
15788 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15789 "different number of member types in base");
15790 } else if ((member->type != baseMember->type) &&
15791 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15792 member->type, baseMember->type, 0) != 0)) {
15793 xmlChar *strBMT = NULL, *strBT = NULL;
15794
15795 xmlSchemaPCustomErrExt(pctxt,
15796 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15797 WXS_BASIC_CAST type, NULL,
15798 "The member type %s is not validly "
15799 "derived from its corresponding member "
15800 "type %s of the base type %s",
15801 xmlSchemaGetComponentQName(&str, member->type),
15802 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15803 xmlSchemaGetComponentQName(&strBT, type->baseType));
15804 FREE_AND_NULL(str)
15805 FREE_AND_NULL(strBMT)
15806 FREE_AND_NULL(strBT)
15807 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15808 }
15809 member = member->next;
15810 if (baseMember != NULL)
15811 baseMember = baseMember->next;
15812 }
15813 }
15814 }
15815 /*
15816 * 3.3.2.4 Only pattern and enumeration facet components are
15817 * allowed among the {facets}.
15818 */
15819 if (type->facets != NULL) {
15820 xmlSchemaFacetPtr facet;
15821 int ok = 1;
15822
15823 facet = type->facets;
15824 do {
15825 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15826 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15827 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15828 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15829 type, facet);
15830 ok = 0;
15831 }
15832 facet = facet->next;
15833 } while (facet != NULL);
15834 if (ok == 0)
15835 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15836
15837 }
15838 /*
15839 * SPEC (3.3.2.5) (same as 1.3.2)
15840 *
15841 * NOTE (3.3.2.5) This is currently done in
15842 * xmlSchemaDeriveAndValidateFacets()
15843 */
15844 }
15845 }
15846
15847 return (0);
15848 }
15849
15850 /**
15851 * xmlSchemaCheckSRCSimpleType:
15852 * @ctxt: the schema parser context
15853 * @type: the simple type definition
15854 *
15855 * Checks crc-simple-type constraints.
15856 *
15857 * Returns 0 if the constraints are satisfied,
15858 * if not a positive error code and -1 on internal
15859 * errors.
15860 */
15861 #if 0
15862 static int
15863 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15864 xmlSchemaTypePtr type)
15865 {
15866 /*
15867 * src-simple-type.1 The corresponding simple type definition, if any,
15868 * must satisfy the conditions set out in Constraints on Simple Type
15869 * Definition Schema Components ($3.14.6).
15870 */
15871 if (WXS_IS_RESTRICTION(type)) {
15872 /*
15873 * src-simple-type.2 "If the <restriction> alternative is chosen,
15874 * either it must have a base [attribute] or a <simpleType> among its
15875 * [children], but not both."
15876 * NOTE: This is checked in the parse function of <restriction>.
15877 */
15878 /*
15879 *
15880 */
15881 } else if (WXS_IS_LIST(type)) {
15882 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15883 * an itemType [attribute] or a <simpleType> among its [children],
15884 * but not both."
15885 *
15886 * NOTE: This is checked in the parse function of <list>.
15887 */
15888 } else if (WXS_IS_UNION(type)) {
15889 /*
15890 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15891 */
15892 }
15893 return (0);
15894 }
15895 #endif
15896
15897 static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)15898 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15899 {
15900 if (ctxt->vctxt == NULL) {
15901 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15902 if (ctxt->vctxt == NULL) {
15903 xmlSchemaPErr(ctxt, NULL,
15904 XML_SCHEMAP_INTERNAL,
15905 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15906 "failed to create a temp. validation context.\n",
15907 NULL, NULL);
15908 return (-1);
15909 }
15910 /* TODO: Pass user data. */
15911 xmlSchemaSetValidErrors(ctxt->vctxt,
15912 ctxt->error, ctxt->warning, ctxt->errCtxt);
15913 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15914 ctxt->serror, ctxt->errCtxt);
15915 }
15916 return (0);
15917 }
15918
15919 static int
15920 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15921 xmlNodePtr node,
15922 xmlSchemaTypePtr type,
15923 const xmlChar *value,
15924 xmlSchemaValPtr *retVal,
15925 int fireErrors,
15926 int normalize,
15927 int isNormalized);
15928
15929 /**
15930 * xmlSchemaParseCheckCOSValidDefault:
15931 * @pctxt: the schema parser context
15932 * @type: the simple type definition
15933 * @value: the default value
15934 * @node: an optional node (the holder of the value)
15935 *
15936 * Schema Component Constraint: Element Default Valid (Immediate)
15937 * (cos-valid-default)
15938 * This will be used by the parser only. For the validator there's
15939 * an other version.
15940 *
15941 * Returns 0 if the constraints are satisfied,
15942 * if not, a positive error code and -1 on internal
15943 * errors.
15944 */
15945 static int
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)15946 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15947 xmlNodePtr node,
15948 xmlSchemaTypePtr type,
15949 const xmlChar *value,
15950 xmlSchemaValPtr *val)
15951 {
15952 int ret = 0;
15953
15954 /*
15955 * cos-valid-default:
15956 * Schema Component Constraint: Element Default Valid (Immediate)
15957 * For a string to be a valid default with respect to a type
15958 * definition the appropriate case among the following must be true:
15959 */
15960 if WXS_IS_COMPLEX(type) {
15961 /*
15962 * Complex type.
15963 *
15964 * SPEC (2.1) "its {content type} must be a simple type definition
15965 * or mixed."
15966 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15967 * type}'s particle must be `emptiable` as defined by
15968 * Particle Emptiable ($3.9.6)."
15969 */
15970 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15971 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15972 /* NOTE that this covers (2.2.2) as well. */
15973 xmlSchemaPCustomErr(pctxt,
15974 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15975 WXS_BASIC_CAST type, type->node,
15976 "For a string to be a valid default, the type definition "
15977 "must be a simple type or a complex type with mixed content "
15978 "and a particle emptiable", NULL);
15979 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15980 }
15981 }
15982 /*
15983 * 1 If the type definition is a simple type definition, then the string
15984 * must be `valid` with respect to that definition as defined by String
15985 * Valid ($3.14.4).
15986 *
15987 * AND
15988 *
15989 * 2.2.1 If the {content type} is a simple type definition, then the
15990 * string must be `valid` with respect to that simple type definition
15991 * as defined by String Valid ($3.14.4).
15992 */
15993 if (WXS_IS_SIMPLE(type))
15994 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15995 type, value, val, 1, 1, 0);
15996 else if (WXS_HAS_SIMPLE_CONTENT(type))
15997 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15998 type->contentTypeDef, value, val, 1, 1, 0);
15999 else
16000 return (ret);
16001
16002 if (ret < 0) {
16003 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
16004 "calling xmlSchemaVCheckCVCSimpleType()");
16005 }
16006
16007 return (ret);
16008 }
16009
16010 /**
16011 * xmlSchemaCheckCTPropsCorrect:
16012 * @ctxt: the schema parser context
16013 * @type: the complex type definition
16014 *
16015 *.(4.6) Constraints on Complex Type Definition Schema Components
16016 * Schema Component Constraint:
16017 * Complex Type Definition Properties Correct (ct-props-correct)
16018 * STATUS: (seems) complete
16019 *
16020 * Returns 0 if the constraints are satisfied, a positive
16021 * error code if not and -1 if an internal error occurred.
16022 */
16023 static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)16024 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
16025 xmlSchemaTypePtr type)
16026 {
16027 /*
16028 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
16029 *
16030 * SPEC (1) "The values of the properties of a complex type definition must
16031 * be as described in the property tableau in The Complex Type Definition
16032 * Schema Component ($3.4.1), modulo the impact of Missing
16033 * Sub-components ($5.3)."
16034 */
16035 if ((type->baseType != NULL) &&
16036 (WXS_IS_SIMPLE(type->baseType)) &&
16037 (WXS_IS_EXTENSION(type) == 0)) {
16038 /*
16039 * SPEC (2) "If the {base type definition} is a simple type definition,
16040 * the {derivation method} must be extension."
16041 */
16042 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16043 XML_SCHEMAP_SRC_CT_1,
16044 NULL, WXS_BASIC_CAST type,
16045 "If the base type is a simple type, the derivation method must be "
16046 "'extension'", NULL, NULL);
16047 return (XML_SCHEMAP_SRC_CT_1);
16048 }
16049 /*
16050 * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
16051 * definition`. That is, it must be possible to reach the `ur-type
16052 * definition` by repeatedly following the {base type definition}."
16053 *
16054 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
16055 */
16056 /*
16057 * NOTE that (4) and (5) need the following:
16058 * - attribute uses need to be already inherited (apply attr. prohibitions)
16059 * - attribute group references need to be expanded already
16060 * - simple types need to be typefixed already
16061 */
16062 if (type->attrUses &&
16063 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
16064 {
16065 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
16066 xmlSchemaAttributeUsePtr use, tmp;
16067 int i, j, hasId = 0;
16068
16069 for (i = uses->nbItems -1; i >= 0; i--) {
16070 use = uses->items[i];
16071
16072 /*
16073 * SPEC ct-props-correct
16074 * (4) "Two distinct attribute declarations in the
16075 * {attribute uses} must not have identical {name}s and
16076 * {target namespace}s."
16077 */
16078 if (i > 0) {
16079 for (j = i -1; j >= 0; j--) {
16080 tmp = uses->items[j];
16081 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16082 WXS_ATTRUSE_DECL_NAME(tmp)) &&
16083 (WXS_ATTRUSE_DECL_TNS(use) ==
16084 WXS_ATTRUSE_DECL_TNS(tmp)))
16085 {
16086 xmlChar *str = NULL;
16087
16088 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16089 XML_SCHEMAP_AG_PROPS_CORRECT,
16090 NULL, WXS_BASIC_CAST type,
16091 "Duplicate %s",
16092 xmlSchemaGetComponentDesignation(&str, use),
16093 NULL);
16094 FREE_AND_NULL(str);
16095 /*
16096 * Remove the duplicate.
16097 */
16098 if (xmlSchemaItemListRemove(uses, i) == -1)
16099 goto exit_failure;
16100 goto next_use;
16101 }
16102 }
16103 }
16104 /*
16105 * SPEC ct-props-correct
16106 * (5) "Two distinct attribute declarations in the
16107 * {attribute uses} must not have {type definition}s which
16108 * are or are derived from ID."
16109 */
16110 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
16111 if (xmlSchemaIsDerivedFromBuiltInType(
16112 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
16113 {
16114 if (hasId) {
16115 xmlChar *str = NULL;
16116
16117 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16118 XML_SCHEMAP_AG_PROPS_CORRECT,
16119 NULL, WXS_BASIC_CAST type,
16120 "There must not exist more than one attribute "
16121 "declaration of type 'xs:ID' "
16122 "(or derived from 'xs:ID'). The %s violates this "
16123 "constraint",
16124 xmlSchemaGetComponentDesignation(&str, use),
16125 NULL);
16126 FREE_AND_NULL(str);
16127 if (xmlSchemaItemListRemove(uses, i) == -1)
16128 goto exit_failure;
16129 }
16130
16131 hasId = 1;
16132 }
16133 }
16134 next_use: {}
16135 }
16136 }
16137 return (0);
16138 exit_failure:
16139 return(-1);
16140 }
16141
16142 static int
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,xmlSchemaTypePtr typeB)16143 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16144 xmlSchemaTypePtr typeB)
16145 {
16146 /*
16147 * TODO: This should implement component-identity
16148 * in the future.
16149 */
16150 if ((typeA == NULL) || (typeB == NULL))
16151 return (0);
16152 return (typeA == typeB);
16153 }
16154
16155 /**
16156 * xmlSchemaCheckCOSCTDerivedOK:
16157 * @ctxt: the schema parser context
16158 * @type: the to-be derived complex type definition
16159 * @baseType: the base complex type definition
16160 * @set: the given set
16161 *
16162 * Schema Component Constraint:
16163 * Type Derivation OK (Complex) (cos-ct-derived-ok)
16164 *
16165 * STATUS: completed
16166 *
16167 * Returns 0 if the constraints are satisfied, or 1
16168 * if not.
16169 */
16170 static int
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16171 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16172 xmlSchemaTypePtr type,
16173 xmlSchemaTypePtr baseType,
16174 int set)
16175 {
16176 int equal = xmlSchemaAreEqualTypes(type, baseType);
16177 /* TODO: Error codes. */
16178 /*
16179 * SPEC "For a complex type definition (call it D, for derived)
16180 * to be validly derived from a type definition (call this
16181 * B, for base) given a subset of {extension, restriction}
16182 * all of the following must be true:"
16183 */
16184 if (! equal) {
16185 /*
16186 * SPEC (1) "If B and D are not the same type definition, then the
16187 * {derivation method} of D must not be in the subset."
16188 */
16189 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16190 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16191 return (1);
16192 } else {
16193 /*
16194 * SPEC (2.1) "B and D must be the same type definition."
16195 */
16196 return (0);
16197 }
16198 /*
16199 * SPEC (2.2) "B must be D's {base type definition}."
16200 */
16201 if (type->baseType == baseType)
16202 return (0);
16203 /*
16204 * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16205 * definition`."
16206 */
16207 if (WXS_IS_ANYTYPE(type->baseType))
16208 return (1);
16209
16210 if (WXS_IS_COMPLEX(type->baseType)) {
16211 /*
16212 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16213 * must be validly derived from B given the subset as defined by this
16214 * constraint."
16215 */
16216 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16217 baseType, set));
16218 } else {
16219 /*
16220 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16221 * must be validly derived from B given the subset as defined in Type
16222 * Derivation OK (Simple) ($3.14.6).
16223 */
16224 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16225 baseType, set));
16226 }
16227 }
16228
16229 /**
16230 * xmlSchemaCheckCOSDerivedOK:
16231 * @type: the derived simple type definition
16232 * @baseType: the base type definition
16233 *
16234 * Calls:
16235 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16236 *
16237 * Checks whether @type can be validly derived from @baseType.
16238 *
16239 * Returns 0 on success, an positive error code otherwise.
16240 */
16241 static int
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16242 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16243 xmlSchemaTypePtr type,
16244 xmlSchemaTypePtr baseType,
16245 int set)
16246 {
16247 if (WXS_IS_SIMPLE(type))
16248 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16249 else
16250 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16251 }
16252
16253 /**
16254 * xmlSchemaCheckCOSCTExtends:
16255 * @ctxt: the schema parser context
16256 * @type: the complex type definition
16257 *
16258 * (3.4.6) Constraints on Complex Type Definition Schema Components
16259 * Schema Component Constraint:
16260 * Derivation Valid (Extension) (cos-ct-extends)
16261 *
16262 * STATUS:
16263 * missing:
16264 * (1.5)
16265 * (1.4.3.2.2.2) "Particle Valid (Extension)"
16266 *
16267 * Returns 0 if the constraints are satisfied, a positive
16268 * error code if not and -1 if an internal error occurred.
16269 */
16270 static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16271 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16272 xmlSchemaTypePtr type)
16273 {
16274 xmlSchemaTypePtr base = type->baseType;
16275 /*
16276 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16277 * temporarily only.
16278 */
16279 /*
16280 * SPEC (1) "If the {base type definition} is a complex type definition,
16281 * then all of the following must be true:"
16282 */
16283 if (WXS_IS_COMPLEX(base)) {
16284 /*
16285 * SPEC (1.1) "The {final} of the {base type definition} must not
16286 * contain extension."
16287 */
16288 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16289 xmlSchemaPCustomErr(ctxt,
16290 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16291 WXS_BASIC_CAST type, NULL,
16292 "The 'final' of the base type definition "
16293 "contains 'extension'", NULL);
16294 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16295 }
16296
16297 /*
16298 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16299 * since they are automatically satisfied through the
16300 * inheriting mechanism.
16301 * Note that even if redefining components, the inheriting mechanism
16302 * is used.
16303 */
16304 #if 0
16305 /*
16306 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16307 * uses}
16308 * of the complex type definition itself, that is, for every attribute
16309 * use in the {attribute uses} of the {base type definition}, there
16310 * must be an attribute use in the {attribute uses} of the complex
16311 * type definition itself whose {attribute declaration} has the same
16312 * {name}, {target namespace} and {type definition} as its attribute
16313 * declaration"
16314 */
16315 if (base->attrUses != NULL) {
16316 int i, j, found;
16317 xmlSchemaAttributeUsePtr use, buse;
16318
16319 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16320 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16321 found = 0;
16322 if (type->attrUses != NULL) {
16323 use = (WXS_LIST_CAST type->attrUses)->items[j];
16324 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16325 {
16326 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16327 WXS_ATTRUSE_DECL_NAME(buse)) &&
16328 (WXS_ATTRUSE_DECL_TNS(use) ==
16329 WXS_ATTRUSE_DECL_TNS(buse)) &&
16330 (WXS_ATTRUSE_TYPEDEF(use) ==
16331 WXS_ATTRUSE_TYPEDEF(buse))
16332 {
16333 found = 1;
16334 break;
16335 }
16336 }
16337 }
16338 if (! found) {
16339 xmlChar *str = NULL;
16340
16341 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16342 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16343 NULL, WXS_BASIC_CAST type,
16344 /*
16345 * TODO: The report does not indicate that also the
16346 * type needs to be the same.
16347 */
16348 "This type is missing a matching correspondent "
16349 "for its {base type}'s %s in its {attribute uses}",
16350 xmlSchemaGetComponentDesignation(&str,
16351 buse->children),
16352 NULL);
16353 FREE_AND_NULL(str)
16354 }
16355 }
16356 }
16357 /*
16358 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16359 * definition must also have one, and the base type definition's
16360 * {attribute wildcard}'s {namespace constraint} must be a subset
16361 * of the complex type definition's {attribute wildcard}'s {namespace
16362 * constraint}, as defined by Wildcard Subset ($3.10.6)."
16363 */
16364
16365 /*
16366 * MAYBE TODO: Enable if ever needed. But this will be needed only
16367 * if created the type via a schema construction API.
16368 */
16369 if (base->attributeWildcard != NULL) {
16370 if (type->attributeWildcard == NULL) {
16371 xmlChar *str = NULL;
16372
16373 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16374 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16375 NULL, type,
16376 "The base %s has an attribute wildcard, "
16377 "but this type is missing an attribute wildcard",
16378 xmlSchemaGetComponentDesignation(&str, base));
16379 FREE_AND_NULL(str)
16380
16381 } else if (xmlSchemaCheckCOSNSSubset(
16382 base->attributeWildcard, type->attributeWildcard))
16383 {
16384 xmlChar *str = NULL;
16385
16386 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16387 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16388 NULL, type,
16389 "The attribute wildcard is not a valid "
16390 "superset of the one in the base %s",
16391 xmlSchemaGetComponentDesignation(&str, base));
16392 FREE_AND_NULL(str)
16393 }
16394 }
16395 #endif
16396 /*
16397 * SPEC (1.4) "One of the following must be true:"
16398 */
16399 if ((type->contentTypeDef != NULL) &&
16400 (type->contentTypeDef == base->contentTypeDef)) {
16401 /*
16402 * SPEC (1.4.1) "The {content type} of the {base type definition}
16403 * and the {content type} of the complex type definition itself
16404 * must be the same simple type definition"
16405 * PASS
16406 */
16407 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16408 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16409 /*
16410 * SPEC (1.4.2) "The {content type} of both the {base type
16411 * definition} and the complex type definition itself must
16412 * be empty."
16413 * PASS
16414 */
16415 } else {
16416 /*
16417 * SPEC (1.4.3) "All of the following must be true:"
16418 */
16419 if (type->subtypes == NULL) {
16420 /*
16421 * SPEC 1.4.3.1 The {content type} of the complex type
16422 * definition itself must specify a particle.
16423 */
16424 xmlSchemaPCustomErr(ctxt,
16425 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16426 WXS_BASIC_CAST type, NULL,
16427 "The content type must specify a particle", NULL);
16428 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16429 }
16430 /*
16431 * SPEC (1.4.3.2) "One of the following must be true:"
16432 */
16433 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16434 /*
16435 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16436 * definition} must be empty.
16437 * PASS
16438 */
16439 } else {
16440 /*
16441 * SPEC (1.4.3.2.2) "All of the following must be true:"
16442 */
16443 if ((type->contentType != base->contentType) ||
16444 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16445 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16446 /*
16447 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16448 * or both must be element-only."
16449 */
16450 xmlSchemaPCustomErr(ctxt,
16451 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16452 WXS_BASIC_CAST type, NULL,
16453 "The content type of both, the type and its base "
16454 "type, must either 'mixed' or 'element-only'", NULL);
16455 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16456 }
16457 /*
16458 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16459 * complex type definition must be a `valid extension`
16460 * of the {base type definition}'s particle, as defined
16461 * in Particle Valid (Extension) ($3.9.6)."
16462 *
16463 * NOTE that we won't check "Particle Valid (Extension)",
16464 * since it is ensured by the derivation process in
16465 * xmlSchemaTypeFixup(). We need to implement this when heading
16466 * for a construction API
16467 * TODO: !! This is needed to be checked if redefining a type !!
16468 */
16469 }
16470 /*
16471 * URGENT TODO (1.5)
16472 */
16473 }
16474 } else {
16475 /*
16476 * SPEC (2) "If the {base type definition} is a simple type definition,
16477 * then all of the following must be true:"
16478 */
16479 if (type->contentTypeDef != base) {
16480 /*
16481 * SPEC (2.1) "The {content type} must be the same simple type
16482 * definition."
16483 */
16484 xmlSchemaPCustomErr(ctxt,
16485 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16486 WXS_BASIC_CAST type, NULL,
16487 "The content type must be the simple base type", NULL);
16488 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16489 }
16490 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16491 /*
16492 * SPEC (2.2) "The {final} of the {base type definition} must not
16493 * contain extension"
16494 * NOTE that this is the same as (1.1).
16495 */
16496 xmlSchemaPCustomErr(ctxt,
16497 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16498 WXS_BASIC_CAST type, NULL,
16499 "The 'final' of the base type definition "
16500 "contains 'extension'", NULL);
16501 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16502 }
16503 }
16504 return (0);
16505 }
16506
16507 /**
16508 * xmlSchemaCheckDerivationOKRestriction:
16509 * @ctxt: the schema parser context
16510 * @type: the complex type definition
16511 *
16512 * (3.4.6) Constraints on Complex Type Definition Schema Components
16513 * Schema Component Constraint:
16514 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16515 *
16516 * STATUS:
16517 * missing:
16518 * (5.4.2) ???
16519 *
16520 * ATTENTION:
16521 * In XML Schema 1.1 this will be:
16522 * Validation Rule: Checking complex type subsumption
16523 *
16524 * Returns 0 if the constraints are satisfied, a positive
16525 * error code if not and -1 if an internal error occurred.
16526 */
16527 static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16528 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16529 xmlSchemaTypePtr type)
16530 {
16531 xmlSchemaTypePtr base;
16532
16533 /*
16534 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16535 * temporarily only.
16536 */
16537 base = type->baseType;
16538 if (! WXS_IS_COMPLEX(base)) {
16539 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16540 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16541 type->node, WXS_BASIC_CAST type,
16542 "The base type must be a complex type", NULL, NULL);
16543 return(ctxt->err);
16544 }
16545 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16546 /*
16547 * SPEC (1) "The {base type definition} must be a complex type
16548 * definition whose {final} does not contain restriction."
16549 */
16550 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16551 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16552 type->node, WXS_BASIC_CAST type,
16553 "The 'final' of the base type definition "
16554 "contains 'restriction'", NULL, NULL);
16555 return (ctxt->err);
16556 }
16557 /*
16558 * SPEC (2), (3) and (4)
16559 * Those are handled in a separate function, since the
16560 * same constraints are needed for redefinition of
16561 * attribute groups as well.
16562 */
16563 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16564 XML_SCHEMA_ACTION_DERIVE,
16565 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16566 type->attrUses, base->attrUses,
16567 type->attributeWildcard,
16568 base->attributeWildcard) == -1)
16569 {
16570 return(-1);
16571 }
16572 /*
16573 * SPEC (5) "One of the following must be true:"
16574 */
16575 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16576 /*
16577 * SPEC (5.1) "The {base type definition} must be the
16578 * `ur-type definition`."
16579 * PASS
16580 */
16581 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16582 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16583 /*
16584 * SPEC (5.2.1) "The {content type} of the complex type definition
16585 * must be a simple type definition"
16586 *
16587 * SPEC (5.2.2) "One of the following must be true:"
16588 */
16589 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16590 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16591 {
16592 int err;
16593 /*
16594 * SPEC (5.2.2.1) "The {content type} of the {base type
16595 * definition} must be a simple type definition from which
16596 * the {content type} is validly derived given the empty
16597 * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16598 *
16599 * ATTENTION TODO: This seems not needed if the type implicitly
16600 * derived from the base type.
16601 *
16602 */
16603 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16604 type->contentTypeDef, base->contentTypeDef, 0);
16605 if (err != 0) {
16606 xmlChar *strA = NULL, *strB = NULL;
16607
16608 if (err == -1)
16609 return(-1);
16610 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16611 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16612 NULL, WXS_BASIC_CAST type,
16613 "The {content type} %s is not validly derived from the "
16614 "base type's {content type} %s",
16615 xmlSchemaGetComponentDesignation(&strA,
16616 type->contentTypeDef),
16617 xmlSchemaGetComponentDesignation(&strB,
16618 base->contentTypeDef));
16619 FREE_AND_NULL(strA);
16620 FREE_AND_NULL(strB);
16621 return(ctxt->err);
16622 }
16623 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16624 (xmlSchemaIsParticleEmptiable(
16625 (xmlSchemaParticlePtr) base->subtypes))) {
16626 /*
16627 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16628 * and have a particle which is `emptiable` as defined in
16629 * Particle Emptiable ($3.9.6)."
16630 * PASS
16631 */
16632 } else {
16633 xmlSchemaPCustomErr(ctxt,
16634 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16635 WXS_BASIC_CAST type, NULL,
16636 "The content type of the base type must be either "
16637 "a simple type or 'mixed' and an emptiable particle", NULL);
16638 return (ctxt->err);
16639 }
16640 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16641 /*
16642 * SPEC (5.3.1) "The {content type} of the complex type itself must
16643 * be empty"
16644 */
16645 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16646 /*
16647 * SPEC (5.3.2.1) "The {content type} of the {base type
16648 * definition} must also be empty."
16649 * PASS
16650 */
16651 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16652 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16653 xmlSchemaIsParticleEmptiable(
16654 (xmlSchemaParticlePtr) base->subtypes)) {
16655 /*
16656 * SPEC (5.3.2.2) "The {content type} of the {base type
16657 * definition} must be elementOnly or mixed and have a particle
16658 * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16659 * PASS
16660 */
16661 } else {
16662 xmlSchemaPCustomErr(ctxt,
16663 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16664 WXS_BASIC_CAST type, NULL,
16665 "The content type of the base type must be either "
16666 "empty or 'mixed' (or 'elements-only') and an emptiable "
16667 "particle", NULL);
16668 return (ctxt->err);
16669 }
16670 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16671 WXS_HAS_MIXED_CONTENT(type)) {
16672 /*
16673 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16674 * itself must be element-only"
16675 */
16676 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16677 /*
16678 * SPEC (5.4.1.2) "The {content type} of the complex type
16679 * definition itself and of the {base type definition} must be
16680 * mixed"
16681 */
16682 xmlSchemaPCustomErr(ctxt,
16683 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16684 WXS_BASIC_CAST type, NULL,
16685 "If the content type is 'mixed', then the content type of the "
16686 "base type must also be 'mixed'", NULL);
16687 return (ctxt->err);
16688 }
16689 /*
16690 * SPEC (5.4.2) "The particle of the complex type definition itself
16691 * must be a `valid restriction` of the particle of the {content
16692 * type} of the {base type definition} as defined in Particle Valid
16693 * (Restriction) ($3.9.6).
16694 *
16695 * URGENT TODO: (5.4.2)
16696 */
16697 } else {
16698 xmlSchemaPCustomErr(ctxt,
16699 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16700 WXS_BASIC_CAST type, NULL,
16701 "The type is not a valid restriction of its base type", NULL);
16702 return (ctxt->err);
16703 }
16704 return (0);
16705 }
16706
16707 /**
16708 * xmlSchemaCheckCTComponent:
16709 * @ctxt: the schema parser context
16710 * @type: the complex type definition
16711 *
16712 * (3.4.6) Constraints on Complex Type Definition Schema Components
16713 *
16714 * Returns 0 if the constraints are satisfied, a positive
16715 * error code if not and -1 if an internal error occurred.
16716 */
16717 static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16718 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16719 xmlSchemaTypePtr type)
16720 {
16721 int ret;
16722 /*
16723 * Complex Type Definition Properties Correct
16724 */
16725 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16726 if (ret != 0)
16727 return (ret);
16728 if (WXS_IS_EXTENSION(type))
16729 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16730 else
16731 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16732 return (ret);
16733 }
16734
16735 /**
16736 * xmlSchemaCheckSRCCT:
16737 * @ctxt: the schema parser context
16738 * @type: the complex type definition
16739 *
16740 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16741 * Schema Representation Constraint:
16742 * Complex Type Definition Representation OK (src-ct)
16743 *
16744 * Returns 0 if the constraints are satisfied, a positive
16745 * error code if not and -1 if an internal error occurred.
16746 */
16747 static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16748 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16749 xmlSchemaTypePtr type)
16750 {
16751 xmlSchemaTypePtr base;
16752 int ret = 0;
16753
16754 /*
16755 * TODO: Adjust the error codes here, as I used
16756 * XML_SCHEMAP_SRC_CT_1 only yet.
16757 */
16758 base = type->baseType;
16759 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16760 /*
16761 * 1 If the <complexContent> alternative is chosen, the type definition
16762 * `resolved` to by the `actual value` of the base [attribute]
16763 * must be a complex type definition;
16764 */
16765 if (! WXS_IS_COMPLEX(base)) {
16766 xmlChar *str = NULL;
16767 xmlSchemaPCustomErr(ctxt,
16768 XML_SCHEMAP_SRC_CT_1,
16769 WXS_BASIC_CAST type, type->node,
16770 "If using <complexContent>, the base type is expected to be "
16771 "a complex type. The base type '%s' is a simple type",
16772 xmlSchemaFormatQName(&str, base->targetNamespace,
16773 base->name));
16774 FREE_AND_NULL(str)
16775 return (XML_SCHEMAP_SRC_CT_1);
16776 }
16777 } else {
16778 /*
16779 * SPEC
16780 * 2 If the <simpleContent> alternative is chosen, all of the
16781 * following must be true:
16782 * 2.1 The type definition `resolved` to by the `actual value` of the
16783 * base [attribute] must be one of the following:
16784 */
16785 if (WXS_IS_SIMPLE(base)) {
16786 if (WXS_IS_EXTENSION(type) == 0) {
16787 xmlChar *str = NULL;
16788 /*
16789 * 2.1.3 only if the <extension> alternative is also
16790 * chosen, a simple type definition.
16791 */
16792 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16793 xmlSchemaPCustomErr(ctxt,
16794 XML_SCHEMAP_SRC_CT_1,
16795 WXS_BASIC_CAST type, NULL,
16796 "If using <simpleContent> and <restriction>, the base "
16797 "type must be a complex type. The base type '%s' is "
16798 "a simple type",
16799 xmlSchemaFormatQName(&str, base->targetNamespace,
16800 base->name));
16801 FREE_AND_NULL(str)
16802 return (XML_SCHEMAP_SRC_CT_1);
16803 }
16804 } else {
16805 /* Base type is a complex type. */
16806 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16807 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16808 /*
16809 * 2.1.1 a complex type definition whose {content type} is a
16810 * simple type definition;
16811 * PASS
16812 */
16813 if (base->contentTypeDef == NULL) {
16814 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16815 WXS_BASIC_CAST type, NULL,
16816 "Internal error: xmlSchemaCheckSRCCT, "
16817 "'%s', base type has no content type",
16818 type->name);
16819 return (-1);
16820 }
16821 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16822 (WXS_IS_RESTRICTION(type))) {
16823
16824 /*
16825 * 2.1.2 only if the <restriction> alternative is also
16826 * chosen, a complex type definition whose {content type}
16827 * is mixed and a particle emptiable.
16828 */
16829 if (! xmlSchemaIsParticleEmptiable(
16830 (xmlSchemaParticlePtr) base->subtypes)) {
16831 ret = XML_SCHEMAP_SRC_CT_1;
16832 } else
16833 /*
16834 * Attention: at this point the <simpleType> child is in
16835 * ->contentTypeDef (put there during parsing).
16836 */
16837 if (type->contentTypeDef == NULL) {
16838 xmlChar *str = NULL;
16839 /*
16840 * 2.2 If clause 2.1.2 above is satisfied, then there
16841 * must be a <simpleType> among the [children] of
16842 * <restriction>.
16843 */
16844 /* TODO: Change error code to ..._SRC_CT_2_2. */
16845 xmlSchemaPCustomErr(ctxt,
16846 XML_SCHEMAP_SRC_CT_1,
16847 WXS_BASIC_CAST type, NULL,
16848 "A <simpleType> is expected among the children "
16849 "of <restriction>, if <simpleContent> is used and "
16850 "the base type '%s' is a complex type",
16851 xmlSchemaFormatQName(&str, base->targetNamespace,
16852 base->name));
16853 FREE_AND_NULL(str)
16854 return (XML_SCHEMAP_SRC_CT_1);
16855 }
16856 } else {
16857 ret = XML_SCHEMAP_SRC_CT_1;
16858 }
16859 }
16860 if (ret > 0) {
16861 xmlChar *str = NULL;
16862 if (WXS_IS_RESTRICTION(type)) {
16863 xmlSchemaPCustomErr(ctxt,
16864 XML_SCHEMAP_SRC_CT_1,
16865 WXS_BASIC_CAST type, NULL,
16866 "If <simpleContent> and <restriction> is used, the "
16867 "base type must be a simple type or a complex type with "
16868 "mixed content and particle emptiable. The base type "
16869 "'%s' is none of those",
16870 xmlSchemaFormatQName(&str, base->targetNamespace,
16871 base->name));
16872 } else {
16873 xmlSchemaPCustomErr(ctxt,
16874 XML_SCHEMAP_SRC_CT_1,
16875 WXS_BASIC_CAST type, NULL,
16876 "If <simpleContent> and <extension> is used, the "
16877 "base type must be a simple type. The base type '%s' "
16878 "is a complex type",
16879 xmlSchemaFormatQName(&str, base->targetNamespace,
16880 base->name));
16881 }
16882 FREE_AND_NULL(str)
16883 }
16884 }
16885 /*
16886 * SPEC (3) "The corresponding complex type definition component must
16887 * satisfy the conditions set out in Constraints on Complex Type
16888 * Definition Schema Components ($3.4.6);"
16889 * NOTE (3) will be done in xmlSchemaTypeFixup().
16890 */
16891 /*
16892 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16893 * above for {attribute wildcard} is satisfied, the intensional
16894 * intersection must be expressible, as defined in Attribute Wildcard
16895 * Intersection ($3.10.6).
16896 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16897 */
16898 return (ret);
16899 }
16900
16901 #ifdef ENABLE_PARTICLE_RESTRICTION
16902 /**
16903 * xmlSchemaCheckParticleRangeOK:
16904 * @ctxt: the schema parser context
16905 * @type: the complex type definition
16906 *
16907 * (3.9.6) Constraints on Particle Schema Components
16908 * Schema Component Constraint:
16909 * Occurrence Range OK (range-ok)
16910 *
16911 * STATUS: complete
16912 *
16913 * Returns 0 if the constraints are satisfied, a positive
16914 * error code if not and -1 if an internal error occurred.
16915 */
16916 static int
xmlSchemaCheckParticleRangeOK(int rmin,int rmax,int bmin,int bmax)16917 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16918 int bmin, int bmax)
16919 {
16920 if (rmin < bmin)
16921 return (1);
16922 if ((bmax != UNBOUNDED) &&
16923 (rmax > bmax))
16924 return (1);
16925 return (0);
16926 }
16927
16928 /**
16929 * xmlSchemaCheckRCaseNameAndTypeOK:
16930 * @ctxt: the schema parser context
16931 * @r: the restricting element declaration particle
16932 * @b: the base element declaration particle
16933 *
16934 * (3.9.6) Constraints on Particle Schema Components
16935 * Schema Component Constraint:
16936 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16937 * (rcase-NameAndTypeOK)
16938 *
16939 * STATUS:
16940 * MISSING (3.2.3)
16941 * CLARIFY: (3.2.2)
16942 *
16943 * Returns 0 if the constraints are satisfied, a positive
16944 * error code if not and -1 if an internal error occurred.
16945 */
16946 static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16947 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16948 xmlSchemaParticlePtr r,
16949 xmlSchemaParticlePtr b)
16950 {
16951 xmlSchemaElementPtr elemR, elemB;
16952
16953 /* TODO: Error codes (rcase-NameAndTypeOK). */
16954 elemR = (xmlSchemaElementPtr) r->children;
16955 elemB = (xmlSchemaElementPtr) b->children;
16956 /*
16957 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16958 * the same."
16959 */
16960 if ((elemR != elemB) &&
16961 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16962 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16963 return (1);
16964 /*
16965 * SPEC (2) "R's occurrence range is a valid restriction of B's
16966 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16967 */
16968 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16969 b->minOccurs, b->maxOccurs) != 0)
16970 return (1);
16971 /*
16972 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16973 * {scope} are global."
16974 */
16975 if (elemR == elemB)
16976 return (0);
16977 /*
16978 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16979 */
16980 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16981 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16982 return (1);
16983 /*
16984 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16985 * or is not fixed, or R's declaration's {value constraint} is fixed
16986 * with the same value."
16987 */
16988 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16989 ((elemR->value == NULL) ||
16990 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16991 /* TODO: Equality of the initial value or normalized or canonical? */
16992 (! xmlStrEqual(elemR->value, elemB->value))))
16993 return (1);
16994 /*
16995 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16996 * definitions} is a subset of B's declaration's {identity-constraint
16997 * definitions}, if any."
16998 */
16999 if (elemB->idcs != NULL) {
17000 /* TODO */
17001 }
17002 /*
17003 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
17004 * superset of B's declaration's {disallowed substitutions}."
17005 */
17006 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
17007 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
17008 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
17009 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
17010 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
17011 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
17012 return (1);
17013 /*
17014 * SPEC (3.2.5) "R's {type definition} is validly derived given
17015 * {extension, list, union} from B's {type definition}"
17016 *
17017 * BADSPEC TODO: What's the point of adding "list" and "union" to the
17018 * set, if the corresponding constraints handle "restriction" and
17019 * "extension" only?
17020 *
17021 */
17022 {
17023 int set = 0;
17024
17025 set |= SUBSET_EXTENSION;
17026 set |= SUBSET_LIST;
17027 set |= SUBSET_UNION;
17028 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
17029 elemB->subtypes, set) != 0)
17030 return (1);
17031 }
17032 return (0);
17033 }
17034
17035 /**
17036 * xmlSchemaCheckRCaseNSCompat:
17037 * @ctxt: the schema parser context
17038 * @r: the restricting element declaration particle
17039 * @b: the base wildcard particle
17040 *
17041 * (3.9.6) Constraints on Particle Schema Components
17042 * Schema Component Constraint:
17043 * Particle Derivation OK (Elt:Any -- NSCompat)
17044 * (rcase-NSCompat)
17045 *
17046 * STATUS: complete
17047 *
17048 * Returns 0 if the constraints are satisfied, a positive
17049 * error code if not and -1 if an internal error occurred.
17050 */
17051 static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17052 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
17053 xmlSchemaParticlePtr r,
17054 xmlSchemaParticlePtr b)
17055 {
17056 /* TODO:Error codes (rcase-NSCompat). */
17057 /*
17058 * SPEC "For an element declaration particle to be a `valid restriction`
17059 * of a wildcard particle all of the following must be true:"
17060 *
17061 * SPEC (1) "The element declaration's {target namespace} is `valid`
17062 * with respect to the wildcard's {namespace constraint} as defined by
17063 * Wildcard allows Namespace Name ($3.10.4)."
17064 */
17065 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
17066 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
17067 return (1);
17068 /*
17069 * SPEC (2) "R's occurrence range is a valid restriction of B's
17070 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17071 */
17072 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17073 b->minOccurs, b->maxOccurs) != 0)
17074 return (1);
17075
17076 return (0);
17077 }
17078
17079 /**
17080 * xmlSchemaCheckRCaseRecurseAsIfGroup:
17081 * @ctxt: the schema parser context
17082 * @r: the restricting element declaration particle
17083 * @b: the base model group particle
17084 *
17085 * (3.9.6) Constraints on Particle Schema Components
17086 * Schema Component Constraint:
17087 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
17088 * (rcase-RecurseAsIfGroup)
17089 *
17090 * STATUS: TODO
17091 *
17092 * Returns 0 if the constraints are satisfied, a positive
17093 * error code if not and -1 if an internal error occurred.
17094 */
17095 static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17096 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
17097 xmlSchemaParticlePtr r,
17098 xmlSchemaParticlePtr b)
17099 {
17100 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
17101 TODO
17102 return (0);
17103 }
17104
17105 /**
17106 * xmlSchemaCheckRCaseNSSubset:
17107 * @ctxt: the schema parser context
17108 * @r: the restricting wildcard particle
17109 * @b: the base wildcard particle
17110 *
17111 * (3.9.6) Constraints on Particle Schema Components
17112 * Schema Component Constraint:
17113 * Particle Derivation OK (Any:Any -- NSSubset)
17114 * (rcase-NSSubset)
17115 *
17116 * STATUS: complete
17117 *
17118 * Returns 0 if the constraints are satisfied, a positive
17119 * error code if not and -1 if an internal error occurred.
17120 */
17121 static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b,int isAnyTypeBase)17122 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
17123 xmlSchemaParticlePtr r,
17124 xmlSchemaParticlePtr b,
17125 int isAnyTypeBase)
17126 {
17127 /* TODO: Error codes (rcase-NSSubset). */
17128 /*
17129 * SPEC (1) "R's occurrence range is a valid restriction of B's
17130 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17131 */
17132 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17133 b->minOccurs, b->maxOccurs))
17134 return (1);
17135 /*
17136 * SPEC (2) "R's {namespace constraint} must be an intensional subset
17137 * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17138 */
17139 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17140 (xmlSchemaWildcardPtr) b->children))
17141 return (1);
17142 /*
17143 * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17144 * definition`, R's {process contents} must be identical to or stronger
17145 * than B's {process contents}, where strict is stronger than lax is
17146 * stronger than skip."
17147 */
17148 if (! isAnyTypeBase) {
17149 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17150 ((xmlSchemaWildcardPtr) b->children)->processContents)
17151 return (1);
17152 }
17153
17154 return (0);
17155 }
17156
17157 /**
17158 * xmlSchemaCheckCOSParticleRestrict:
17159 * @ctxt: the schema parser context
17160 * @type: the complex type definition
17161 *
17162 * (3.9.6) Constraints on Particle Schema Components
17163 * Schema Component Constraint:
17164 * Particle Valid (Restriction) (cos-particle-restrict)
17165 *
17166 * STATUS: TODO
17167 *
17168 * Returns 0 if the constraints are satisfied, a positive
17169 * error code if not and -1 if an internal error occurred.
17170 */
17171 static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17172 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17173 xmlSchemaParticlePtr r,
17174 xmlSchemaParticlePtr b)
17175 {
17176 int ret = 0;
17177
17178 /*part = WXS_TYPE_PARTICLE(type);
17179 basePart = WXS_TYPE_PARTICLE(base);
17180 */
17181
17182 TODO
17183
17184 /*
17185 * SPEC (1) "They are the same particle."
17186 */
17187 if (r == b)
17188 return (0);
17189
17190
17191 return (0);
17192 }
17193
17194 #if 0
17195 /**
17196 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17197 * @ctxt: the schema parser context
17198 * @r: the model group particle
17199 * @b: the base wildcard particle
17200 *
17201 * (3.9.6) Constraints on Particle Schema Components
17202 * Schema Component Constraint:
17203 * Particle Derivation OK (All/Choice/Sequence:Any --
17204 * NSRecurseCheckCardinality)
17205 * (rcase-NSRecurseCheckCardinality)
17206 *
17207 * STATUS: TODO: subst-groups
17208 *
17209 * Returns 0 if the constraints are satisfied, a positive
17210 * error code if not and -1 if an internal error occurred.
17211 */
17212 static int
17213 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17214 xmlSchemaParticlePtr r,
17215 xmlSchemaParticlePtr b)
17216 {
17217 xmlSchemaParticlePtr part;
17218 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17219 if ((r->children == NULL) || (r->children->children == NULL))
17220 return (-1);
17221 /*
17222 * SPEC "For a group particle to be a `valid restriction` of a
17223 * wildcard particle..."
17224 *
17225 * SPEC (1) "Every member of the {particles} of the group is a `valid
17226 * restriction` of the wildcard as defined by
17227 * Particle Valid (Restriction) ($3.9.6)."
17228 */
17229 part = (xmlSchemaParticlePtr) r->children->children;
17230 do {
17231 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17232 return (1);
17233 part = (xmlSchemaParticlePtr) part->next;
17234 } while (part != NULL);
17235 /*
17236 * SPEC (2) "The effective total range of the group [...] is a
17237 * valid restriction of B's occurrence range as defined by
17238 * Occurrence Range OK ($3.9.6)."
17239 */
17240 if (xmlSchemaCheckParticleRangeOK(
17241 xmlSchemaGetParticleTotalRangeMin(r),
17242 xmlSchemaGetParticleTotalRangeMax(r),
17243 b->minOccurs, b->maxOccurs) != 0)
17244 return (1);
17245 return (0);
17246 }
17247 #endif
17248
17249 /**
17250 * xmlSchemaCheckRCaseRecurse:
17251 * @ctxt: the schema parser context
17252 * @r: the <all> or <sequence> model group particle
17253 * @b: the base <all> or <sequence> model group particle
17254 *
17255 * (3.9.6) Constraints on Particle Schema Components
17256 * Schema Component Constraint:
17257 * Particle Derivation OK (All:All,Sequence:Sequence --
17258 Recurse)
17259 * (rcase-Recurse)
17260 *
17261 * STATUS: ?
17262 * TODO: subst-groups
17263 *
17264 * Returns 0 if the constraints are satisfied, a positive
17265 * error code if not and -1 if an internal error occurred.
17266 */
17267 static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17268 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17269 xmlSchemaParticlePtr r,
17270 xmlSchemaParticlePtr b)
17271 {
17272 /* xmlSchemaParticlePtr part; */
17273 /* TODO: Error codes (rcase-Recurse). */
17274 if ((r->children == NULL) || (b->children == NULL) ||
17275 (r->children->type != b->children->type))
17276 return (-1);
17277 /*
17278 * SPEC "For an all or sequence group particle to be a `valid
17279 * restriction` of another group particle with the same {compositor}..."
17280 *
17281 * SPEC (1) "R's occurrence range is a valid restriction of B's
17282 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17283 */
17284 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17285 b->minOccurs, b->maxOccurs))
17286 return (1);
17287
17288
17289 return (0);
17290 }
17291
17292 #endif
17293
17294 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17295 xmlSchemaPCustomErrExt(pctxt, \
17296 XML_SCHEMAP_INVALID_FACET_VALUE, \
17297 WXS_BASIC_CAST fac1, fac1->node, \
17298 "It is an error for both '%s' and '%s' to be specified on the "\
17299 "same type definition", \
17300 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17301 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17302
17303 #define FACET_RESTR_ERR(fac1, msg) \
17304 xmlSchemaPCustomErr(pctxt, \
17305 XML_SCHEMAP_INVALID_FACET_VALUE, \
17306 WXS_BASIC_CAST fac1, fac1->node, \
17307 msg, NULL);
17308
17309 #define FACET_RESTR_FIXED_ERR(fac) \
17310 xmlSchemaPCustomErr(pctxt, \
17311 XML_SCHEMAP_INVALID_FACET_VALUE, \
17312 WXS_BASIC_CAST fac, fac->node, \
17313 "The base type's facet is 'fixed', thus the value must not " \
17314 "differ", NULL);
17315
17316 static void
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,xmlSchemaFacetPtr facet1,xmlSchemaFacetPtr facet2,int lessGreater,int orEqual,int ofBase)17317 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17318 xmlSchemaFacetPtr facet1,
17319 xmlSchemaFacetPtr facet2,
17320 int lessGreater,
17321 int orEqual,
17322 int ofBase)
17323 {
17324 xmlChar *msg = NULL;
17325
17326 msg = xmlStrdup(BAD_CAST "'");
17327 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17328 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17329 if (lessGreater == 0)
17330 msg = xmlStrcat(msg, BAD_CAST " equal to");
17331 if (lessGreater == 1)
17332 msg = xmlStrcat(msg, BAD_CAST " greater than");
17333 else
17334 msg = xmlStrcat(msg, BAD_CAST " less than");
17335
17336 if (orEqual)
17337 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17338 msg = xmlStrcat(msg, BAD_CAST " '");
17339 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17340 if (ofBase)
17341 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17342 else
17343 msg = xmlStrcat(msg, BAD_CAST "'");
17344
17345 xmlSchemaPCustomErr(pctxt,
17346 XML_SCHEMAP_INVALID_FACET_VALUE,
17347 WXS_BASIC_CAST facet1, NULL,
17348 (const char *) msg, NULL);
17349
17350 if (msg != NULL)
17351 xmlFree(msg);
17352 }
17353
17354 /*
17355 * xmlSchemaDeriveAndValidateFacets:
17356 *
17357 * Schema Component Constraint: Simple Type Restriction (Facets)
17358 * (st-restrict-facets)
17359 */
17360 static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17361 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17362 xmlSchemaTypePtr type)
17363 {
17364 xmlSchemaTypePtr base = type->baseType;
17365 xmlSchemaFacetLinkPtr link, cur, last = NULL;
17366 xmlSchemaFacetPtr facet, bfacet,
17367 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17368 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17369 fmininc = NULL, fmaxinc = NULL,
17370 fminexc = NULL, fmaxexc = NULL,
17371 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17372 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17373 bfmininc = NULL, bfmaxinc = NULL,
17374 bfminexc = NULL, bfmaxexc = NULL;
17375 int res; /* err = 0, fixedErr; */
17376
17377 /*
17378 * SPEC st-restrict-facets 1:
17379 * "The {variety} of R is the same as that of B."
17380 */
17381 /*
17382 * SPEC st-restrict-facets 2:
17383 * "If {variety} is atomic, the {primitive type definition}
17384 * of R is the same as that of B."
17385 *
17386 * NOTE: we leave 1 & 2 out for now, since this will be
17387 * satisfied by the derivation process.
17388 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17389 */
17390 /*
17391 * SPEC st-restrict-facets 3:
17392 * "The {facets} of R are the union of S and the {facets}
17393 * of B, eliminating duplicates. To eliminate duplicates,
17394 * when a facet of the same kind occurs in both S and the
17395 * {facets} of B, the one in the {facets} of B is not
17396 * included, with the exception of enumeration and pattern
17397 * facets, for which multiple occurrences with distinct values
17398 * are allowed."
17399 */
17400
17401 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17402 return (0);
17403
17404 last = type->facetSet;
17405 if (last != NULL)
17406 while (last->next != NULL)
17407 last = last->next;
17408
17409 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17410 facet = cur->facet;
17411 switch (facet->type) {
17412 case XML_SCHEMA_FACET_LENGTH:
17413 flength = facet; break;
17414 case XML_SCHEMA_FACET_MINLENGTH:
17415 fminlen = facet; break;
17416 case XML_SCHEMA_FACET_MININCLUSIVE:
17417 fmininc = facet; break;
17418 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17419 fminexc = facet; break;
17420 case XML_SCHEMA_FACET_MAXLENGTH:
17421 fmaxlen = facet; break;
17422 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17423 fmaxinc = facet; break;
17424 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17425 fmaxexc = facet; break;
17426 case XML_SCHEMA_FACET_TOTALDIGITS:
17427 ftotdig = facet; break;
17428 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17429 ffracdig = facet; break;
17430 default:
17431 break;
17432 }
17433 }
17434 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17435 facet = cur->facet;
17436 switch (facet->type) {
17437 case XML_SCHEMA_FACET_LENGTH:
17438 bflength = facet; break;
17439 case XML_SCHEMA_FACET_MINLENGTH:
17440 bfminlen = facet; break;
17441 case XML_SCHEMA_FACET_MININCLUSIVE:
17442 bfmininc = facet; break;
17443 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17444 bfminexc = facet; break;
17445 case XML_SCHEMA_FACET_MAXLENGTH:
17446 bfmaxlen = facet; break;
17447 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17448 bfmaxinc = facet; break;
17449 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17450 bfmaxexc = facet; break;
17451 case XML_SCHEMA_FACET_TOTALDIGITS:
17452 bftotdig = facet; break;
17453 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17454 bffracdig = facet; break;
17455 default:
17456 break;
17457 }
17458 }
17459 /*
17460 * length and minLength or maxLength (2.2) + (3.2)
17461 */
17462 if (flength && (fminlen || fmaxlen)) {
17463 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17464 "either of 'minLength' or 'maxLength' to be specified on "
17465 "the same type definition")
17466 }
17467 /*
17468 * Mutual exclusions in the same derivation step.
17469 */
17470 if ((fmaxinc) && (fmaxexc)) {
17471 /*
17472 * SCC "maxInclusive and maxExclusive"
17473 */
17474 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17475 }
17476 if ((fmininc) && (fminexc)) {
17477 /*
17478 * SCC "minInclusive and minExclusive"
17479 */
17480 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17481 }
17482
17483 if (flength && bflength) {
17484 /*
17485 * SCC "length valid restriction"
17486 * The values have to be equal.
17487 */
17488 res = xmlSchemaCompareValues(flength->val, bflength->val);
17489 if (res == -2)
17490 goto internal_error;
17491 if (res != 0)
17492 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17493 if ((res != 0) && (bflength->fixed)) {
17494 FACET_RESTR_FIXED_ERR(flength)
17495 }
17496
17497 }
17498 if (fminlen && bfminlen) {
17499 /*
17500 * SCC "minLength valid restriction"
17501 * minLength >= BASE minLength
17502 */
17503 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17504 if (res == -2)
17505 goto internal_error;
17506 if (res == -1)
17507 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17508 if ((res != 0) && (bfminlen->fixed)) {
17509 FACET_RESTR_FIXED_ERR(fminlen)
17510 }
17511 }
17512 if (fmaxlen && bfmaxlen) {
17513 /*
17514 * SCC "maxLength valid restriction"
17515 * maxLength <= BASE minLength
17516 */
17517 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17518 if (res == -2)
17519 goto internal_error;
17520 if (res == 1)
17521 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17522 if ((res != 0) && (bfmaxlen->fixed)) {
17523 FACET_RESTR_FIXED_ERR(fmaxlen)
17524 }
17525 }
17526 /*
17527 * SCC "length and minLength or maxLength"
17528 */
17529 if (! flength)
17530 flength = bflength;
17531 if (flength) {
17532 if (! fminlen)
17533 fminlen = bfminlen;
17534 if (fminlen) {
17535 /* (1.1) length >= minLength */
17536 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17537 if (res == -2)
17538 goto internal_error;
17539 if (res == -1)
17540 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17541 }
17542 if (! fmaxlen)
17543 fmaxlen = bfmaxlen;
17544 if (fmaxlen) {
17545 /* (2.1) length <= maxLength */
17546 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17547 if (res == -2)
17548 goto internal_error;
17549 if (res == 1)
17550 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17551 }
17552 }
17553 if (fmaxinc) {
17554 /*
17555 * "maxInclusive"
17556 */
17557 if (fmininc) {
17558 /* SCC "maxInclusive >= minInclusive" */
17559 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17560 if (res == -2)
17561 goto internal_error;
17562 if (res == -1) {
17563 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17564 }
17565 }
17566 /*
17567 * SCC "maxInclusive valid restriction"
17568 */
17569 if (bfmaxinc) {
17570 /* maxInclusive <= BASE maxInclusive */
17571 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17572 if (res == -2)
17573 goto internal_error;
17574 if (res == 1)
17575 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17576 if ((res != 0) && (bfmaxinc->fixed)) {
17577 FACET_RESTR_FIXED_ERR(fmaxinc)
17578 }
17579 }
17580 if (bfmaxexc) {
17581 /* maxInclusive < BASE maxExclusive */
17582 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17583 if (res == -2)
17584 goto internal_error;
17585 if (res != -1) {
17586 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17587 }
17588 }
17589 if (bfmininc) {
17590 /* maxInclusive >= BASE minInclusive */
17591 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17592 if (res == -2)
17593 goto internal_error;
17594 if (res == -1) {
17595 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17596 }
17597 }
17598 if (bfminexc) {
17599 /* maxInclusive > BASE minExclusive */
17600 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17601 if (res == -2)
17602 goto internal_error;
17603 if (res != 1) {
17604 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17605 }
17606 }
17607 }
17608 if (fmaxexc) {
17609 /*
17610 * "maxExclusive >= minExclusive"
17611 */
17612 if (fminexc) {
17613 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17614 if (res == -2)
17615 goto internal_error;
17616 if (res == -1) {
17617 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17618 }
17619 }
17620 /*
17621 * "maxExclusive valid restriction"
17622 */
17623 if (bfmaxexc) {
17624 /* maxExclusive <= BASE maxExclusive */
17625 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17626 if (res == -2)
17627 goto internal_error;
17628 if (res == 1) {
17629 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17630 }
17631 if ((res != 0) && (bfmaxexc->fixed)) {
17632 FACET_RESTR_FIXED_ERR(fmaxexc)
17633 }
17634 }
17635 if (bfmaxinc) {
17636 /* maxExclusive <= BASE maxInclusive */
17637 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17638 if (res == -2)
17639 goto internal_error;
17640 if (res == 1) {
17641 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17642 }
17643 }
17644 if (bfmininc) {
17645 /* maxExclusive > BASE minInclusive */
17646 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17647 if (res == -2)
17648 goto internal_error;
17649 if (res != 1) {
17650 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17651 }
17652 }
17653 if (bfminexc) {
17654 /* maxExclusive > BASE minExclusive */
17655 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17656 if (res == -2)
17657 goto internal_error;
17658 if (res != 1) {
17659 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17660 }
17661 }
17662 }
17663 if (fminexc) {
17664 /*
17665 * "minExclusive < maxInclusive"
17666 */
17667 if (fmaxinc) {
17668 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17669 if (res == -2)
17670 goto internal_error;
17671 if (res != -1) {
17672 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17673 }
17674 }
17675 /*
17676 * "minExclusive valid restriction"
17677 */
17678 if (bfminexc) {
17679 /* minExclusive >= BASE minExclusive */
17680 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17681 if (res == -2)
17682 goto internal_error;
17683 if (res == -1) {
17684 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17685 }
17686 if ((res != 0) && (bfminexc->fixed)) {
17687 FACET_RESTR_FIXED_ERR(fminexc)
17688 }
17689 }
17690 if (bfmaxinc) {
17691 /* minExclusive <= BASE maxInclusive */
17692 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17693 if (res == -2)
17694 goto internal_error;
17695 if (res == 1) {
17696 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17697 }
17698 }
17699 if (bfmininc) {
17700 /* minExclusive >= BASE minInclusive */
17701 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17702 if (res == -2)
17703 goto internal_error;
17704 if (res == -1) {
17705 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17706 }
17707 }
17708 if (bfmaxexc) {
17709 /* minExclusive < BASE maxExclusive */
17710 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17711 if (res == -2)
17712 goto internal_error;
17713 if (res != -1) {
17714 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17715 }
17716 }
17717 }
17718 if (fmininc) {
17719 /*
17720 * "minInclusive < maxExclusive"
17721 */
17722 if (fmaxexc) {
17723 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17724 if (res == -2)
17725 goto internal_error;
17726 if (res != -1) {
17727 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17728 }
17729 }
17730 /*
17731 * "minExclusive valid restriction"
17732 */
17733 if (bfmininc) {
17734 /* minInclusive >= BASE minInclusive */
17735 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17736 if (res == -2)
17737 goto internal_error;
17738 if (res == -1) {
17739 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17740 }
17741 if ((res != 0) && (bfmininc->fixed)) {
17742 FACET_RESTR_FIXED_ERR(fmininc)
17743 }
17744 }
17745 if (bfmaxinc) {
17746 /* minInclusive <= BASE maxInclusive */
17747 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17748 if (res == -2)
17749 goto internal_error;
17750 if (res == 1) {
17751 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17752 }
17753 }
17754 if (bfminexc) {
17755 /* minInclusive > BASE minExclusive */
17756 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17757 if (res == -2)
17758 goto internal_error;
17759 if (res != 1)
17760 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17761 }
17762 if (bfmaxexc) {
17763 /* minInclusive < BASE maxExclusive */
17764 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17765 if (res == -2)
17766 goto internal_error;
17767 if (res != -1)
17768 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17769 }
17770 }
17771 if (ftotdig && bftotdig) {
17772 /*
17773 * SCC " totalDigits valid restriction"
17774 * totalDigits <= BASE totalDigits
17775 */
17776 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17777 if (res == -2)
17778 goto internal_error;
17779 if (res == 1)
17780 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17781 -1, 1, 1);
17782 if ((res != 0) && (bftotdig->fixed)) {
17783 FACET_RESTR_FIXED_ERR(ftotdig)
17784 }
17785 }
17786 if (ffracdig && bffracdig) {
17787 /*
17788 * SCC "fractionDigits valid restriction"
17789 * fractionDigits <= BASE fractionDigits
17790 */
17791 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17792 if (res == -2)
17793 goto internal_error;
17794 if (res == 1)
17795 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17796 -1, 1, 1);
17797 if ((res != 0) && (bffracdig->fixed)) {
17798 FACET_RESTR_FIXED_ERR(ffracdig)
17799 }
17800 }
17801 /*
17802 * SCC "fractionDigits less than or equal to totalDigits"
17803 */
17804 if (! ftotdig)
17805 ftotdig = bftotdig;
17806 if (! ffracdig)
17807 ffracdig = bffracdig;
17808 if (ftotdig && ffracdig) {
17809 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17810 if (res == -2)
17811 goto internal_error;
17812 if (res == 1)
17813 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17814 -1, 1, 0);
17815 }
17816 /*
17817 * *Enumerations* won' be added here, since only the first set
17818 * of enumerations in the ancestor-or-self axis is used
17819 * for validation, plus we need to use the base type of those
17820 * enumerations for whitespace.
17821 *
17822 * *Patterns*: won't be add here, since they are ORed at
17823 * type level and ANDed at ancestor level. This will
17824 * happen during validation by walking the base axis
17825 * of the type.
17826 */
17827 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17828 bfacet = cur->facet;
17829 /*
17830 * Special handling of enumerations and patterns.
17831 * TODO: hmm, they should not appear in the set, so remove this.
17832 */
17833 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17834 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17835 continue;
17836 /*
17837 * Search for a duplicate facet in the current type.
17838 */
17839 link = type->facetSet;
17840 /* err = 0; */
17841 /* fixedErr = 0; */
17842 while (link != NULL) {
17843 facet = link->facet;
17844 if (facet->type == bfacet->type) {
17845 switch (facet->type) {
17846 case XML_SCHEMA_FACET_WHITESPACE:
17847 /*
17848 * The whitespace must be stronger.
17849 */
17850 if (facet->whitespace < bfacet->whitespace) {
17851 FACET_RESTR_ERR(facet,
17852 "The 'whitespace' value has to be equal to "
17853 "or stronger than the 'whitespace' value of "
17854 "the base type")
17855 }
17856 if ((bfacet->fixed) &&
17857 (facet->whitespace != bfacet->whitespace)) {
17858 FACET_RESTR_FIXED_ERR(facet)
17859 }
17860 break;
17861 default:
17862 break;
17863 }
17864 /* Duplicate found. */
17865 break;
17866 }
17867 link = link->next;
17868 }
17869 /*
17870 * If no duplicate was found: add the base types's facet
17871 * to the set.
17872 */
17873 if (link == NULL) {
17874 link = (xmlSchemaFacetLinkPtr)
17875 xmlMalloc(sizeof(xmlSchemaFacetLink));
17876 if (link == NULL) {
17877 xmlSchemaPErrMemory(pctxt,
17878 "deriving facets, creating a facet link", NULL);
17879 return (-1);
17880 }
17881 link->facet = cur->facet;
17882 link->next = NULL;
17883 if (last == NULL)
17884 type->facetSet = link;
17885 else
17886 last->next = link;
17887 last = link;
17888 }
17889
17890 }
17891
17892 return (0);
17893 internal_error:
17894 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17895 "an error occurred");
17896 return (-1);
17897 }
17898
17899 static int
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17900 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17901 xmlSchemaTypePtr type)
17902 {
17903 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17904 /*
17905 * The actual value is then formed by replacing any union type
17906 * definition in the `explicit members` with the members of their
17907 * {member type definitions}, in order.
17908 *
17909 * TODO: There's a bug entry at
17910 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17911 * which indicates that we'll keep the union types the future.
17912 */
17913 link = type->memberTypes;
17914 while (link != NULL) {
17915
17916 if (WXS_IS_TYPE_NOT_FIXED(link->type))
17917 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17918
17919 if (WXS_IS_UNION(link->type)) {
17920 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17921 if (subLink != NULL) {
17922 link->type = subLink->type;
17923 if (subLink->next != NULL) {
17924 lastLink = link->next;
17925 subLink = subLink->next;
17926 prevLink = link;
17927 while (subLink != NULL) {
17928 newLink = (xmlSchemaTypeLinkPtr)
17929 xmlMalloc(sizeof(xmlSchemaTypeLink));
17930 if (newLink == NULL) {
17931 xmlSchemaPErrMemory(pctxt, "allocating a type link",
17932 NULL);
17933 return (-1);
17934 }
17935 newLink->type = subLink->type;
17936 prevLink->next = newLink;
17937 prevLink = newLink;
17938 newLink->next = lastLink;
17939
17940 subLink = subLink->next;
17941 }
17942 }
17943 }
17944 }
17945 link = link->next;
17946 }
17947 return (0);
17948 }
17949
17950 static void
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)17951 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17952 {
17953 int has = 0, needVal = 0, normVal = 0;
17954
17955 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17956 if (has) {
17957 needVal = (type->baseType->flags &
17958 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17959 normVal = (type->baseType->flags &
17960 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17961 }
17962 if (type->facets != NULL) {
17963 xmlSchemaFacetPtr fac;
17964
17965 for (fac = type->facets; fac != NULL; fac = fac->next) {
17966 switch (fac->type) {
17967 case XML_SCHEMA_FACET_WHITESPACE:
17968 break;
17969 case XML_SCHEMA_FACET_PATTERN:
17970 normVal = 1;
17971 has = 1;
17972 break;
17973 case XML_SCHEMA_FACET_ENUMERATION:
17974 needVal = 1;
17975 normVal = 1;
17976 has = 1;
17977 break;
17978 default:
17979 has = 1;
17980 break;
17981 }
17982 }
17983 }
17984 if (normVal)
17985 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17986 if (needVal)
17987 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17988 if (has)
17989 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17990
17991 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17992 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17993 /*
17994 * OPTIMIZE VAL TODO: Some facets need a computed value.
17995 */
17996 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17997 (prim->builtInType != XML_SCHEMAS_STRING)) {
17998 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17999 }
18000 }
18001 }
18002
18003 static int
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)18004 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
18005 {
18006
18007
18008 /*
18009 * Evaluate the whitespace-facet value.
18010 */
18011 if (WXS_IS_LIST(type)) {
18012 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18013 return (0);
18014 } else if (WXS_IS_UNION(type))
18015 return (0);
18016
18017 if (type->facetSet != NULL) {
18018 xmlSchemaFacetLinkPtr lin;
18019
18020 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
18021 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
18022 switch (lin->facet->whitespace) {
18023 case XML_SCHEMAS_FACET_PRESERVE:
18024 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18025 break;
18026 case XML_SCHEMAS_FACET_REPLACE:
18027 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18028 break;
18029 case XML_SCHEMAS_FACET_COLLAPSE:
18030 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18031 break;
18032 default:
18033 return (-1);
18034 }
18035 return (0);
18036 }
18037 }
18038 }
18039 /*
18040 * For all `atomic` datatypes other than string (and types `derived`
18041 * by `restriction` from it) the value of whiteSpace is fixed to
18042 * collapse
18043 */
18044 {
18045 xmlSchemaTypePtr anc;
18046
18047 for (anc = type->baseType; anc != NULL &&
18048 anc->builtInType != XML_SCHEMAS_ANYTYPE;
18049 anc = anc->baseType) {
18050
18051 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
18052 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
18053 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18054
18055 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
18056 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
18057 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18058
18059 } else
18060 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18061 break;
18062 }
18063 }
18064 }
18065 return (0);
18066 }
18067
18068 static int
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18069 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
18070 xmlSchemaTypePtr type)
18071 {
18072 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18073 return(0);
18074 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
18075 return(0);
18076 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
18077
18078 if (WXS_IS_LIST(type)) {
18079 /*
18080 * Corresponds to <simpleType><list>...
18081 */
18082 if (type->subtypes == NULL) {
18083 /*
18084 * This one is really needed, so get out.
18085 */
18086 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18087 "list type has no item-type assigned");
18088 return(-1);
18089 }
18090 } else if (WXS_IS_UNION(type)) {
18091 /*
18092 * Corresponds to <simpleType><union>...
18093 */
18094 if (type->memberTypes == NULL) {
18095 /*
18096 * This one is really needed, so get out.
18097 */
18098 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18099 "union type has no member-types assigned");
18100 return(-1);
18101 }
18102 } else {
18103 /*
18104 * Corresponds to <simpleType><restriction>...
18105 */
18106 if (type->baseType == NULL) {
18107 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18108 "type has no base-type assigned");
18109 return(-1);
18110 }
18111 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
18112 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
18113 return(-1);
18114 /*
18115 * Variety
18116 * If the <restriction> alternative is chosen, then the
18117 * {variety} of the {base type definition}.
18118 */
18119 if (WXS_IS_ATOMIC(type->baseType))
18120 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
18121 else if (WXS_IS_LIST(type->baseType)) {
18122 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
18123 /*
18124 * Inherit the itemType.
18125 */
18126 type->subtypes = type->baseType->subtypes;
18127 } else if (WXS_IS_UNION(type->baseType)) {
18128 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
18129 /*
18130 * NOTE that we won't assign the memberTypes of the base,
18131 * since this will make trouble when freeing them; we will
18132 * use a lookup function to access them instead.
18133 */
18134 }
18135 }
18136 return(0);
18137 }
18138
18139 #ifdef DEBUG_TYPE
18140 static void
xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18141 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18142 xmlSchemaTypePtr type)
18143 {
18144 if (type->node != NULL) {
18145 xmlGenericError(xmlGenericErrorContext,
18146 "Type of %s : %s:%d :", name,
18147 type->node->doc->URL,
18148 xmlGetLineNo(type->node));
18149 } else {
18150 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18151 }
18152 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18153 switch (type->contentType) {
18154 case XML_SCHEMA_CONTENT_SIMPLE:
18155 xmlGenericError(xmlGenericErrorContext, "simple\n");
18156 break;
18157 case XML_SCHEMA_CONTENT_ELEMENTS:
18158 xmlGenericError(xmlGenericErrorContext, "elements\n");
18159 break;
18160 case XML_SCHEMA_CONTENT_UNKNOWN:
18161 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18162 break;
18163 case XML_SCHEMA_CONTENT_EMPTY:
18164 xmlGenericError(xmlGenericErrorContext, "empty\n");
18165 break;
18166 case XML_SCHEMA_CONTENT_MIXED:
18167 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18168 type->subtypes))
18169 xmlGenericError(xmlGenericErrorContext,
18170 "mixed as emptiable particle\n");
18171 else
18172 xmlGenericError(xmlGenericErrorContext, "mixed\n");
18173 break;
18174 /* Removed, since not used. */
18175 /*
18176 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18177 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18178 break;
18179 */
18180 case XML_SCHEMA_CONTENT_BASIC:
18181 xmlGenericError(xmlGenericErrorContext, "basic\n");
18182 break;
18183 default:
18184 xmlGenericError(xmlGenericErrorContext,
18185 "not registered !!!\n");
18186 break;
18187 }
18188 }
18189 }
18190 #endif
18191
18192 /*
18193 * 3.14.6 Constraints on Simple Type Definition Schema Components
18194 */
18195 static int
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18196 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18197 xmlSchemaTypePtr type)
18198 {
18199 int res, olderrs = pctxt->nberrors;
18200
18201 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18202 return(-1);
18203
18204 if (! WXS_IS_TYPE_NOT_FIXED(type))
18205 return(0);
18206
18207 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18208 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18209
18210 if (type->baseType == NULL) {
18211 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18212 "missing baseType");
18213 goto exit_failure;
18214 }
18215 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18216 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18217 /*
18218 * If a member type of a union is a union itself, we need to substitute
18219 * that member type for its member types.
18220 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18221 * types in WXS 1.1.
18222 */
18223 if ((type->memberTypes != NULL) &&
18224 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18225 return(-1);
18226 /*
18227 * SPEC src-simple-type 1
18228 * "The corresponding simple type definition, if any, must satisfy
18229 * the conditions set out in Constraints on Simple Type Definition
18230 * Schema Components ($3.14.6)."
18231 */
18232 /*
18233 * Schema Component Constraint: Simple Type Definition Properties Correct
18234 * (st-props-correct)
18235 */
18236 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18237 HFAILURE HERROR
18238 /*
18239 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18240 * (cos-st-restricts)
18241 */
18242 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18243 HFAILURE HERROR
18244 /*
18245 * TODO: Removed the error report, since it got annoying to get an
18246 * extra error report, if anything failed until now.
18247 * Enable this if needed.
18248 *
18249 * xmlSchemaPErr(ctxt, type->node,
18250 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18251 * "Simple type '%s' does not satisfy the constraints "
18252 * "on simple type definitions.\n",
18253 * type->name, NULL);
18254 */
18255 /*
18256 * Schema Component Constraint: Simple Type Restriction (Facets)
18257 * (st-restrict-facets)
18258 */
18259 res = xmlSchemaCheckFacetValues(type, pctxt);
18260 HFAILURE HERROR
18261 if ((type->facetSet != NULL) ||
18262 (type->baseType->facetSet != NULL)) {
18263 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18264 HFAILURE HERROR
18265 }
18266 /*
18267 * Whitespace value.
18268 */
18269 res = xmlSchemaTypeFixupWhitespace(type);
18270 HFAILURE HERROR
18271 xmlSchemaTypeFixupOptimFacets(type);
18272
18273 exit_error:
18274 #ifdef DEBUG_TYPE
18275 xmlSchemaDebugFixedType(pctxt, type);
18276 #endif
18277 if (olderrs != pctxt->nberrors)
18278 return(pctxt->err);
18279 return(0);
18280
18281 exit_failure:
18282 #ifdef DEBUG_TYPE
18283 xmlSchemaDebugFixedType(pctxt, type);
18284 #endif
18285 return(-1);
18286 }
18287
18288 static int
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18289 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18290 xmlSchemaTypePtr type)
18291 {
18292 int res = 0, olderrs = pctxt->nberrors;
18293 xmlSchemaTypePtr baseType = type->baseType;
18294
18295 if (! WXS_IS_TYPE_NOT_FIXED(type))
18296 return(0);
18297 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18298 if (baseType == NULL) {
18299 PERROR_INT("xmlSchemaFixupComplexType",
18300 "missing baseType");
18301 goto exit_failure;
18302 }
18303 /*
18304 * Fixup the base type.
18305 */
18306 if (WXS_IS_TYPE_NOT_FIXED(baseType))
18307 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18308 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18309 /*
18310 * Skip fixup if the base type is invalid.
18311 * TODO: Generate a warning!
18312 */
18313 return(0);
18314 }
18315 /*
18316 * This basically checks if the base type can be derived.
18317 */
18318 res = xmlSchemaCheckSRCCT(pctxt, type);
18319 HFAILURE HERROR
18320 /*
18321 * Fixup the content type.
18322 */
18323 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18324 /*
18325 * Corresponds to <complexType><simpleContent>...
18326 */
18327 if ((WXS_IS_COMPLEX(baseType)) &&
18328 (baseType->contentTypeDef != NULL) &&
18329 (WXS_IS_RESTRICTION(type))) {
18330 xmlSchemaTypePtr contentBase, content;
18331 #ifdef ENABLE_NAMED_LOCALS
18332 char buf[30];
18333 const xmlChar *tmpname;
18334 #endif
18335 /*
18336 * SPEC (1) If <restriction> + base type is <complexType>,
18337 * "whose own {content type} is a simple type..."
18338 */
18339 if (type->contentTypeDef != NULL) {
18340 /*
18341 * SPEC (1.1) "the simple type definition corresponding to the
18342 * <simpleType> among the [children] of <restriction> if there
18343 * is one;"
18344 * Note that this "<simpleType> among the [children]" was put
18345 * into ->contentTypeDef during parsing.
18346 */
18347 contentBase = type->contentTypeDef;
18348 type->contentTypeDef = NULL;
18349 } else {
18350 /*
18351 * (1.2) "...otherwise (<restriction> has no <simpleType>
18352 * among its [children]), the simple type definition which
18353 * is the {content type} of the ... base type."
18354 */
18355 contentBase = baseType->contentTypeDef;
18356 }
18357 /*
18358 * SPEC
18359 * "... a simple type definition which restricts the simple
18360 * type definition identified in clause 1.1 or clause 1.2
18361 * with a set of facet components"
18362 *
18363 * Create the anonymous simple type, which will be the content
18364 * type of the complex type.
18365 */
18366 #ifdef ENABLE_NAMED_LOCALS
18367 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18368 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18369 content = xmlSchemaAddType(pctxt, pctxt->schema,
18370 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18371 type->node, 0);
18372 #else
18373 content = xmlSchemaAddType(pctxt, pctxt->schema,
18374 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18375 type->node, 0);
18376 #endif
18377 if (content == NULL)
18378 goto exit_failure;
18379 /*
18380 * We will use the same node as for the <complexType>
18381 * to have it somehow anchored in the schema doc.
18382 */
18383 content->type = XML_SCHEMA_TYPE_SIMPLE;
18384 content->baseType = contentBase;
18385 /*
18386 * Move the facets, previously anchored on the
18387 * complexType during parsing.
18388 */
18389 content->facets = type->facets;
18390 type->facets = NULL;
18391 content->facetSet = type->facetSet;
18392 type->facetSet = NULL;
18393
18394 type->contentTypeDef = content;
18395 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18396 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18397 /*
18398 * Fixup the newly created type. We don't need to check
18399 * for circularity here.
18400 */
18401 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18402 HFAILURE HERROR
18403 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18404 HFAILURE HERROR
18405
18406 } else if ((WXS_IS_COMPLEX(baseType)) &&
18407 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18408 (WXS_IS_RESTRICTION(type))) {
18409 /*
18410 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18411 * an emptiable particle, then a simple type definition which
18412 * restricts the <restriction>'s <simpleType> child.
18413 */
18414 if ((type->contentTypeDef == NULL) ||
18415 (type->contentTypeDef->baseType == NULL)) {
18416 /*
18417 * TODO: Check if this ever happens.
18418 */
18419 xmlSchemaPCustomErr(pctxt,
18420 XML_SCHEMAP_INTERNAL,
18421 WXS_BASIC_CAST type, NULL,
18422 "Internal error: xmlSchemaTypeFixup, "
18423 "complex type '%s': the <simpleContent><restriction> "
18424 "is missing a <simpleType> child, but was not caught "
18425 "by xmlSchemaCheckSRCCT()", type->name);
18426 goto exit_failure;
18427 }
18428 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18429 /*
18430 * SPEC (3) If <extension> + base is <complexType> with
18431 * <simpleType> content, "...then the {content type} of that
18432 * complex type definition"
18433 */
18434 if (baseType->contentTypeDef == NULL) {
18435 /*
18436 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18437 * should have caught this already.
18438 */
18439 xmlSchemaPCustomErr(pctxt,
18440 XML_SCHEMAP_INTERNAL,
18441 WXS_BASIC_CAST type, NULL,
18442 "Internal error: xmlSchemaTypeFixup, "
18443 "complex type '%s': the <extension>ed base type is "
18444 "a complex type with no simple content type",
18445 type->name);
18446 goto exit_failure;
18447 }
18448 type->contentTypeDef = baseType->contentTypeDef;
18449 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18450 /*
18451 * SPEC (4) <extension> + base is <simpleType>
18452 * "... then that simple type definition"
18453 */
18454 type->contentTypeDef = baseType;
18455 } else {
18456 /*
18457 * TODO: Check if this ever happens.
18458 */
18459 xmlSchemaPCustomErr(pctxt,
18460 XML_SCHEMAP_INTERNAL,
18461 WXS_BASIC_CAST type, NULL,
18462 "Internal error: xmlSchemaTypeFixup, "
18463 "complex type '%s' with <simpleContent>: unhandled "
18464 "derivation case", type->name);
18465 goto exit_failure;
18466 }
18467 } else {
18468 int dummySequence = 0;
18469 xmlSchemaParticlePtr particle =
18470 (xmlSchemaParticlePtr) type->subtypes;
18471 /*
18472 * Corresponds to <complexType><complexContent>...
18473 *
18474 * NOTE that the effective mixed was already set during parsing of
18475 * <complexType> and <complexContent>; its flag value is
18476 * XML_SCHEMAS_TYPE_MIXED.
18477 *
18478 * Compute the "effective content":
18479 * (2.1.1) + (2.1.2) + (2.1.3)
18480 */
18481 if ((particle == NULL) ||
18482 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18483 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18484 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18485 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18486 (particle->minOccurs == 0))) &&
18487 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18488 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18489 /*
18490 * SPEC (2.1.4) "If the `effective mixed` is true, then
18491 * a particle whose properties are as follows:..."
18492 *
18493 * Empty sequence model group with
18494 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18495 * NOTE that we sill assign it the <complexType> node to
18496 * somehow anchor it in the doc.
18497 */
18498 if ((particle == NULL) ||
18499 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18500 /*
18501 * Create the particle.
18502 */
18503 particle = xmlSchemaAddParticle(pctxt,
18504 type->node, 1, 1);
18505 if (particle == NULL)
18506 goto exit_failure;
18507 /*
18508 * Create the model group.
18509 */ /* URGENT TODO: avoid adding to pending items. */
18510 particle->children = (xmlSchemaTreeItemPtr)
18511 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18512 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18513 if (particle->children == NULL)
18514 goto exit_failure;
18515
18516 type->subtypes = (xmlSchemaTypePtr) particle;
18517 }
18518 dummySequence = 1;
18519 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18520 } else {
18521 /*
18522 * SPEC (2.1.5) "otherwise empty"
18523 */
18524 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18525 }
18526 } else {
18527 /*
18528 * SPEC (2.2) "otherwise the particle corresponding to the
18529 * <all>, <choice>, <group> or <sequence> among the
18530 * [children]."
18531 */
18532 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18533 }
18534 /*
18535 * Compute the "content type".
18536 */
18537 if (WXS_IS_RESTRICTION(type)) {
18538 /*
18539 * SPEC (3.1) "If <restriction>..."
18540 * (3.1.1) + (3.1.2) */
18541 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18542 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18543 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18544 }
18545 } else {
18546 /*
18547 * SPEC (3.2) "If <extension>..."
18548 */
18549 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18550 /*
18551 * SPEC (3.2.1)
18552 * "If the `effective content` is empty, then the
18553 * {content type} of the [...] base ..."
18554 */
18555 type->contentType = baseType->contentType;
18556 type->subtypes = baseType->subtypes;
18557 /*
18558 * Fixes bug #347316:
18559 * This is the case when the base type has a simple
18560 * type definition as content.
18561 */
18562 type->contentTypeDef = baseType->contentTypeDef;
18563 /*
18564 * NOTE that the effective mixed is ignored here.
18565 */
18566 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18567 /*
18568 * SPEC (3.2.2)
18569 */
18570 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18571 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18572 } else {
18573 /*
18574 * SPEC (3.2.3)
18575 */
18576 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18577 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18578 /*
18579 * "A model group whose {compositor} is sequence and whose
18580 * {particles} are..."
18581 */
18582 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18583 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18584 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18585 XML_SCHEMA_TYPE_ALL))
18586 {
18587 /*
18588 * SPEC cos-all-limited (1)
18589 */
18590 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18591 /* TODO: error code */
18592 XML_SCHEMAP_COS_ALL_LIMITED,
18593 WXS_ITEM_NODE(type), NULL,
18594 "The type has an 'all' model group in its "
18595 "{content type} and thus cannot be derived from "
18596 "a non-empty type, since this would produce a "
18597 "'sequence' model group containing the 'all' "
18598 "model group; 'all' model groups are not "
18599 "allowed to appear inside other model groups",
18600 NULL, NULL);
18601
18602 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18603 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18604 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18605 XML_SCHEMA_TYPE_ALL))
18606 {
18607 /*
18608 * SPEC cos-all-limited (1)
18609 */
18610 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18611 /* TODO: error code */
18612 XML_SCHEMAP_COS_ALL_LIMITED,
18613 WXS_ITEM_NODE(type), NULL,
18614 "A type cannot be derived by extension from a type "
18615 "which has an 'all' model group in its "
18616 "{content type}, since this would produce a "
18617 "'sequence' model group containing the 'all' "
18618 "model group; 'all' model groups are not "
18619 "allowed to appear inside other model groups",
18620 NULL, NULL);
18621
18622 } else if ((!dummySequence) && (baseType->subtypes != NULL)) {
18623 xmlSchemaTreeItemPtr effectiveContent =
18624 (xmlSchemaTreeItemPtr) type->subtypes;
18625 /*
18626 * Create the particle.
18627 */
18628 particle = xmlSchemaAddParticle(pctxt,
18629 type->node, 1, 1);
18630 if (particle == NULL)
18631 goto exit_failure;
18632 /*
18633 * Create the "sequence" model group.
18634 */
18635 particle->children = (xmlSchemaTreeItemPtr)
18636 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18637 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18638 if (particle->children == NULL)
18639 goto exit_failure;
18640 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18641 /*
18642 * SPEC "the particle of the {content type} of
18643 * the ... base ..."
18644 * Create a duplicate of the base type's particle
18645 * and assign its "term" to it.
18646 */
18647 particle->children->children =
18648 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18649 type->node,
18650 ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18651 ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18652 if (particle->children->children == NULL)
18653 goto exit_failure;
18654 particle = (xmlSchemaParticlePtr)
18655 particle->children->children;
18656 particle->children =
18657 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18658 /*
18659 * SPEC "followed by the `effective content`."
18660 */
18661 particle->next = effectiveContent;
18662 /*
18663 * This all will result in:
18664 * new-particle
18665 * --> new-sequence(
18666 * new-particle
18667 * --> base-model,
18668 * this-particle
18669 * --> this-model
18670 * )
18671 */
18672 } else {
18673 /*
18674 * This is the case when there is already an empty
18675 * <sequence> with minOccurs==maxOccurs==1.
18676 * Just add the base types's content type.
18677 * NOTE that, although we miss to add an intermediate
18678 * <sequence>, this should produce no difference to
18679 * neither the regex compilation of the content model,
18680 * nor to the complex type constraints.
18681 */
18682 particle->children->children =
18683 (xmlSchemaTreeItemPtr) baseType->subtypes;
18684 }
18685 }
18686 }
18687 }
18688 /*
18689 * Now fixup attribute uses:
18690 * - expand attr. group references
18691 * - intersect attribute wildcards
18692 * - inherit attribute uses of the base type
18693 * - inherit or union attr. wildcards if extending
18694 * - apply attr. use prohibitions if restricting
18695 */
18696 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18697 HFAILURE HERROR
18698 /*
18699 * Apply the complex type component constraints; this will not
18700 * check attributes, since this is done in
18701 * xmlSchemaFixupTypeAttributeUses().
18702 */
18703 res = xmlSchemaCheckCTComponent(pctxt, type);
18704 HFAILURE HERROR
18705
18706 #ifdef DEBUG_TYPE
18707 xmlSchemaDebugFixedType(pctxt, type);
18708 #endif
18709 if (olderrs != pctxt->nberrors)
18710 return(pctxt->err);
18711 else
18712 return(0);
18713
18714 exit_error:
18715 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18716 #ifdef DEBUG_TYPE
18717 xmlSchemaDebugFixedType(pctxt, type);
18718 #endif
18719 return(pctxt->err);
18720
18721 exit_failure:
18722 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18723 #ifdef DEBUG_TYPE
18724 xmlSchemaDebugFixedType(pctxt, type);
18725 #endif
18726 return(-1);
18727 }
18728
18729
18730 /**
18731 * xmlSchemaTypeFixup:
18732 * @typeDecl: the schema type definition
18733 * @ctxt: the schema parser context
18734 *
18735 * Fixes the content model of the type.
18736 * URGENT TODO: We need an int result!
18737 */
18738 static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,xmlSchemaAbstractCtxtPtr actxt)18739 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18740 xmlSchemaAbstractCtxtPtr actxt)
18741 {
18742 if (type == NULL)
18743 return(0);
18744 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18745 AERROR_INT("xmlSchemaTypeFixup",
18746 "this function needs a parser context");
18747 return(-1);
18748 }
18749 if (! WXS_IS_TYPE_NOT_FIXED(type))
18750 return(0);
18751 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18752 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18753 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18754 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18755 return(0);
18756 }
18757
18758 /**
18759 * xmlSchemaCheckFacet:
18760 * @facet: the facet
18761 * @typeDecl: the schema type definition
18762 * @pctxt: the schema parser context or NULL
18763 * @name: the optional name of the type
18764 *
18765 * Checks and computes the values of facets.
18766 *
18767 * Returns 0 if valid, a positive error code if not valid and
18768 * -1 in case of an internal or API error.
18769 */
18770 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt,const xmlChar * name ATTRIBUTE_UNUSED)18771 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18772 xmlSchemaTypePtr typeDecl,
18773 xmlSchemaParserCtxtPtr pctxt,
18774 const xmlChar * name ATTRIBUTE_UNUSED)
18775 {
18776 int ret = 0, ctxtGiven;
18777
18778 if ((facet == NULL) || (typeDecl == NULL))
18779 return(-1);
18780 /*
18781 * TODO: will the parser context be given if used from
18782 * the relaxNG module?
18783 */
18784 if (pctxt == NULL)
18785 ctxtGiven = 0;
18786 else
18787 ctxtGiven = 1;
18788
18789 switch (facet->type) {
18790 case XML_SCHEMA_FACET_MININCLUSIVE:
18791 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18792 case XML_SCHEMA_FACET_MAXINCLUSIVE:
18793 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18794 case XML_SCHEMA_FACET_ENUMERATION: {
18795 /*
18796 * Okay we need to validate the value
18797 * at that point.
18798 */
18799 xmlSchemaTypePtr base;
18800
18801 /* 4.3.5.5 Constraints on enumeration Schema Components
18802 * Schema Component Constraint: enumeration valid restriction
18803 * It is an `error` if any member of {value} is not in the
18804 * `value space` of {base type definition}.
18805 *
18806 * minInclusive, maxInclusive, minExclusive, maxExclusive:
18807 * The value `must` be in the
18808 * `value space` of the `base type`.
18809 */
18810 /*
18811 * This function is intended to deliver a compiled value
18812 * on the facet. In this implementation of XML Schemata the
18813 * type holding a facet, won't be a built-in type.
18814 * Thus to ensure that other API
18815 * calls (relaxng) do work, if the given type is a built-in
18816 * type, we will assume that the given built-in type *is
18817 * already* the base type.
18818 */
18819 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18820 base = typeDecl->baseType;
18821 if (base == NULL) {
18822 PERROR_INT("xmlSchemaCheckFacet",
18823 "a type user derived type has no base type");
18824 return (-1);
18825 }
18826 } else
18827 base = typeDecl;
18828
18829 if (! ctxtGiven) {
18830 /*
18831 * A context is needed if called from RelaxNG.
18832 */
18833 pctxt = xmlSchemaNewParserCtxt("*");
18834 if (pctxt == NULL)
18835 return (-1);
18836 }
18837 /*
18838 * NOTE: This call does not check the content nodes,
18839 * since they are not available:
18840 * facet->node is just the node holding the facet
18841 * definition, *not* the attribute holding the *value*
18842 * of the facet.
18843 */
18844 ret = xmlSchemaVCheckCVCSimpleType(
18845 ACTXT_CAST pctxt, facet->node, base,
18846 facet->value, &(facet->val), 1, 1, 0);
18847 if (ret != 0) {
18848 if (ret < 0) {
18849 /* No error message for RelaxNG. */
18850 if (ctxtGiven) {
18851 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18852 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18853 "Internal error: xmlSchemaCheckFacet, "
18854 "failed to validate the value '%s' of the "
18855 "facet '%s' against the base type",
18856 facet->value, xmlSchemaFacetTypeToString(facet->type));
18857 }
18858 goto internal_error;
18859 }
18860 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18861 /* No error message for RelaxNG. */
18862 if (ctxtGiven) {
18863 xmlChar *str = NULL;
18864
18865 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18866 ret, facet->node, WXS_BASIC_CAST facet,
18867 "The value '%s' of the facet does not validate "
18868 "against the base type '%s'",
18869 facet->value,
18870 xmlSchemaFormatQName(&str,
18871 base->targetNamespace, base->name));
18872 FREE_AND_NULL(str);
18873 }
18874 goto exit;
18875 } else if (facet->val == NULL) {
18876 if (ctxtGiven) {
18877 PERROR_INT("xmlSchemaCheckFacet",
18878 "value was not computed");
18879 }
18880 TODO
18881 }
18882 break;
18883 }
18884 case XML_SCHEMA_FACET_PATTERN:
18885 facet->regexp = xmlRegexpCompile(facet->value);
18886 if (facet->regexp == NULL) {
18887 ret = XML_SCHEMAP_REGEXP_INVALID;
18888 /* No error message for RelaxNG. */
18889 if (ctxtGiven) {
18890 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18891 ret, facet->node, WXS_BASIC_CAST typeDecl,
18892 "The value '%s' of the facet 'pattern' is not a "
18893 "valid regular expression",
18894 facet->value, NULL);
18895 }
18896 }
18897 break;
18898 case XML_SCHEMA_FACET_TOTALDIGITS:
18899 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18900 case XML_SCHEMA_FACET_LENGTH:
18901 case XML_SCHEMA_FACET_MAXLENGTH:
18902 case XML_SCHEMA_FACET_MINLENGTH:
18903
18904 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18905 ret = xmlSchemaValidatePredefinedType(
18906 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18907 facet->value, &(facet->val));
18908 } else {
18909 ret = xmlSchemaValidatePredefinedType(
18910 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18911 facet->value, &(facet->val));
18912 }
18913 if (ret != 0) {
18914 if (ret < 0) {
18915 /* No error message for RelaxNG. */
18916 if (ctxtGiven) {
18917 PERROR_INT("xmlSchemaCheckFacet",
18918 "validating facet value");
18919 }
18920 goto internal_error;
18921 }
18922 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18923 /* No error message for RelaxNG. */
18924 if (ctxtGiven) {
18925 /* error code */
18926 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18927 ret, facet->node, WXS_BASIC_CAST typeDecl,
18928 "The value '%s' of the facet '%s' is not a valid '%s'",
18929 facet->value,
18930 xmlSchemaFacetTypeToString(facet->type),
18931 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18932 BAD_CAST "nonNegativeInteger" :
18933 BAD_CAST "positiveInteger",
18934 NULL);
18935 }
18936 }
18937 break;
18938
18939 case XML_SCHEMA_FACET_WHITESPACE:{
18940 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18941 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18942 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18943 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18944 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18945 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18946 } else {
18947 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18948 /* No error message for RelaxNG. */
18949 if (ctxtGiven) {
18950 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18951 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18952 ret, facet->node, WXS_BASIC_CAST typeDecl,
18953 "The value '%s' of the facet 'whitespace' is not "
18954 "valid", facet->value, NULL);
18955 }
18956 }
18957 }
18958 default:
18959 break;
18960 }
18961 exit:
18962 if ((! ctxtGiven) && (pctxt != NULL))
18963 xmlSchemaFreeParserCtxt(pctxt);
18964 return (ret);
18965 internal_error:
18966 if ((! ctxtGiven) && (pctxt != NULL))
18967 xmlSchemaFreeParserCtxt(pctxt);
18968 return (-1);
18969 }
18970
18971 /**
18972 * xmlSchemaCheckFacetValues:
18973 * @typeDecl: the schema type definition
18974 * @ctxt: the schema parser context
18975 *
18976 * Checks the default values types, especially for facets
18977 */
18978 static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt)18979 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18980 xmlSchemaParserCtxtPtr pctxt)
18981 {
18982 int res, olderrs = pctxt->nberrors;
18983 const xmlChar *name = typeDecl->name;
18984 /*
18985 * NOTE: It is intended to use the facets list, instead
18986 * of facetSet.
18987 */
18988 if (typeDecl->facets != NULL) {
18989 xmlSchemaFacetPtr facet = typeDecl->facets;
18990
18991 /*
18992 * Temporarily assign the "schema" to the validation context
18993 * of the parser context. This is needed for NOTATION validation.
18994 */
18995 if (pctxt->vctxt == NULL) {
18996 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18997 return(-1);
18998 }
18999 pctxt->vctxt->schema = pctxt->schema;
19000 while (facet != NULL) {
19001 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
19002 HFAILURE
19003 facet = facet->next;
19004 }
19005 pctxt->vctxt->schema = NULL;
19006 }
19007 if (olderrs != pctxt->nberrors)
19008 return(pctxt->err);
19009 return(0);
19010 exit_failure:
19011 return(-1);
19012 }
19013
19014 /**
19015 * xmlSchemaGetCircModelGrDefRef:
19016 * @ctxtMGroup: the searched model group
19017 * @selfMGroup: the second searched model group
19018 * @particle: the first particle
19019 *
19020 * This one is intended to be used by
19021 * xmlSchemaCheckGroupDefCircular only.
19022 *
19023 * Returns the particle with the circular model group definition reference,
19024 * otherwise NULL.
19025 */
19026 static xmlSchemaTreeItemPtr
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,xmlSchemaTreeItemPtr particle)19027 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
19028 xmlSchemaTreeItemPtr particle)
19029 {
19030 xmlSchemaTreeItemPtr circ = NULL;
19031 xmlSchemaTreeItemPtr term;
19032 xmlSchemaModelGroupDefPtr gdef;
19033
19034 for (; particle != NULL; particle = particle->next) {
19035 term = particle->children;
19036 if (term == NULL)
19037 continue;
19038 switch (term->type) {
19039 case XML_SCHEMA_TYPE_GROUP:
19040 gdef = (xmlSchemaModelGroupDefPtr) term;
19041 if (gdef == groupDef)
19042 return (particle);
19043 /*
19044 * Mark this model group definition to avoid infinite
19045 * recursion on circular references not yet examined.
19046 */
19047 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
19048 continue;
19049 if (gdef->children != NULL) {
19050 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19051 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
19052 gdef->children->children);
19053 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19054 if (circ != NULL)
19055 return (circ);
19056 }
19057 break;
19058 case XML_SCHEMA_TYPE_SEQUENCE:
19059 case XML_SCHEMA_TYPE_CHOICE:
19060 case XML_SCHEMA_TYPE_ALL:
19061 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
19062 if (circ != NULL)
19063 return (circ);
19064 break;
19065 default:
19066 break;
19067 }
19068 }
19069 return (NULL);
19070 }
19071
19072 /**
19073 * xmlSchemaCheckGroupDefCircular:
19074 * @item: the model group definition
19075 * @ctxt: the parser context
19076 * @name: the name
19077 *
19078 * Checks for circular references to model group definitions.
19079 */
19080 static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,xmlSchemaParserCtxtPtr ctxt)19081 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
19082 xmlSchemaParserCtxtPtr ctxt)
19083 {
19084 /*
19085 * Schema Component Constraint: Model Group Correct
19086 * 2 Circular groups are disallowed. That is, within the {particles}
19087 * of a group there must not be at any depth a particle whose {term}
19088 * is the group itself.
19089 */
19090 if ((item == NULL) ||
19091 (item->type != XML_SCHEMA_TYPE_GROUP) ||
19092 (item->children == NULL))
19093 return;
19094 {
19095 xmlSchemaTreeItemPtr circ;
19096
19097 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
19098 if (circ != NULL) {
19099 xmlChar *str = NULL;
19100 /*
19101 * TODO: The error report is not adequate: this constraint
19102 * is defined for model groups but not definitions, but since
19103 * there cannot be any circular model groups without a model group
19104 * definition (if not using a construction API), we check those
19105 * definitions only.
19106 */
19107 xmlSchemaPCustomErr(ctxt,
19108 XML_SCHEMAP_MG_PROPS_CORRECT_2,
19109 NULL, WXS_ITEM_NODE(circ),
19110 "Circular reference to the model group definition '%s' "
19111 "defined", xmlSchemaFormatQName(&str,
19112 item->targetNamespace, item->name));
19113 FREE_AND_NULL(str)
19114 /*
19115 * NOTE: We will cut the reference to avoid further
19116 * confusion of the processor. This is a fatal error.
19117 */
19118 circ->children = NULL;
19119 }
19120 }
19121 }
19122
19123 /**
19124 * xmlSchemaModelGroupToModelGroupDefFixup:
19125 * @ctxt: the parser context
19126 * @mg: the model group
19127 *
19128 * Assigns the model group of model group definitions to the "term"
19129 * of the referencing particle.
19130 * In xmlSchemaResolveModelGroupParticleReferences the model group
19131 * definitions were assigned to the "term", since needed for the
19132 * circularity check.
19133 *
19134 * Schema Component Constraint:
19135 * All Group Limited (cos-all-limited) (1.2)
19136 */
19137 static void
xmlSchemaModelGroupToModelGroupDefFixup(xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaModelGroupPtr mg)19138 xmlSchemaModelGroupToModelGroupDefFixup(
19139 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
19140 xmlSchemaModelGroupPtr mg)
19141 {
19142 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19143
19144 while (particle != NULL) {
19145 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19146 ((WXS_PARTICLE_TERM(particle))->type !=
19147 XML_SCHEMA_TYPE_GROUP))
19148 {
19149 particle = WXS_PTC_CAST particle->next;
19150 continue;
19151 }
19152 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19153 /*
19154 * TODO: Remove the particle.
19155 */
19156 WXS_PARTICLE_TERM(particle) = NULL;
19157 particle = WXS_PTC_CAST particle->next;
19158 continue;
19159 }
19160 /*
19161 * Assign the model group to the {term} of the particle.
19162 */
19163 WXS_PARTICLE_TERM(particle) =
19164 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19165
19166 particle = WXS_PTC_CAST particle->next;
19167 }
19168 }
19169
19170 /**
19171 * xmlSchemaCheckAttrGroupCircularRecur:
19172 * @ctxtGr: the searched attribute group
19173 * @attr: the current attribute list to be processed
19174 *
19175 * This one is intended to be used by
19176 * xmlSchemaCheckAttrGroupCircular only.
19177 *
19178 * Returns the circular attribute group reference, otherwise NULL.
19179 */
19180 static xmlSchemaQNameRefPtr
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,xmlSchemaItemListPtr list)19181 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19182 xmlSchemaItemListPtr list)
19183 {
19184 xmlSchemaAttributeGroupPtr gr;
19185 xmlSchemaQNameRefPtr ref, circ;
19186 int i;
19187 /*
19188 * We will search for an attribute group reference which
19189 * references the context attribute group.
19190 */
19191 for (i = 0; i < list->nbItems; i++) {
19192 ref = list->items[i];
19193 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19194 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19195 (ref->item != NULL))
19196 {
19197 gr = WXS_ATTR_GROUP_CAST ref->item;
19198 if (gr == ctxtGr)
19199 return(ref);
19200 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19201 continue;
19202 /*
19203 * Mark as visited to avoid infinite recursion on
19204 * circular references not yet examined.
19205 */
19206 if ((gr->attrUses) &&
19207 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19208 {
19209 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19210 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19211 (xmlSchemaItemListPtr) gr->attrUses);
19212 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19213 if (circ != NULL)
19214 return (circ);
19215 }
19216
19217 }
19218 }
19219 return (NULL);
19220 }
19221
19222 /**
19223 * xmlSchemaCheckAttrGroupCircular:
19224 * attrGr: the attribute group definition
19225 * @ctxt: the parser context
19226 * @name: the name
19227 *
19228 * Checks for circular references of attribute groups.
19229 */
19230 static int
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,xmlSchemaParserCtxtPtr ctxt)19231 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19232 xmlSchemaParserCtxtPtr ctxt)
19233 {
19234 /*
19235 * Schema Representation Constraint:
19236 * Attribute Group Definition Representation OK
19237 * 3 Circular group reference is disallowed outside <redefine>.
19238 * That is, unless this element information item's parent is
19239 * <redefine>, then among the [children], if any, there must
19240 * not be an <attributeGroup> with ref [attribute] which resolves
19241 * to the component corresponding to this <attributeGroup>. Indirect
19242 * circularity is also ruled out. That is, when QName resolution
19243 * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19244 * any <attributeGroup>s with a ref [attribute] among the [children],
19245 * it must not be the case that a `QName` is encountered at any depth
19246 * which resolves to the component corresponding to this <attributeGroup>.
19247 */
19248 if (attrGr->attrUses == NULL)
19249 return(0);
19250 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19251 return(0);
19252 else {
19253 xmlSchemaQNameRefPtr circ;
19254
19255 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19256 (xmlSchemaItemListPtr) attrGr->attrUses);
19257 if (circ != NULL) {
19258 xmlChar *str = NULL;
19259 /*
19260 * TODO: Report the referenced attr group as QName.
19261 */
19262 xmlSchemaPCustomErr(ctxt,
19263 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19264 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19265 "Circular reference to the attribute group '%s' "
19266 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19267 FREE_AND_NULL(str);
19268 /*
19269 * NOTE: We will cut the reference to avoid further
19270 * confusion of the processor.
19271 * BADSPEC TODO: The spec should define how to process in this case.
19272 */
19273 circ->item = NULL;
19274 return(ctxt->err);
19275 }
19276 }
19277 return(0);
19278 }
19279
19280 static int
19281 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19282 xmlSchemaAttributeGroupPtr attrGr);
19283
19284 /**
19285 * xmlSchemaExpandAttributeGroupRefs:
19286 * @pctxt: the parser context
19287 * @node: the node of the component holding the attribute uses
19288 * @completeWild: the intersected wildcard to be returned
19289 * @list: the attribute uses
19290 *
19291 * Substitutes contained attribute group references
19292 * for their attribute uses. Wildcards are intersected.
19293 * Attribute use prohibitions are removed from the list
19294 * and returned via the @prohibs list.
19295 * Pointlessness of attr. prohibs, if a matching attr. decl
19296 * is existent a well, are checked.
19297 */
19298 static int
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr item,xmlSchemaWildcardPtr * completeWild,xmlSchemaItemListPtr list,xmlSchemaItemListPtr prohibs)19299 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19300 xmlSchemaBasicItemPtr item,
19301 xmlSchemaWildcardPtr *completeWild,
19302 xmlSchemaItemListPtr list,
19303 xmlSchemaItemListPtr prohibs)
19304 {
19305 xmlSchemaAttributeGroupPtr gr;
19306 xmlSchemaAttributeUsePtr use;
19307 xmlSchemaItemListPtr sublist;
19308 int i, j;
19309 int created = (*completeWild == NULL) ? 0 : 1;
19310
19311 if (prohibs)
19312 prohibs->nbItems = 0;
19313
19314 for (i = 0; i < list->nbItems; i++) {
19315 use = list->items[i];
19316
19317 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19318 if (prohibs == NULL) {
19319 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19320 "unexpected attr prohibition found");
19321 return(-1);
19322 }
19323 /*
19324 * Remove from attribute uses.
19325 */
19326 if (xmlSchemaItemListRemove(list, i) == -1)
19327 return(-1);
19328 i--;
19329 /*
19330 * Note that duplicate prohibitions were already
19331 * handled at parsing time.
19332 */
19333 /*
19334 * Add to list of prohibitions.
19335 */
19336 xmlSchemaItemListAddSize(prohibs, 2, use);
19337 continue;
19338 }
19339 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19340 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19341 {
19342 if ((WXS_QNAME_CAST use)->item == NULL)
19343 return(-1);
19344 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19345 /*
19346 * Expand the referenced attr. group.
19347 * TODO: remove this, this is done in a previous step, so
19348 * already done here.
19349 */
19350 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19351 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19352 return(-1);
19353 }
19354 /*
19355 * Build the 'complete' wildcard; i.e. intersect multiple
19356 * wildcards.
19357 */
19358 if (gr->attributeWildcard != NULL) {
19359 if (*completeWild == NULL) {
19360 *completeWild = gr->attributeWildcard;
19361 } else {
19362 if (! created) {
19363 xmlSchemaWildcardPtr tmpWild;
19364
19365 /*
19366 * Copy the first encountered wildcard as context,
19367 * except for the annotation.
19368 *
19369 * Although the complete wildcard might not correspond
19370 * to any node in the schema, we will anchor it on
19371 * the node of the owner component.
19372 */
19373 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19374 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19375 WXS_ITEM_NODE(item));
19376 if (tmpWild == NULL)
19377 return(-1);
19378 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19379 tmpWild, *completeWild) == -1)
19380 return (-1);
19381 tmpWild->processContents = (*completeWild)->processContents;
19382 *completeWild = tmpWild;
19383 created = 1;
19384 }
19385
19386 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19387 gr->attributeWildcard) == -1)
19388 return(-1);
19389 }
19390 }
19391 /*
19392 * Just remove the reference if the referenced group does not
19393 * contain any attribute uses.
19394 */
19395 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19396 if ((sublist == NULL) || sublist->nbItems == 0) {
19397 if (xmlSchemaItemListRemove(list, i) == -1)
19398 return(-1);
19399 i--;
19400 continue;
19401 }
19402 /*
19403 * Add the attribute uses.
19404 */
19405 list->items[i] = sublist->items[0];
19406 if (sublist->nbItems != 1) {
19407 for (j = 1; j < sublist->nbItems; j++) {
19408 i++;
19409 if (xmlSchemaItemListInsert(list,
19410 sublist->items[j], i) == -1)
19411 return(-1);
19412 }
19413 }
19414 }
19415
19416 }
19417 /*
19418 * Handle pointless prohibitions of declared attributes.
19419 */
19420 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19421 xmlSchemaAttributeUseProhibPtr prohib;
19422
19423 for (i = prohibs->nbItems -1; i >= 0; i--) {
19424 prohib = prohibs->items[i];
19425 for (j = 0; j < list->nbItems; j++) {
19426 use = list->items[j];
19427
19428 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19429 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19430 {
19431 xmlChar *str = NULL;
19432
19433 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19434 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19435 prohib->node, NULL,
19436 "Skipping pointless attribute use prohibition "
19437 "'%s', since a corresponding attribute use "
19438 "exists already in the type definition",
19439 xmlSchemaFormatQName(&str,
19440 prohib->targetNamespace, prohib->name),
19441 NULL, NULL);
19442 FREE_AND_NULL(str);
19443 /*
19444 * Remove the prohibition.
19445 */
19446 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19447 return(-1);
19448 break;
19449 }
19450 }
19451 }
19452 }
19453 return(0);
19454 }
19455
19456 /**
19457 * xmlSchemaAttributeGroupExpandRefs:
19458 * @pctxt: the parser context
19459 * @attrGr: the attribute group definition
19460 *
19461 * Computation of:
19462 * {attribute uses} property
19463 * {attribute wildcard} property
19464 *
19465 * Substitutes contained attribute group references
19466 * for their attribute uses. Wildcards are intersected.
19467 */
19468 static int
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19469 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19470 xmlSchemaAttributeGroupPtr attrGr)
19471 {
19472 if ((attrGr->attrUses == NULL) ||
19473 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19474 return(0);
19475
19476 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19477 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19478 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19479 return(-1);
19480 return(0);
19481 }
19482
19483 /**
19484 * xmlSchemaAttributeGroupExpandRefs:
19485 * @pctxt: the parser context
19486 * @attrGr: the attribute group definition
19487 *
19488 * Substitutes contained attribute group references
19489 * for their attribute uses. Wildcards are intersected.
19490 *
19491 * Schema Component Constraint:
19492 * Attribute Group Definition Properties Correct (ag-props-correct)
19493 */
19494 static int
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19495 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19496 xmlSchemaAttributeGroupPtr attrGr)
19497 {
19498 /*
19499 * SPEC ag-props-correct
19500 * (1) "The values of the properties of an attribute group definition
19501 * must be as described in the property tableau in The Attribute
19502 * Group Definition Schema Component ($3.6.1), modulo the impact of
19503 * Missing Sub-components ($5.3);"
19504 */
19505
19506 if ((attrGr->attrUses != NULL) &&
19507 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19508 {
19509 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19510 xmlSchemaAttributeUsePtr use, tmp;
19511 int i, j, hasId = 0;
19512
19513 for (i = uses->nbItems -1; i >= 0; i--) {
19514 use = uses->items[i];
19515 /*
19516 * SPEC ag-props-correct
19517 * (2) "Two distinct members of the {attribute uses} must not have
19518 * {attribute declaration}s both of whose {name}s match and whose
19519 * {target namespace}s are identical."
19520 */
19521 if (i > 0) {
19522 for (j = i -1; j >= 0; j--) {
19523 tmp = uses->items[j];
19524 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19525 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19526 (WXS_ATTRUSE_DECL_TNS(use) ==
19527 WXS_ATTRUSE_DECL_TNS(tmp)))
19528 {
19529 xmlChar *str = NULL;
19530
19531 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19532 XML_SCHEMAP_AG_PROPS_CORRECT,
19533 attrGr->node, WXS_BASIC_CAST attrGr,
19534 "Duplicate %s",
19535 xmlSchemaGetComponentDesignation(&str, use),
19536 NULL);
19537 FREE_AND_NULL(str);
19538 /*
19539 * Remove the duplicate.
19540 */
19541 if (xmlSchemaItemListRemove(uses, i) == -1)
19542 return(-1);
19543 goto next_use;
19544 }
19545 }
19546 }
19547 /*
19548 * SPEC ag-props-correct
19549 * (3) "Two distinct members of the {attribute uses} must not have
19550 * {attribute declaration}s both of whose {type definition}s are or
19551 * are derived from ID."
19552 * TODO: Does 'derived' include member-types of unions?
19553 */
19554 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19555 if (xmlSchemaIsDerivedFromBuiltInType(
19556 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19557 {
19558 if (hasId) {
19559 xmlChar *str = NULL;
19560
19561 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19562 XML_SCHEMAP_AG_PROPS_CORRECT,
19563 attrGr->node, WXS_BASIC_CAST attrGr,
19564 "There must not exist more than one attribute "
19565 "declaration of type 'xs:ID' "
19566 "(or derived from 'xs:ID'). The %s violates this "
19567 "constraint",
19568 xmlSchemaGetComponentDesignation(&str, use),
19569 NULL);
19570 FREE_AND_NULL(str);
19571 if (xmlSchemaItemListRemove(uses, i) == -1)
19572 return(-1);
19573 }
19574 hasId = 1;
19575 }
19576 }
19577 next_use: {}
19578 }
19579 }
19580 return(0);
19581 }
19582
19583 /**
19584 * xmlSchemaResolveAttrGroupReferences:
19585 * @attrgrpDecl: the schema attribute definition
19586 * @ctxt: the schema parser context
19587 * @name: the attribute name
19588 *
19589 * Resolves references to attribute group definitions.
19590 */
19591 static int
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,xmlSchemaParserCtxtPtr ctxt)19592 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19593 xmlSchemaParserCtxtPtr ctxt)
19594 {
19595 xmlSchemaAttributeGroupPtr group;
19596
19597 if (ref->item != NULL)
19598 return(0);
19599 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19600 ref->name,
19601 ref->targetNamespace);
19602 if (group == NULL) {
19603 xmlSchemaPResCompAttrErr(ctxt,
19604 XML_SCHEMAP_SRC_RESOLVE,
19605 NULL, ref->node,
19606 "ref", ref->name, ref->targetNamespace,
19607 ref->itemType, NULL);
19608 return(ctxt->err);
19609 }
19610 ref->item = WXS_BASIC_CAST group;
19611 return(0);
19612 }
19613
19614 /**
19615 * xmlSchemaCheckAttrPropsCorrect:
19616 * @item: an schema attribute declaration/use
19617 * @ctxt: a schema parser context
19618 * @name: the name of the attribute
19619 *
19620 *
19621 * Schema Component Constraint:
19622 * Attribute Declaration Properties Correct (a-props-correct)
19623 *
19624 * Validates the value constraints of an attribute declaration/use.
19625 * NOTE that this needs the simple type definitions to be already
19626 * built and checked.
19627 */
19628 static int
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributePtr attr)19629 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19630 xmlSchemaAttributePtr attr)
19631 {
19632
19633 /*
19634 * SPEC a-props-correct (1)
19635 * "The values of the properties of an attribute declaration must
19636 * be as described in the property tableau in The Attribute
19637 * Declaration Schema Component ($3.2.1), modulo the impact of
19638 * Missing Sub-components ($5.3)."
19639 */
19640
19641 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19642 return(0);
19643
19644 if (attr->defValue != NULL) {
19645 int ret;
19646
19647 /*
19648 * SPEC a-props-correct (3)
19649 * "If the {type definition} is or is derived from ID then there
19650 * must not be a {value constraint}."
19651 */
19652 if (xmlSchemaIsDerivedFromBuiltInType(
19653 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19654 {
19655 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19656 XML_SCHEMAP_A_PROPS_CORRECT_3,
19657 NULL, WXS_BASIC_CAST attr,
19658 "Value constraints are not allowed if the type definition "
19659 "is or is derived from xs:ID",
19660 NULL, NULL);
19661 return(pctxt->err);
19662 }
19663 /*
19664 * SPEC a-props-correct (2)
19665 * "if there is a {value constraint}, the canonical lexical
19666 * representation of its value must be `valid` with respect
19667 * to the {type definition} as defined in String Valid ($3.14.4)."
19668 * TODO: Don't care about the *canonical* stuff here, this requirement
19669 * will be removed in WXS 1.1 anyway.
19670 */
19671 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19672 attr->node, WXS_ATTR_TYPEDEF(attr),
19673 attr->defValue, &(attr->defVal),
19674 1, 1, 0);
19675 if (ret != 0) {
19676 if (ret < 0) {
19677 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19678 "calling xmlSchemaVCheckCVCSimpleType()");
19679 return(-1);
19680 }
19681 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19682 XML_SCHEMAP_A_PROPS_CORRECT_2,
19683 NULL, WXS_BASIC_CAST attr,
19684 "The value of the value constraint is not valid",
19685 NULL, NULL);
19686 return(pctxt->err);
19687 }
19688 }
19689
19690 return(0);
19691 }
19692
19693 static xmlSchemaElementPtr
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,xmlSchemaElementPtr ancestor)19694 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19695 xmlSchemaElementPtr ancestor)
19696 {
19697 xmlSchemaElementPtr ret;
19698
19699 if (WXS_SUBST_HEAD(ancestor) == NULL)
19700 return (NULL);
19701 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19702 return (ancestor);
19703
19704 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19705 return (NULL);
19706 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19707 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19708 WXS_SUBST_HEAD(ancestor));
19709 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19710
19711 return (ret);
19712 }
19713
19714 /**
19715 * xmlSchemaCheckElemPropsCorrect:
19716 * @ctxt: a schema parser context
19717 * @decl: the element declaration
19718 * @name: the name of the attribute
19719 *
19720 * Schema Component Constraint:
19721 * Element Declaration Properties Correct (e-props-correct)
19722 *
19723 * STATUS:
19724 * missing: (6)
19725 */
19726 static int
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr elemDecl)19727 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19728 xmlSchemaElementPtr elemDecl)
19729 {
19730 int ret = 0;
19731 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19732 /*
19733 * SPEC (1) "The values of the properties of an element declaration
19734 * must be as described in the property tableau in The Element
19735 * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19736 * Sub-components ($5.3)."
19737 */
19738 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19739 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19740
19741 xmlSchemaCheckElementDeclComponent(head, pctxt);
19742 /*
19743 * SPEC (3) "If there is a non-`absent` {substitution group
19744 * affiliation}, then {scope} must be global."
19745 */
19746 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19747 xmlSchemaPCustomErr(pctxt,
19748 XML_SCHEMAP_E_PROPS_CORRECT_3,
19749 WXS_BASIC_CAST elemDecl, NULL,
19750 "Only global element declarations can have a "
19751 "substitution group affiliation", NULL);
19752 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19753 }
19754 /*
19755 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19756 * That is, it must not be possible to return to an element declaration
19757 * by repeatedly following the {substitution group affiliation}
19758 * property."
19759 */
19760 if (head == elemDecl)
19761 circ = head;
19762 else if (WXS_SUBST_HEAD(head) != NULL)
19763 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19764 else
19765 circ = NULL;
19766 if (circ != NULL) {
19767 xmlChar *strA = NULL, *strB = NULL;
19768
19769 xmlSchemaPCustomErrExt(pctxt,
19770 XML_SCHEMAP_E_PROPS_CORRECT_6,
19771 WXS_BASIC_CAST circ, NULL,
19772 "The element declaration '%s' defines a circular "
19773 "substitution group to element declaration '%s'",
19774 xmlSchemaGetComponentQName(&strA, circ),
19775 xmlSchemaGetComponentQName(&strB, head),
19776 NULL);
19777 FREE_AND_NULL(strA)
19778 FREE_AND_NULL(strB)
19779 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19780 }
19781 /*
19782 * SPEC (4) "If there is a {substitution group affiliation},
19783 * the {type definition}
19784 * of the element declaration must be validly derived from the {type
19785 * definition} of the {substitution group affiliation}, given the value
19786 * of the {substitution group exclusions} of the {substitution group
19787 * affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19788 * (if the {type definition} is complex) or as defined in
19789 * Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19790 * simple)."
19791 *
19792 * NOTE: {substitution group exclusions} means the values of the
19793 * attribute "final".
19794 */
19795
19796 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19797 int set = 0;
19798
19799 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19800 set |= SUBSET_EXTENSION;
19801 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19802 set |= SUBSET_RESTRICTION;
19803
19804 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19805 WXS_ELEM_TYPEDEF(head), set) != 0) {
19806 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19807
19808 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19809 xmlSchemaPCustomErrExt(pctxt,
19810 XML_SCHEMAP_E_PROPS_CORRECT_4,
19811 WXS_BASIC_CAST elemDecl, NULL,
19812 "The type definition '%s' was "
19813 "either rejected by the substitution group "
19814 "affiliation '%s', or not validly derived from its type "
19815 "definition '%s'",
19816 xmlSchemaGetComponentQName(&strA, typeDef),
19817 xmlSchemaGetComponentQName(&strB, head),
19818 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19819 FREE_AND_NULL(strA)
19820 FREE_AND_NULL(strB)
19821 FREE_AND_NULL(strC)
19822 }
19823 }
19824 }
19825 /*
19826 * SPEC (5) "If the {type definition} or {type definition}'s
19827 * {content type}
19828 * is or is derived from ID then there must not be a {value constraint}.
19829 * Note: The use of ID as a type definition for elements goes beyond
19830 * XML 1.0, and should be avoided if backwards compatibility is desired"
19831 */
19832 if ((elemDecl->value != NULL) &&
19833 ((WXS_IS_SIMPLE(typeDef) &&
19834 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19835 (WXS_IS_COMPLEX(typeDef) &&
19836 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19837 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19838 XML_SCHEMAS_ID)))) {
19839
19840 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19841 xmlSchemaPCustomErr(pctxt,
19842 XML_SCHEMAP_E_PROPS_CORRECT_5,
19843 WXS_BASIC_CAST elemDecl, NULL,
19844 "The type definition (or type definition's content type) is or "
19845 "is derived from ID; value constraints are not allowed in "
19846 "conjunction with such a type definition", NULL);
19847 } else if (elemDecl->value != NULL) {
19848 int vcret;
19849 xmlNodePtr node = NULL;
19850
19851 /*
19852 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19853 * representation of its value must be `valid` with respect to the
19854 * {type definition} as defined in Element Default Valid (Immediate)
19855 * ($3.3.6)."
19856 */
19857 if (typeDef == NULL) {
19858 xmlSchemaPErr(pctxt, elemDecl->node,
19859 XML_SCHEMAP_INTERNAL,
19860 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19861 "type is missing... skipping validation of "
19862 "the value constraint", NULL, NULL);
19863 return (-1);
19864 }
19865 if (elemDecl->node != NULL) {
19866 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19867 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19868 BAD_CAST "fixed");
19869 else
19870 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19871 BAD_CAST "default");
19872 }
19873 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19874 typeDef, elemDecl->value, &(elemDecl->defVal));
19875 if (vcret != 0) {
19876 if (vcret < 0) {
19877 PERROR_INT("xmlSchemaElemCheckValConstr",
19878 "failed to validate the value constraint of an "
19879 "element declaration");
19880 return (-1);
19881 }
19882 return (vcret);
19883 }
19884 }
19885
19886 return (ret);
19887 }
19888
19889 /**
19890 * xmlSchemaCheckElemSubstGroup:
19891 * @ctxt: a schema parser context
19892 * @decl: the element declaration
19893 * @name: the name of the attribute
19894 *
19895 * Schema Component Constraint:
19896 * Substitution Group (cos-equiv-class)
19897 *
19898 * In Libxml2 the subst. groups will be precomputed, in terms of that
19899 * a list will be built for each subst. group head, holding all direct
19900 * referents to this head.
19901 * NOTE that this function needs:
19902 * 1. circular subst. groups to be checked beforehand
19903 * 2. the declaration's type to be derived from the head's type
19904 *
19905 * STATUS:
19906 *
19907 */
19908 static void
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaElementPtr elemDecl)19909 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19910 xmlSchemaElementPtr elemDecl)
19911 {
19912 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19913 /* SPEC (1) "Its {abstract} is false." */
19914 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19915 return;
19916 {
19917 xmlSchemaElementPtr head;
19918 xmlSchemaTypePtr headType, type;
19919 int set, methSet;
19920 /*
19921 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19922 * {disallowed substitutions} as the blocking constraint, as defined in
19923 * Substitution Group OK (Transitive) ($3.3.6)."
19924 */
19925 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19926 head = WXS_SUBST_HEAD(head)) {
19927 set = 0;
19928 methSet = 0;
19929 /*
19930 * The blocking constraints.
19931 */
19932 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19933 continue;
19934 headType = head->subtypes;
19935 type = elemDecl->subtypes;
19936 if (headType == type)
19937 goto add_member;
19938 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19939 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19940 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19941 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19942 /*
19943 * SPEC: Substitution Group OK (Transitive) (2.3)
19944 * "The set of all {derivation method}s involved in the
19945 * derivation of D's {type definition} from C's {type definition}
19946 * does not intersect with the union of the blocking constraint,
19947 * C's {prohibited substitutions} (if C is complex, otherwise the
19948 * empty set) and the {prohibited substitutions} (respectively the
19949 * empty set) of any intermediate {type definition}s in the
19950 * derivation of D's {type definition} from C's {type definition}."
19951 */
19952 /*
19953 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19954 * subst.head axis, the methSet does not need to be computed for
19955 * the full depth over and over.
19956 */
19957 /*
19958 * The set of all {derivation method}s involved in the derivation
19959 */
19960 while ((type != NULL) && (type != headType)) {
19961 if ((WXS_IS_EXTENSION(type)) &&
19962 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19963 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19964
19965 if (WXS_IS_RESTRICTION(type) &&
19966 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19967 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19968
19969 type = type->baseType;
19970 }
19971 /*
19972 * The {prohibited substitutions} of all intermediate types +
19973 * the head's type.
19974 */
19975 type = elemDecl->subtypes->baseType;
19976 while (type != NULL) {
19977 if (WXS_IS_COMPLEX(type)) {
19978 if ((type->flags &
19979 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19980 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19981 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19982 if ((type->flags &
19983 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19984 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19985 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19986 } else
19987 break;
19988 if (type == headType)
19989 break;
19990 type = type->baseType;
19991 }
19992 if ((set != 0) &&
19993 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19994 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19995 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19996 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19997 continue;
19998 }
19999 add_member:
20000 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
20001 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
20002 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
20003 }
20004 }
20005 }
20006
20007 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
20008 /**
20009 * xmlSchemaCheckElementDeclComponent
20010 * @pctxt: the schema parser context
20011 * @ctxtComponent: the context component (an element declaration)
20012 * @ctxtParticle: the first particle of the context component
20013 * @searchParticle: the element declaration particle to be analysed
20014 *
20015 * Schema Component Constraint: Element Declarations Consistent
20016 */
20017 static int
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ctxtComponent,xmlSchemaParticlePtr ctxtParticle,xmlSchemaParticlePtr searchParticle,xmlSchemaParticlePtr curParticle,int search)20018 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
20019 xmlSchemaBasicItemPtr ctxtComponent,
20020 xmlSchemaParticlePtr ctxtParticle,
20021 xmlSchemaParticlePtr searchParticle,
20022 xmlSchemaParticlePtr curParticle,
20023 int search)
20024 {
20025 return(0);
20026
20027 int ret = 0;
20028 xmlSchemaParticlePtr cur = curParticle;
20029 if (curParticle == NULL) {
20030 return(0);
20031 }
20032 if (WXS_PARTICLE_TERM(curParticle) == NULL) {
20033 /*
20034 * Just return in this case. A missing "term" of the particle
20035 * might arise due to an invalid "term" component.
20036 */
20037 return(0);
20038 }
20039 while (cur != NULL) {
20040 switch (WXS_PARTICLE_TERM(cur)->type) {
20041 case XML_SCHEMA_TYPE_ANY:
20042 break;
20043 case XML_SCHEMA_TYPE_ELEMENT:
20044 if (search == 0) {
20045 ret = xmlSchemaCheckElementDeclConsistent(pctxt,
20046 ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
20047 if (ret != 0)
20048 return(ret);
20049 } else {
20050 xmlSchemaElementPtr elem =
20051 WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
20052 /*
20053 * SPEC Element Declarations Consistent:
20054 * "If the {particles} contains, either directly,
20055 * indirectly (that is, within the {particles} of a
20056 * contained model group, recursively) or `implicitly`
20057 * two or more element declaration particles with
20058 * the same {name} and {target namespace}, then
20059 * all their type definitions must be the same
20060 * top-level definition [...]"
20061 */
20062 if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
20063 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
20064 xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20065 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
20066 {
20067 xmlChar *strA = NULL, *strB = NULL;
20068
20069 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20070 /* TODO: error code */
20071 XML_SCHEMAP_COS_NONAMBIG,
20072 WXS_ITEM_NODE(cur), NULL,
20073 "In the content model of %s, there are multiple "
20074 "element declarations for '%s' with different "
20075 "type definitions",
20076 xmlSchemaGetComponentDesignation(&strA,
20077 ctxtComponent),
20078 xmlSchemaFormatQName(&strB,
20079 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20080 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
20081 FREE_AND_NULL(strA);
20082 FREE_AND_NULL(strB);
20083 return(XML_SCHEMAP_COS_NONAMBIG);
20084 }
20085 }
20086 break;
20087 case XML_SCHEMA_TYPE_SEQUENCE: {
20088 break;
20089 }
20090 case XML_SCHEMA_TYPE_CHOICE:{
20091 /*
20092 xmlSchemaTreeItemPtr sub;
20093
20094 sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
20095 while (sub != NULL) {
20096 ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
20097 ctxtParticle, ctxtElem);
20098 if (ret != 0)
20099 return(ret);
20100 sub = sub->next;
20101 }
20102 */
20103 break;
20104 }
20105 case XML_SCHEMA_TYPE_ALL:
20106 break;
20107 case XML_SCHEMA_TYPE_GROUP:
20108 break;
20109 default:
20110 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
20111 "xmlSchemaCheckElementDeclConsistent",
20112 "found unexpected term of type '%s' in content model",
20113 WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
20114 return(-1);
20115 }
20116 cur = (xmlSchemaParticlePtr) cur->next;
20117 }
20118
20119 exit:
20120 return(ret);
20121 }
20122 #endif
20123
20124 /**
20125 * xmlSchemaCheckElementDeclComponent
20126 * @item: an schema element declaration/particle
20127 * @ctxt: a schema parser context
20128 * @name: the name of the attribute
20129 *
20130 * Validates the value constraints of an element declaration.
20131 * Adds substitution group members.
20132 */
20133 static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)20134 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
20135 xmlSchemaParserCtxtPtr ctxt)
20136 {
20137 if (elemDecl == NULL)
20138 return;
20139 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
20140 return;
20141 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
20142 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20143 /*
20144 * Adds substitution group members.
20145 */
20146 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20147 }
20148 }
20149
20150 /**
20151 * xmlSchemaResolveModelGroupParticleReferences:
20152 * @particle: a particle component
20153 * @ctxt: a parser context
20154 *
20155 * Resolves references of a model group's {particles} to
20156 * model group definitions and to element declarations.
20157 */
20158 static void
xmlSchemaResolveModelGroupParticleReferences(xmlSchemaParserCtxtPtr ctxt,xmlSchemaModelGroupPtr mg)20159 xmlSchemaResolveModelGroupParticleReferences(
20160 xmlSchemaParserCtxtPtr ctxt,
20161 xmlSchemaModelGroupPtr mg)
20162 {
20163 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20164 xmlSchemaQNameRefPtr ref;
20165 xmlSchemaBasicItemPtr refItem;
20166
20167 /*
20168 * URGENT TODO: Test this.
20169 */
20170 while (particle != NULL) {
20171 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20172 ((WXS_PARTICLE_TERM(particle))->type !=
20173 XML_SCHEMA_EXTRA_QNAMEREF))
20174 {
20175 goto next_particle;
20176 }
20177 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20178 /*
20179 * Resolve the reference.
20180 * NULL the {term} by default.
20181 */
20182 particle->children = NULL;
20183
20184 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20185 ref->itemType, ref->name, ref->targetNamespace);
20186 if (refItem == NULL) {
20187 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20188 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20189 ref->targetNamespace, ref->itemType, NULL);
20190 /* TODO: remove the particle. */
20191 goto next_particle;
20192 }
20193 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20194 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20195 /* TODO: remove the particle. */
20196 goto next_particle;
20197 /*
20198 * NOTE that we will assign the model group definition
20199 * itself to the "term" of the particle. This will ease
20200 * the check for circular model group definitions. After
20201 * that the "term" will be assigned the model group of the
20202 * model group definition.
20203 */
20204 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20205 XML_SCHEMA_TYPE_ALL) {
20206 /*
20207 * SPEC cos-all-limited (1)
20208 * SPEC cos-all-limited (1.2)
20209 * "It appears only as the value of one or both of the
20210 * following properties:"
20211 * (1.1) "the {model group} property of a model group
20212 * definition."
20213 * (1.2) "the {term} property of a particle [... of] the "
20214 * {content type} of a complex type definition."
20215 */
20216 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20217 /* TODO: error code */
20218 XML_SCHEMAP_COS_ALL_LIMITED,
20219 WXS_ITEM_NODE(particle), NULL,
20220 "A model group definition is referenced, but "
20221 "it contains an 'all' model group, which "
20222 "cannot be contained by model groups",
20223 NULL, NULL);
20224 /* TODO: remove the particle. */
20225 goto next_particle;
20226 }
20227 particle->children = (xmlSchemaTreeItemPtr) refItem;
20228 } else {
20229 /*
20230 * TODO: Are referenced element declarations the only
20231 * other components we expect here?
20232 */
20233 particle->children = (xmlSchemaTreeItemPtr) refItem;
20234 }
20235 next_particle:
20236 particle = WXS_PTC_CAST particle->next;
20237 }
20238 }
20239
20240 static int
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,xmlSchemaValPtr y)20241 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20242 xmlSchemaValPtr y)
20243 {
20244 xmlSchemaTypePtr tx, ty, ptx, pty;
20245 int ret;
20246
20247 while (x != NULL) {
20248 /* Same types. */
20249 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20250 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20251 ptx = xmlSchemaGetPrimitiveType(tx);
20252 pty = xmlSchemaGetPrimitiveType(ty);
20253 /*
20254 * (1) if a datatype T' is `derived` by `restriction` from an
20255 * atomic datatype T then the `value space` of T' is a subset of
20256 * the `value space` of T. */
20257 /*
20258 * (2) if datatypes T' and T'' are `derived` by `restriction`
20259 * from a common atomic ancestor T then the `value space`s of T'
20260 * and T'' may overlap.
20261 */
20262 if (ptx != pty)
20263 return(0);
20264 /*
20265 * We assume computed values to be normalized, so do a fast
20266 * string comparison for string based types.
20267 */
20268 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20269 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20270 if (! xmlStrEqual(
20271 xmlSchemaValueGetAsString(x),
20272 xmlSchemaValueGetAsString(y)))
20273 return (0);
20274 } else {
20275 ret = xmlSchemaCompareValuesWhtsp(
20276 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20277 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20278 if (ret == -2)
20279 return(-1);
20280 if (ret != 0)
20281 return(0);
20282 }
20283 /*
20284 * Lists.
20285 */
20286 x = xmlSchemaValueGetNext(x);
20287 if (x != NULL) {
20288 y = xmlSchemaValueGetNext(y);
20289 if (y == NULL)
20290 return (0);
20291 } else if (xmlSchemaValueGetNext(y) != NULL)
20292 return (0);
20293 else
20294 return (1);
20295 }
20296 return (0);
20297 }
20298
20299 /**
20300 * xmlSchemaResolveAttrUseReferences:
20301 * @item: an attribute use
20302 * @ctxt: a parser context
20303 *
20304 * Resolves the referenced attribute declaration.
20305 */
20306 static int
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,xmlSchemaParserCtxtPtr ctxt)20307 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20308 xmlSchemaParserCtxtPtr ctxt)
20309 {
20310 if ((ctxt == NULL) || (ause == NULL))
20311 return(-1);
20312 if ((ause->attrDecl == NULL) ||
20313 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20314 return(0);
20315
20316 {
20317 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20318
20319 /*
20320 * TODO: Evaluate, what errors could occur if the declaration is not
20321 * found.
20322 */
20323 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20324 ref->name, ref->targetNamespace);
20325 if (ause->attrDecl == NULL) {
20326 xmlSchemaPResCompAttrErr(ctxt,
20327 XML_SCHEMAP_SRC_RESOLVE,
20328 WXS_BASIC_CAST ause, ause->node,
20329 "ref", ref->name, ref->targetNamespace,
20330 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20331 return(ctxt->err);;
20332 }
20333 }
20334 return(0);
20335 }
20336
20337 /**
20338 * xmlSchemaCheckAttrUsePropsCorrect:
20339 * @ctxt: a parser context
20340 * @use: an attribute use
20341 *
20342 * Schema Component Constraint:
20343 * Attribute Use Correct (au-props-correct)
20344 *
20345 */
20346 static int
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaAttributeUsePtr use)20347 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20348 xmlSchemaAttributeUsePtr use)
20349 {
20350 if ((ctxt == NULL) || (use == NULL))
20351 return(-1);
20352 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20353 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20354 return(0);
20355
20356 /*
20357 * SPEC au-props-correct (1)
20358 * "The values of the properties of an attribute use must be as
20359 * described in the property tableau in The Attribute Use Schema
20360 * Component ($3.5.1), modulo the impact of Missing
20361 * Sub-components ($5.3)."
20362 */
20363
20364 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20365 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20366 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20367 {
20368 xmlSchemaPCustomErr(ctxt,
20369 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20370 WXS_BASIC_CAST use, NULL,
20371 "The attribute declaration has a 'fixed' value constraint "
20372 ", thus the attribute use must also have a 'fixed' value "
20373 "constraint",
20374 NULL);
20375 return(ctxt->err);
20376 }
20377 /*
20378 * Compute and check the value constraint's value.
20379 */
20380 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20381 int ret;
20382 /*
20383 * TODO: The spec seems to be missing a check of the
20384 * value constraint of the attribute use. We will do it here.
20385 */
20386 /*
20387 * SPEC a-props-correct (3)
20388 */
20389 if (xmlSchemaIsDerivedFromBuiltInType(
20390 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20391 {
20392 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20393 XML_SCHEMAP_AU_PROPS_CORRECT,
20394 NULL, WXS_BASIC_CAST use,
20395 "Value constraints are not allowed if the type definition "
20396 "is or is derived from xs:ID",
20397 NULL, NULL);
20398 return(ctxt->err);
20399 }
20400
20401 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20402 use->node, WXS_ATTRUSE_TYPEDEF(use),
20403 use->defValue, &(use->defVal),
20404 1, 1, 0);
20405 if (ret != 0) {
20406 if (ret < 0) {
20407 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20408 "calling xmlSchemaVCheckCVCSimpleType()");
20409 return(-1);
20410 }
20411 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20412 XML_SCHEMAP_AU_PROPS_CORRECT,
20413 NULL, WXS_BASIC_CAST use,
20414 "The value of the value constraint is not valid",
20415 NULL, NULL);
20416 return(ctxt->err);
20417 }
20418 }
20419 /*
20420 * SPEC au-props-correct (2)
20421 * "If the {attribute declaration} has a fixed
20422 * {value constraint}, then if the attribute use itself has a
20423 * {value constraint}, it must also be fixed and its value must match
20424 * that of the {attribute declaration}'s {value constraint}."
20425 */
20426 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20427 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20428 {
20429 if (! xmlSchemaAreValuesEqual(use->defVal,
20430 (WXS_ATTRUSE_DECL(use))->defVal))
20431 {
20432 xmlSchemaPCustomErr(ctxt,
20433 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20434 WXS_BASIC_CAST use, NULL,
20435 "The 'fixed' value constraint of the attribute use "
20436 "must match the attribute declaration's value "
20437 "constraint '%s'",
20438 (WXS_ATTRUSE_DECL(use))->defValue);
20439 }
20440 return(ctxt->err);
20441 }
20442 return(0);
20443 }
20444
20445
20446
20447
20448 /**
20449 * xmlSchemaResolveAttrTypeReferences:
20450 * @item: an attribute declaration
20451 * @ctxt: a parser context
20452 *
20453 * Resolves the referenced type definition component.
20454 */
20455 static int
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,xmlSchemaParserCtxtPtr ctxt)20456 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20457 xmlSchemaParserCtxtPtr ctxt)
20458 {
20459 /*
20460 * The simple type definition corresponding to the <simpleType> element
20461 * information item in the [children], if present, otherwise the simple
20462 * type definition `resolved` to by the `actual value` of the type
20463 * [attribute], if present, otherwise the `simple ur-type definition`.
20464 */
20465 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20466 return(0);
20467 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20468 if (item->subtypes != NULL)
20469 return(0);
20470 if (item->typeName != NULL) {
20471 xmlSchemaTypePtr type;
20472
20473 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20474 item->typeNs);
20475 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20476 xmlSchemaPResCompAttrErr(ctxt,
20477 XML_SCHEMAP_SRC_RESOLVE,
20478 WXS_BASIC_CAST item, item->node,
20479 "type", item->typeName, item->typeNs,
20480 XML_SCHEMA_TYPE_SIMPLE, NULL);
20481 return(ctxt->err);
20482 } else
20483 item->subtypes = type;
20484
20485 } else {
20486 /*
20487 * The type defaults to the xs:anySimpleType.
20488 */
20489 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20490 }
20491 return(0);
20492 }
20493
20494 /**
20495 * xmlSchemaResolveIDCKeyReferences:
20496 * @idc: the identity-constraint definition
20497 * @ctxt: the schema parser context
20498 * @name: the attribute name
20499 *
20500 * Resolve keyRef references to key/unique IDCs.
20501 * Schema Component Constraint:
20502 * Identity-constraint Definition Properties Correct (c-props-correct)
20503 */
20504 static int
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,xmlSchemaParserCtxtPtr pctxt)20505 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20506 xmlSchemaParserCtxtPtr pctxt)
20507 {
20508 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20509 return(0);
20510 if (idc->ref->name != NULL) {
20511 idc->ref->item = (xmlSchemaBasicItemPtr)
20512 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20513 idc->ref->targetNamespace);
20514 if (idc->ref->item == NULL) {
20515 /*
20516 * TODO: It is actually not an error to fail to resolve
20517 * at this stage. BUT we need to be that strict!
20518 */
20519 xmlSchemaPResCompAttrErr(pctxt,
20520 XML_SCHEMAP_SRC_RESOLVE,
20521 WXS_BASIC_CAST idc, idc->node,
20522 "refer", idc->ref->name,
20523 idc->ref->targetNamespace,
20524 XML_SCHEMA_TYPE_IDC_KEY, NULL);
20525 return(pctxt->err);
20526 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20527 /*
20528 * SPEC c-props-correct (1)
20529 */
20530 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20531 XML_SCHEMAP_C_PROPS_CORRECT,
20532 NULL, WXS_BASIC_CAST idc,
20533 "The keyref references a keyref",
20534 NULL, NULL);
20535 idc->ref->item = NULL;
20536 return(pctxt->err);
20537 } else {
20538 if (idc->nbFields !=
20539 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20540 xmlChar *str = NULL;
20541 xmlSchemaIDCPtr refer;
20542
20543 refer = (xmlSchemaIDCPtr) idc->ref->item;
20544 /*
20545 * SPEC c-props-correct(2)
20546 * "If the {identity-constraint category} is keyref,
20547 * the cardinality of the {fields} must equal that of
20548 * the {fields} of the {referenced key}.
20549 */
20550 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20551 XML_SCHEMAP_C_PROPS_CORRECT,
20552 NULL, WXS_BASIC_CAST idc,
20553 "The cardinality of the keyref differs from the "
20554 "cardinality of the referenced key/unique '%s'",
20555 xmlSchemaFormatQName(&str, refer->targetNamespace,
20556 refer->name),
20557 NULL);
20558 FREE_AND_NULL(str)
20559 return(pctxt->err);
20560 }
20561 }
20562 }
20563 return(0);
20564 }
20565
20566 static int
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,xmlSchemaParserCtxtPtr pctxt)20567 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20568 xmlSchemaParserCtxtPtr pctxt)
20569 {
20570 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20571 prohib->targetNamespace) == NULL) {
20572
20573 xmlSchemaPResCompAttrErr(pctxt,
20574 XML_SCHEMAP_SRC_RESOLVE,
20575 NULL, prohib->node,
20576 "ref", prohib->name, prohib->targetNamespace,
20577 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20578 return(XML_SCHEMAP_SRC_RESOLVE);
20579 }
20580 return(0);
20581 }
20582
20583 #define WXS_REDEFINED_TYPE(c) \
20584 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20585
20586 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20587 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20588
20589 #define WXS_REDEFINED_ATTR_GROUP(c) \
20590 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20591
20592 static int
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)20593 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20594 {
20595 int err = 0;
20596 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20597 xmlSchemaBasicItemPtr prev, item;
20598 int wasRedefined;
20599
20600 if (redef == NULL)
20601 return(0);
20602
20603 do {
20604 item = redef->item;
20605 /*
20606 * First try to locate the redefined component in the
20607 * schema graph starting with the redefined schema.
20608 * NOTE: According to this schema bug entry:
20609 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20610 * it's not clear if the referenced component needs to originate
20611 * from the <redefine>d schema _document_ or the schema; the latter
20612 * would include all imported and included sub-schemas of the
20613 * <redefine>d schema. Currently the latter approach is used.
20614 * SUPPLEMENT: It seems that the WG moves towards the latter
20615 * approach, so we are doing it right.
20616 *
20617 */
20618 prev = xmlSchemaFindRedefCompInGraph(
20619 redef->targetBucket, item->type,
20620 redef->refName, redef->refTargetNs);
20621 if (prev == NULL) {
20622 xmlChar *str = NULL;
20623 xmlNodePtr node;
20624
20625 /*
20626 * SPEC src-redefine:
20627 * (6.2.1) "The `actual value` of its own name attribute plus
20628 * target namespace must successfully `resolve` to a model
20629 * group definition in I."
20630 * (7.2.1) "The `actual value` of its own name attribute plus
20631 * target namespace must successfully `resolve` to an attribute
20632 * group definition in I."
20633
20634 *
20635 * Note that, if we are redefining with the use of references
20636 * to components, the spec assumes the src-resolve to be used;
20637 * but this won't assure that we search only *inside* the
20638 * redefined schema.
20639 */
20640 if (redef->reference)
20641 node = WXS_ITEM_NODE(redef->reference);
20642 else
20643 node = WXS_ITEM_NODE(item);
20644 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20645 /*
20646 * TODO: error code.
20647 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20648 * reference kind.
20649 */
20650 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20651 "The %s '%s' to be redefined could not be found in "
20652 "the redefined schema",
20653 WXS_ITEM_TYPE_NAME(item),
20654 xmlSchemaFormatQName(&str, redef->refTargetNs,
20655 redef->refName));
20656 FREE_AND_NULL(str);
20657 err = pctxt->err;
20658 redef = redef->next;
20659 continue;
20660 }
20661 /*
20662 * TODO: Obtaining and setting the redefinition state is really
20663 * clumsy.
20664 */
20665 wasRedefined = 0;
20666 switch (item->type) {
20667 case XML_SCHEMA_TYPE_COMPLEX:
20668 case XML_SCHEMA_TYPE_SIMPLE:
20669 if ((WXS_TYPE_CAST prev)->flags &
20670 XML_SCHEMAS_TYPE_REDEFINED)
20671 {
20672 wasRedefined = 1;
20673 break;
20674 }
20675 /* Mark it as redefined. */
20676 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20677 /*
20678 * Assign the redefined type to the
20679 * base type of the redefining type.
20680 * TODO: How
20681 */
20682 ((xmlSchemaTypePtr) item)->baseType =
20683 (xmlSchemaTypePtr) prev;
20684 break;
20685 case XML_SCHEMA_TYPE_GROUP:
20686 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20687 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20688 {
20689 wasRedefined = 1;
20690 break;
20691 }
20692 /* Mark it as redefined. */
20693 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20694 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20695 if (redef->reference != NULL) {
20696 /*
20697 * Overwrite the QName-reference with the
20698 * referenced model group def.
20699 */
20700 (WXS_PTC_CAST redef->reference)->children =
20701 WXS_TREE_CAST prev;
20702 }
20703 redef->target = prev;
20704 break;
20705 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20706 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20707 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20708 {
20709 wasRedefined = 1;
20710 break;
20711 }
20712 (WXS_ATTR_GROUP_CAST prev)->flags |=
20713 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20714 if (redef->reference != NULL) {
20715 /*
20716 * Assign the redefined attribute group to the
20717 * QName-reference component.
20718 * This is the easy case, since we will just
20719 * expand the redefined group.
20720 */
20721 (WXS_QNAME_CAST redef->reference)->item = prev;
20722 redef->target = NULL;
20723 } else {
20724 /*
20725 * This is the complicated case: we need
20726 * to apply src-redefine (7.2.2) at a later
20727 * stage, i.e. when attribute group references
20728 * have been expanded and simple types have
20729 * been fixed.
20730 */
20731 redef->target = prev;
20732 }
20733 break;
20734 default:
20735 PERROR_INT("xmlSchemaResolveRedefReferences",
20736 "Unexpected redefined component type");
20737 return(-1);
20738 }
20739 if (wasRedefined) {
20740 xmlChar *str = NULL;
20741 xmlNodePtr node;
20742
20743 if (redef->reference)
20744 node = WXS_ITEM_NODE(redef->reference);
20745 else
20746 node = WXS_ITEM_NODE(redef->item);
20747
20748 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20749 /* TODO: error code. */
20750 XML_SCHEMAP_SRC_REDEFINE,
20751 node, NULL,
20752 "The referenced %s was already redefined. Multiple "
20753 "redefinition of the same component is not supported",
20754 xmlSchemaGetComponentDesignation(&str, prev),
20755 NULL);
20756 FREE_AND_NULL(str)
20757 err = pctxt->err;
20758 redef = redef->next;
20759 continue;
20760 }
20761 redef = redef->next;
20762 } while (redef != NULL);
20763
20764 return(err);
20765 }
20766
20767 static int
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)20768 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20769 {
20770 int err = 0;
20771 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20772 xmlSchemaBasicItemPtr item;
20773
20774 if (redef == NULL)
20775 return(0);
20776
20777 do {
20778 if (redef->target == NULL) {
20779 redef = redef->next;
20780 continue;
20781 }
20782 item = redef->item;
20783
20784 switch (item->type) {
20785 case XML_SCHEMA_TYPE_SIMPLE:
20786 case XML_SCHEMA_TYPE_COMPLEX:
20787 /*
20788 * Since the spec wants the {name} of the redefined
20789 * type to be 'absent', we'll NULL it.
20790 */
20791 (WXS_TYPE_CAST redef->target)->name = NULL;
20792
20793 /*
20794 * TODO: Seems like there's nothing more to do. The normal
20795 * inheritance mechanism is used. But not 100% sure.
20796 */
20797 break;
20798 case XML_SCHEMA_TYPE_GROUP:
20799 /*
20800 * URGENT TODO:
20801 * SPEC src-redefine:
20802 * (6.2.2) "The {model group} of the model group definition
20803 * which corresponds to it per XML Representation of Model
20804 * Group Definition Schema Components ($3.7.2) must be a
20805 * `valid restriction` of the {model group} of that model
20806 * group definition in I, as defined in Particle Valid
20807 * (Restriction) ($3.9.6)."
20808 */
20809 break;
20810 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20811 /*
20812 * SPEC src-redefine:
20813 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20814 * the attribute group definition which corresponds to it
20815 * per XML Representation of Attribute Group Definition Schema
20816 * Components ($3.6.2) must be `valid restrictions` of the
20817 * {attribute uses} and {attribute wildcard} of that attribute
20818 * group definition in I, as defined in clause 2, clause 3 and
20819 * clause 4 of Derivation Valid (Restriction, Complex)
20820 * ($3.4.6) (where references to the base type definition are
20821 * understood as references to the attribute group definition
20822 * in I)."
20823 */
20824 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20825 XML_SCHEMA_ACTION_REDEFINE,
20826 item, redef->target,
20827 (WXS_ATTR_GROUP_CAST item)->attrUses,
20828 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20829 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20830 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20831 if (err == -1)
20832 return(-1);
20833 break;
20834 default:
20835 break;
20836 }
20837 redef = redef->next;
20838 } while (redef != NULL);
20839 return(0);
20840 }
20841
20842
20843 static int
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr bucket)20844 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20845 xmlSchemaBucketPtr bucket)
20846 {
20847 xmlSchemaBasicItemPtr item;
20848 int err;
20849 xmlHashTablePtr *table;
20850 const xmlChar *name;
20851 int i;
20852
20853 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20854 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20855 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20856 else \
20857 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20858
20859 /*
20860 * Add global components to the schema's hash tables.
20861 * This is the place where duplicate components will be
20862 * detected.
20863 * TODO: I think normally we should support imports of the
20864 * same namespace from multiple locations. We don't do currently,
20865 * but if we do then according to:
20866 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20867 * we would need, if imported directly, to import redefined
20868 * components as well to be able to catch clashing components.
20869 * (I hope I'll still know what this means after some months :-()
20870 */
20871 if (bucket == NULL)
20872 return(-1);
20873 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20874 return(0);
20875 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20876
20877 for (i = 0; i < bucket->globals->nbItems; i++) {
20878 item = bucket->globals->items[i];
20879 table = NULL;
20880 switch (item->type) {
20881 case XML_SCHEMA_TYPE_COMPLEX:
20882 case XML_SCHEMA_TYPE_SIMPLE:
20883 if (WXS_REDEFINED_TYPE(item))
20884 continue;
20885 name = (WXS_TYPE_CAST item)->name;
20886 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20887 break;
20888 case XML_SCHEMA_TYPE_ELEMENT:
20889 name = (WXS_ELEM_CAST item)->name;
20890 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20891 break;
20892 case XML_SCHEMA_TYPE_ATTRIBUTE:
20893 name = (WXS_ATTR_CAST item)->name;
20894 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20895 break;
20896 case XML_SCHEMA_TYPE_GROUP:
20897 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20898 continue;
20899 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20900 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20901 break;
20902 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20903 if (WXS_REDEFINED_ATTR_GROUP(item))
20904 continue;
20905 name = (WXS_ATTR_GROUP_CAST item)->name;
20906 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20907 break;
20908 case XML_SCHEMA_TYPE_IDC_KEY:
20909 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20910 case XML_SCHEMA_TYPE_IDC_KEYREF:
20911 name = (WXS_IDC_CAST item)->name;
20912 WXS_GET_GLOBAL_HASH(bucket, idcDef)
20913 break;
20914 case XML_SCHEMA_TYPE_NOTATION:
20915 name = ((xmlSchemaNotationPtr) item)->name;
20916 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20917 break;
20918 default:
20919 PERROR_INT("xmlSchemaAddComponents",
20920 "Unexpected global component type");
20921 continue;
20922 }
20923 if (*table == NULL) {
20924 *table = xmlHashCreateDict(10, pctxt->dict);
20925 if (*table == NULL) {
20926 PERROR_INT("xmlSchemaAddComponents",
20927 "failed to create a component hash table");
20928 return(-1);
20929 }
20930 }
20931 err = xmlHashAddEntry(*table, name, item);
20932 if (err != 0) {
20933 xmlChar *str = NULL;
20934
20935 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20936 XML_SCHEMAP_REDEFINED_TYPE,
20937 WXS_ITEM_NODE(item),
20938 WXS_BASIC_CAST item,
20939 "A global %s '%s' does already exist",
20940 WXS_ITEM_TYPE_NAME(item),
20941 xmlSchemaGetComponentQName(&str, item));
20942 FREE_AND_NULL(str);
20943 }
20944 }
20945 /*
20946 * Process imported/included schemas.
20947 */
20948 if (bucket->relations != NULL) {
20949 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20950 do {
20951 if ((rel->bucket != NULL) &&
20952 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20953 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20954 return(-1);
20955 }
20956 rel = rel->next;
20957 } while (rel != NULL);
20958 }
20959 return(0);
20960 }
20961
20962 static int
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr rootBucket)20963 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20964 xmlSchemaBucketPtr rootBucket)
20965 {
20966 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20967 xmlSchemaTreeItemPtr item, *items;
20968 int nbItems, i, ret = 0;
20969 xmlSchemaBucketPtr oldbucket = con->bucket;
20970 xmlSchemaElementPtr elemDecl;
20971
20972 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20973
20974 if ((con->pending == NULL) ||
20975 (con->pending->nbItems == 0))
20976 return(0);
20977
20978 /*
20979 * Since xmlSchemaFixupComplexType() will create new particles
20980 * (local components), and those particle components need a bucket
20981 * on the constructor, we'll assure here that the constructor has
20982 * a bucket.
20983 * TODO: Think about storing locals _only_ on the main bucket.
20984 */
20985 if (con->bucket == NULL)
20986 con->bucket = rootBucket;
20987
20988 /* TODO:
20989 * SPEC (src-redefine):
20990 * (6.2) "If it has no such self-reference, then all of the
20991 * following must be true:"
20992
20993 * (6.2.2) The {model group} of the model group definition which
20994 * corresponds to it per XML Representation of Model Group
20995 * Definition Schema Components ($3.7.2) must be a `valid
20996 * restriction` of the {model group} of that model group definition
20997 * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20998 */
20999 xmlSchemaCheckSRCRedefineFirst(pctxt);
21000
21001 /*
21002 * Add global components to the schemata's hash tables.
21003 */
21004 xmlSchemaAddComponents(pctxt, rootBucket);
21005
21006 pctxt->ctxtType = NULL;
21007 items = (xmlSchemaTreeItemPtr *) con->pending->items;
21008 nbItems = con->pending->nbItems;
21009 /*
21010 * Now that we have parsed *all* the schema document(s) and converted
21011 * them to schema components, we can resolve references, apply component
21012 * constraints, create the FSA from the content model, etc.
21013 */
21014 /*
21015 * Resolve references of..
21016 *
21017 * 1. element declarations:
21018 * - the type definition
21019 * - the substitution group affiliation
21020 * 2. simple/complex types:
21021 * - the base type definition
21022 * - the memberTypes of union types
21023 * - the itemType of list types
21024 * 3. attributes declarations and attribute uses:
21025 * - the type definition
21026 * - if an attribute use, then the attribute declaration
21027 * 4. attribute group references:
21028 * - the attribute group definition
21029 * 5. particles:
21030 * - the term of the particle (e.g. a model group)
21031 * 6. IDC key-references:
21032 * - the referenced IDC 'key' or 'unique' definition
21033 * 7. Attribute prohibitions which had a "ref" attribute.
21034 */
21035 for (i = 0; i < nbItems; i++) {
21036 item = items[i];
21037 switch (item->type) {
21038 case XML_SCHEMA_TYPE_ELEMENT:
21039 xmlSchemaResolveElementReferences(
21040 (xmlSchemaElementPtr) item, pctxt);
21041 FIXHFAILURE;
21042 break;
21043 case XML_SCHEMA_TYPE_COMPLEX:
21044 case XML_SCHEMA_TYPE_SIMPLE:
21045 xmlSchemaResolveTypeReferences(
21046 (xmlSchemaTypePtr) item, pctxt);
21047 FIXHFAILURE;
21048 break;
21049 case XML_SCHEMA_TYPE_ATTRIBUTE:
21050 xmlSchemaResolveAttrTypeReferences(
21051 (xmlSchemaAttributePtr) item, pctxt);
21052 FIXHFAILURE;
21053 break;
21054 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21055 xmlSchemaResolveAttrUseReferences(
21056 (xmlSchemaAttributeUsePtr) item, pctxt);
21057 FIXHFAILURE;
21058 break;
21059 case XML_SCHEMA_EXTRA_QNAMEREF:
21060 if ((WXS_QNAME_CAST item)->itemType ==
21061 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
21062 {
21063 xmlSchemaResolveAttrGroupReferences(
21064 WXS_QNAME_CAST item, pctxt);
21065 }
21066 FIXHFAILURE;
21067 break;
21068 case XML_SCHEMA_TYPE_SEQUENCE:
21069 case XML_SCHEMA_TYPE_CHOICE:
21070 case XML_SCHEMA_TYPE_ALL:
21071 xmlSchemaResolveModelGroupParticleReferences(pctxt,
21072 WXS_MODEL_GROUP_CAST item);
21073 FIXHFAILURE;
21074 break;
21075 case XML_SCHEMA_TYPE_IDC_KEY:
21076 case XML_SCHEMA_TYPE_IDC_UNIQUE:
21077 case XML_SCHEMA_TYPE_IDC_KEYREF:
21078 xmlSchemaResolveIDCKeyReferences(
21079 (xmlSchemaIDCPtr) item, pctxt);
21080 FIXHFAILURE;
21081 break;
21082 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
21083 /*
21084 * Handle attribute prohibition which had a
21085 * "ref" attribute.
21086 */
21087 xmlSchemaResolveAttrUseProhibReferences(
21088 WXS_ATTR_PROHIB_CAST item, pctxt);
21089 FIXHFAILURE;
21090 break;
21091 default:
21092 break;
21093 }
21094 }
21095 if (pctxt->nberrors != 0)
21096 goto exit_error;
21097
21098 /*
21099 * Now that all references are resolved we
21100 * can check for circularity of...
21101 * 1. the base axis of type definitions
21102 * 2. nested model group definitions
21103 * 3. nested attribute group definitions
21104 * TODO: check for circular substitution groups.
21105 */
21106 for (i = 0; i < nbItems; i++) {
21107 item = items[i];
21108 /*
21109 * Let's better stop on the first error here.
21110 */
21111 switch (item->type) {
21112 case XML_SCHEMA_TYPE_COMPLEX:
21113 case XML_SCHEMA_TYPE_SIMPLE:
21114 xmlSchemaCheckTypeDefCircular(
21115 (xmlSchemaTypePtr) item, pctxt);
21116 FIXHFAILURE;
21117 if (pctxt->nberrors != 0)
21118 goto exit_error;
21119 break;
21120 case XML_SCHEMA_TYPE_GROUP:
21121 xmlSchemaCheckGroupDefCircular(
21122 (xmlSchemaModelGroupDefPtr) item, pctxt);
21123 FIXHFAILURE;
21124 if (pctxt->nberrors != 0)
21125 goto exit_error;
21126 break;
21127 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21128 xmlSchemaCheckAttrGroupCircular(
21129 (xmlSchemaAttributeGroupPtr) item, pctxt);
21130 FIXHFAILURE;
21131 if (pctxt->nberrors != 0)
21132 goto exit_error;
21133 break;
21134 default:
21135 break;
21136 }
21137 }
21138 if (pctxt->nberrors != 0)
21139 goto exit_error;
21140 /*
21141 * Model group definition references:
21142 * Such a reference is reflected by a particle at the component
21143 * level. Until now the 'term' of such particles pointed
21144 * to the model group definition; this was done, in order to
21145 * ease circularity checks. Now we need to set the 'term' of
21146 * such particles to the model group of the model group definition.
21147 */
21148 for (i = 0; i < nbItems; i++) {
21149 item = items[i];
21150 switch (item->type) {
21151 case XML_SCHEMA_TYPE_SEQUENCE:
21152 case XML_SCHEMA_TYPE_CHOICE:
21153 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21154 WXS_MODEL_GROUP_CAST item);
21155 break;
21156 default:
21157 break;
21158 }
21159 }
21160 if (pctxt->nberrors != 0)
21161 goto exit_error;
21162 /*
21163 * Expand attribute group references of attribute group definitions.
21164 */
21165 for (i = 0; i < nbItems; i++) {
21166 item = items[i];
21167 switch (item->type) {
21168 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21169 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21170 WXS_ATTR_GROUP_HAS_REFS(item))
21171 {
21172 xmlSchemaAttributeGroupExpandRefs(pctxt,
21173 WXS_ATTR_GROUP_CAST item);
21174 FIXHFAILURE;
21175 }
21176 break;
21177 default:
21178 break;
21179 }
21180 }
21181 if (pctxt->nberrors != 0)
21182 goto exit_error;
21183 /*
21184 * First compute the variety of simple types. This is needed as
21185 * a separate step, since otherwise we won't be able to detect
21186 * circular union types in all cases.
21187 */
21188 for (i = 0; i < nbItems; i++) {
21189 item = items[i];
21190 switch (item->type) {
21191 case XML_SCHEMA_TYPE_SIMPLE:
21192 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21193 xmlSchemaFixupSimpleTypeStageOne(pctxt,
21194 (xmlSchemaTypePtr) item);
21195 FIXHFAILURE;
21196 }
21197 break;
21198 default:
21199 break;
21200 }
21201 }
21202 if (pctxt->nberrors != 0)
21203 goto exit_error;
21204 /*
21205 * Detect circular union types. Note that this needs the variety to
21206 * be already computed.
21207 */
21208 for (i = 0; i < nbItems; i++) {
21209 item = items[i];
21210 switch (item->type) {
21211 case XML_SCHEMA_TYPE_SIMPLE:
21212 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21213 xmlSchemaCheckUnionTypeDefCircular(pctxt,
21214 (xmlSchemaTypePtr) item);
21215 FIXHFAILURE;
21216 }
21217 break;
21218 default:
21219 break;
21220 }
21221 }
21222 if (pctxt->nberrors != 0)
21223 goto exit_error;
21224
21225 /*
21226 * Do the complete type fixup for simple types.
21227 */
21228 for (i = 0; i < nbItems; i++) {
21229 item = items[i];
21230 switch (item->type) {
21231 case XML_SCHEMA_TYPE_SIMPLE:
21232 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21233 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21234 FIXHFAILURE;
21235 }
21236 break;
21237 default:
21238 break;
21239 }
21240 }
21241 if (pctxt->nberrors != 0)
21242 goto exit_error;
21243 /*
21244 * At this point we need build and check all simple types.
21245 */
21246 /*
21247 * Apply constraints for attribute declarations.
21248 */
21249 for (i = 0; i < nbItems; i++) {
21250 item = items[i];
21251 switch (item->type) {
21252 case XML_SCHEMA_TYPE_ATTRIBUTE:
21253 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21254 FIXHFAILURE;
21255 break;
21256 default:
21257 break;
21258 }
21259 }
21260 if (pctxt->nberrors != 0)
21261 goto exit_error;
21262 /*
21263 * Apply constraints for attribute uses.
21264 */
21265 for (i = 0; i < nbItems; i++) {
21266 item = items[i];
21267 switch (item->type) {
21268 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21269 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21270 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21271 WXS_ATTR_USE_CAST item);
21272 FIXHFAILURE;
21273 }
21274 break;
21275 default:
21276 break;
21277 }
21278 }
21279 if (pctxt->nberrors != 0)
21280 goto exit_error;
21281
21282 /*
21283 * Apply constraints for attribute group definitions.
21284 */
21285 for (i = 0; i < nbItems; i++) {
21286 item = items[i];
21287 switch (item->type) {
21288 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21289 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21290 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21291 {
21292 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21293 FIXHFAILURE;
21294 }
21295 break;
21296 default:
21297 break;
21298 }
21299 }
21300 if (pctxt->nberrors != 0)
21301 goto exit_error;
21302
21303 /*
21304 * Apply constraints for redefinitions.
21305 */
21306 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21307 xmlSchemaCheckSRCRedefineSecond(pctxt);
21308 if (pctxt->nberrors != 0)
21309 goto exit_error;
21310
21311 /*
21312 * Complex types are built and checked.
21313 */
21314 for (i = 0; i < nbItems; i++) {
21315 item = con->pending->items[i];
21316 switch (item->type) {
21317 case XML_SCHEMA_TYPE_COMPLEX:
21318 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21319 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21320 FIXHFAILURE;
21321 }
21322 break;
21323 default:
21324 break;
21325 }
21326 }
21327 if (pctxt->nberrors != 0)
21328 goto exit_error;
21329
21330 /*
21331 * The list could have changed, since xmlSchemaFixupComplexType()
21332 * will create particles and model groups in some cases.
21333 */
21334 items = (xmlSchemaTreeItemPtr *) con->pending->items;
21335 nbItems = con->pending->nbItems;
21336
21337 /*
21338 * Apply some constraints for element declarations.
21339 */
21340 for (i = 0; i < nbItems; i++) {
21341 item = items[i];
21342 switch (item->type) {
21343 case XML_SCHEMA_TYPE_ELEMENT:
21344 elemDecl = (xmlSchemaElementPtr) item;
21345
21346 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21347 {
21348 xmlSchemaCheckElementDeclComponent(
21349 (xmlSchemaElementPtr) elemDecl, pctxt);
21350 FIXHFAILURE;
21351 }
21352
21353 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21354 /*
21355 * Schema Component Constraint: Element Declarations Consistent
21356 * Apply this constraint to local types of element declarations.
21357 */
21358 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21359 (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21360 (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21361 {
21362 xmlSchemaCheckElementDeclConsistent(pctxt,
21363 WXS_BASIC_CAST elemDecl,
21364 WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21365 NULL, NULL, 0);
21366 }
21367 #endif
21368 break;
21369 default:
21370 break;
21371 }
21372 }
21373 if (pctxt->nberrors != 0)
21374 goto exit_error;
21375
21376 /*
21377 * Finally we can build the automaton from the content model of
21378 * complex types.
21379 */
21380
21381 for (i = 0; i < nbItems; i++) {
21382 item = items[i];
21383 switch (item->type) {
21384 case XML_SCHEMA_TYPE_COMPLEX:
21385 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21386 /* FIXHFAILURE; */
21387 break;
21388 default:
21389 break;
21390 }
21391 }
21392 if (pctxt->nberrors != 0)
21393 goto exit_error;
21394 /*
21395 * URGENT TODO: cos-element-consistent
21396 */
21397 goto exit;
21398
21399 exit_error:
21400 ret = pctxt->err;
21401 goto exit;
21402
21403 exit_failure:
21404 ret = -1;
21405
21406 exit:
21407 /*
21408 * Reset the constructor. This is needed for XSI acquisition, since
21409 * those items will be processed over and over again for every XSI
21410 * if not cleared here.
21411 */
21412 con->bucket = oldbucket;
21413 con->pending->nbItems = 0;
21414 if (con->substGroups != NULL) {
21415 xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21416 con->substGroups = NULL;
21417 }
21418 if (con->redefs != NULL) {
21419 xmlSchemaRedefListFree(con->redefs);
21420 con->redefs = NULL;
21421 }
21422 return(ret);
21423 }
21424 /**
21425 * xmlSchemaParse:
21426 * @ctxt: a schema validation context
21427 *
21428 * parse a schema definition resource and build an internal
21429 * XML Schema structure which can be used to validate instances.
21430 *
21431 * Returns the internal XML Schema structure built from the resource or
21432 * NULL in case of error
21433 */
21434 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)21435 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21436 {
21437 xmlSchemaPtr mainSchema = NULL;
21438 xmlSchemaBucketPtr bucket = NULL;
21439 int res;
21440
21441 /*
21442 * This one is used if the schema to be parsed was specified via
21443 * the API; i.e. not automatically by the validated instance document.
21444 */
21445
21446 xmlSchemaInitTypes();
21447
21448 if (ctxt == NULL)
21449 return (NULL);
21450
21451 /* TODO: Init the context. Is this all we need?*/
21452 ctxt->nberrors = 0;
21453 ctxt->err = 0;
21454 ctxt->counter = 0;
21455
21456 /* Create the *main* schema. */
21457 mainSchema = xmlSchemaNewSchema(ctxt);
21458 if (mainSchema == NULL)
21459 goto exit_failure;
21460 /*
21461 * Create the schema constructor.
21462 */
21463 if (ctxt->constructor == NULL) {
21464 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21465 if (ctxt->constructor == NULL)
21466 return(NULL);
21467 /* Take ownership of the constructor to be able to free it. */
21468 ctxt->ownsConstructor = 1;
21469 }
21470 ctxt->constructor->mainSchema = mainSchema;
21471 /*
21472 * Locate and add the schema document.
21473 */
21474 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21475 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21476 NULL, NULL, &bucket);
21477 if (res == -1)
21478 goto exit_failure;
21479 if (res != 0)
21480 goto exit;
21481
21482 if (bucket == NULL) {
21483 /* TODO: Error code, actually we failed to *locate* the schema. */
21484 if (ctxt->URL)
21485 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21486 NULL, NULL,
21487 "Failed to locate the main schema resource at '%s'",
21488 ctxt->URL, NULL);
21489 else
21490 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21491 NULL, NULL,
21492 "Failed to locate the main schema resource",
21493 NULL, NULL);
21494 goto exit;
21495 }
21496 /* Then do the parsing for good. */
21497 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21498 goto exit_failure;
21499 if (ctxt->nberrors != 0)
21500 goto exit;
21501
21502 mainSchema->doc = bucket->doc;
21503 mainSchema->preserve = ctxt->preserve;
21504
21505 ctxt->schema = mainSchema;
21506
21507 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21508 goto exit_failure;
21509
21510 /*
21511 * TODO: This is not nice, since we cannot distinguish from the
21512 * result if there was an internal error or not.
21513 */
21514 exit:
21515 if (ctxt->nberrors != 0) {
21516 if (mainSchema) {
21517 xmlSchemaFree(mainSchema);
21518 mainSchema = NULL;
21519 }
21520 if (ctxt->constructor) {
21521 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21522 ctxt->constructor = NULL;
21523 ctxt->ownsConstructor = 0;
21524 }
21525 }
21526 ctxt->schema = NULL;
21527 return(mainSchema);
21528 exit_failure:
21529 /*
21530 * Quite verbose, but should catch internal errors, which were
21531 * not communicated.
21532 */
21533 if (mainSchema) {
21534 xmlSchemaFree(mainSchema);
21535 mainSchema = NULL;
21536 }
21537 if (ctxt->constructor) {
21538 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21539 ctxt->constructor = NULL;
21540 ctxt->ownsConstructor = 0;
21541 }
21542 PERROR_INT2("xmlSchemaParse",
21543 "An internal error occurred");
21544 ctxt->schema = NULL;
21545 return(NULL);
21546 }
21547
21548 /**
21549 * xmlSchemaSetParserErrors:
21550 * @ctxt: a schema validation context
21551 * @err: the error callback
21552 * @warn: the warning callback
21553 * @ctx: contextual data for the callbacks
21554 *
21555 * Set the callback functions used to handle errors for a validation context
21556 */
21557 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)21558 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21559 xmlSchemaValidityErrorFunc err,
21560 xmlSchemaValidityWarningFunc warn, void *ctx)
21561 {
21562 if (ctxt == NULL)
21563 return;
21564 ctxt->error = err;
21565 ctxt->warning = warn;
21566 ctxt->errCtxt = ctx;
21567 if (ctxt->vctxt != NULL)
21568 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21569 }
21570
21571 /**
21572 * xmlSchemaSetParserStructuredErrors:
21573 * @ctxt: a schema parser context
21574 * @serror: the structured error function
21575 * @ctx: the functions context
21576 *
21577 * Set the structured error callback
21578 */
21579 void
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)21580 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21581 xmlStructuredErrorFunc serror,
21582 void *ctx)
21583 {
21584 if (ctxt == NULL)
21585 return;
21586 ctxt->serror = serror;
21587 ctxt->errCtxt = ctx;
21588 if (ctxt->vctxt != NULL)
21589 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21590 }
21591
21592 /**
21593 * xmlSchemaGetParserErrors:
21594 * @ctxt: a XMl-Schema parser context
21595 * @err: the error callback result
21596 * @warn: the warning callback result
21597 * @ctx: contextual data for the callbacks result
21598 *
21599 * Get the callback information used to handle errors for a parser context
21600 *
21601 * Returns -1 in case of failure, 0 otherwise
21602 */
21603 int
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)21604 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21605 xmlSchemaValidityErrorFunc * err,
21606 xmlSchemaValidityWarningFunc * warn, void **ctx)
21607 {
21608 if (ctxt == NULL)
21609 return(-1);
21610 if (err != NULL)
21611 *err = ctxt->error;
21612 if (warn != NULL)
21613 *warn = ctxt->warning;
21614 if (ctx != NULL)
21615 *ctx = ctxt->errCtxt;
21616 return(0);
21617 }
21618
21619 /**
21620 * xmlSchemaFacetTypeToString:
21621 * @type: the facet type
21622 *
21623 * Convert the xmlSchemaTypeType to a char string.
21624 *
21625 * Returns the char string representation of the facet type if the
21626 * type is a facet and an "Internal Error" string otherwise.
21627 */
21628 static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)21629 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21630 {
21631 switch (type) {
21632 case XML_SCHEMA_FACET_PATTERN:
21633 return (BAD_CAST "pattern");
21634 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21635 return (BAD_CAST "maxExclusive");
21636 case XML_SCHEMA_FACET_MAXINCLUSIVE:
21637 return (BAD_CAST "maxInclusive");
21638 case XML_SCHEMA_FACET_MINEXCLUSIVE:
21639 return (BAD_CAST "minExclusive");
21640 case XML_SCHEMA_FACET_MININCLUSIVE:
21641 return (BAD_CAST "minInclusive");
21642 case XML_SCHEMA_FACET_WHITESPACE:
21643 return (BAD_CAST "whiteSpace");
21644 case XML_SCHEMA_FACET_ENUMERATION:
21645 return (BAD_CAST "enumeration");
21646 case XML_SCHEMA_FACET_LENGTH:
21647 return (BAD_CAST "length");
21648 case XML_SCHEMA_FACET_MAXLENGTH:
21649 return (BAD_CAST "maxLength");
21650 case XML_SCHEMA_FACET_MINLENGTH:
21651 return (BAD_CAST "minLength");
21652 case XML_SCHEMA_FACET_TOTALDIGITS:
21653 return (BAD_CAST "totalDigits");
21654 case XML_SCHEMA_FACET_FRACTIONDIGITS:
21655 return (BAD_CAST "fractionDigits");
21656 default:
21657 break;
21658 }
21659 return (BAD_CAST "Internal Error");
21660 }
21661
21662 static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)21663 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21664 {
21665 /*
21666 * The normalization type can be changed only for types which are derived
21667 * from xsd:string.
21668 */
21669 if (type->type == XML_SCHEMA_TYPE_BASIC) {
21670 /*
21671 * Note that we assume a whitespace of preserve for anySimpleType.
21672 */
21673 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21674 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21675 return(XML_SCHEMA_WHITESPACE_PRESERVE);
21676 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21677 return(XML_SCHEMA_WHITESPACE_REPLACE);
21678 else {
21679 /*
21680 * For all `atomic` datatypes other than string (and types `derived`
21681 * by `restriction` from it) the value of whiteSpace is fixed to
21682 * collapse
21683 * Note that this includes built-in list datatypes.
21684 */
21685 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21686 }
21687 } else if (WXS_IS_LIST(type)) {
21688 /*
21689 * For list types the facet "whiteSpace" is fixed to "collapse".
21690 */
21691 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21692 } else if (WXS_IS_UNION(type)) {
21693 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21694 } else if (WXS_IS_ATOMIC(type)) {
21695 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21696 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21697 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21698 return (XML_SCHEMA_WHITESPACE_REPLACE);
21699 else
21700 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21701 }
21702 return (-1);
21703 }
21704
21705 /************************************************************************
21706 * *
21707 * Simple type validation *
21708 * *
21709 ************************************************************************/
21710
21711
21712 /************************************************************************
21713 * *
21714 * DOM Validation code *
21715 * *
21716 ************************************************************************/
21717
21718 /**
21719 * xmlSchemaAssembleByLocation:
21720 * @pctxt: a schema parser context
21721 * @vctxt: a schema validation context
21722 * @schema: the existing schema
21723 * @node: the node that fired the assembling
21724 * @nsName: the namespace name of the new schema
21725 * @location: the location of the schema
21726 *
21727 * Expands an existing schema by an additional schema.
21728 *
21729 * Returns 0 if the new schema is correct, a positive error code
21730 * number otherwise and -1 in case of an internal or API error.
21731 */
21732 static int
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * nsName,const xmlChar * location)21733 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21734 xmlSchemaPtr schema,
21735 xmlNodePtr node,
21736 const xmlChar *nsName,
21737 const xmlChar *location)
21738 {
21739 int ret = 0;
21740 xmlSchemaParserCtxtPtr pctxt;
21741 xmlSchemaBucketPtr bucket = NULL;
21742
21743 if ((vctxt == NULL) || (schema == NULL))
21744 return (-1);
21745
21746 if (vctxt->pctxt == NULL) {
21747 VERROR_INT("xmlSchemaAssembleByLocation",
21748 "no parser context available");
21749 return(-1);
21750 }
21751 pctxt = vctxt->pctxt;
21752 if (pctxt->constructor == NULL) {
21753 PERROR_INT("xmlSchemaAssembleByLocation",
21754 "no constructor");
21755 return(-1);
21756 }
21757 /*
21758 * Acquire the schema document.
21759 */
21760 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21761 location, node);
21762 /*
21763 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21764 * the process will automatically change this to
21765 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21766 */
21767 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21768 location, NULL, NULL, 0, node, NULL, nsName,
21769 &bucket);
21770 if (ret != 0)
21771 return(ret);
21772 if (bucket == NULL) {
21773 /*
21774 * Generate a warning that the document could not be located.
21775 */
21776 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21777 node, NULL,
21778 "The document at location '%s' could not be acquired",
21779 location, NULL, NULL);
21780 return(ret);
21781 }
21782 /*
21783 * The first located schema will be handled as if all other
21784 * schemas imported by XSI were imported by this first schema.
21785 */
21786 if ((bucket != NULL) &&
21787 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21788 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21789 /*
21790 * TODO: Is this handled like an import? I.e. is it not an error
21791 * if the schema cannot be located?
21792 */
21793 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21794 return(0);
21795 /*
21796 * We will reuse the parser context for every schema imported
21797 * directly via XSI. So reset the context.
21798 */
21799 pctxt->nberrors = 0;
21800 pctxt->err = 0;
21801 pctxt->doc = bucket->doc;
21802
21803 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21804 if (ret == -1) {
21805 pctxt->doc = NULL;
21806 goto exit_failure;
21807 }
21808 /* Paranoid error channelling. */
21809 if ((ret == 0) && (pctxt->nberrors != 0))
21810 ret = pctxt->err;
21811 if (pctxt->nberrors == 0) {
21812 /*
21813 * Only bother to fixup pending components, if there was
21814 * no error yet.
21815 * For every XSI acquired schema (and its sub-schemata) we will
21816 * fixup the components.
21817 */
21818 xmlSchemaFixupComponents(pctxt, bucket);
21819 ret = pctxt->err;
21820 /*
21821 * Not nice, but we need somehow to channel the schema parser
21822 * error to the validation context.
21823 */
21824 if ((ret != 0) && (vctxt->err == 0))
21825 vctxt->err = ret;
21826 vctxt->nberrors += pctxt->nberrors;
21827 } else {
21828 /* Add to validation error sum. */
21829 vctxt->nberrors += pctxt->nberrors;
21830 }
21831 pctxt->doc = NULL;
21832 return(ret);
21833 exit_failure:
21834 pctxt->doc = NULL;
21835 return (-1);
21836 }
21837
21838 static xmlSchemaAttrInfoPtr
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,int metaType)21839 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21840 int metaType)
21841 {
21842 if (vctxt->nbAttrInfos == 0)
21843 return (NULL);
21844 {
21845 int i;
21846 xmlSchemaAttrInfoPtr iattr;
21847
21848 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21849 iattr = vctxt->attrInfos[i];
21850 if (iattr->metaType == metaType)
21851 return (iattr);
21852 }
21853
21854 }
21855 return (NULL);
21856 }
21857
21858 /**
21859 * xmlSchemaAssembleByXSI:
21860 * @vctxt: a schema validation context
21861 *
21862 * Expands an existing schema by an additional schema using
21863 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21864 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21865 * must be set to 1.
21866 *
21867 * Returns 0 if the new schema is correct, a positive error code
21868 * number otherwise and -1 in case of an internal or API error.
21869 */
21870 static int
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)21871 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21872 {
21873 const xmlChar *cur, *end;
21874 const xmlChar *nsname = NULL, *location;
21875 int count = 0;
21876 int ret = 0;
21877 xmlSchemaAttrInfoPtr iattr;
21878
21879 /*
21880 * Parse the value; we will assume an even number of values
21881 * to be given (this is how Xerces and XSV work).
21882 *
21883 * URGENT TODO: !! This needs to work for both
21884 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21885 * element !!
21886 */
21887 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21888 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21889 if (iattr == NULL)
21890 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21891 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21892 if (iattr == NULL)
21893 return (0);
21894 cur = iattr->value;
21895 do {
21896 /*
21897 * TODO: Move the string parsing mechanism away from here.
21898 */
21899 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21900 /*
21901 * Get the namespace name.
21902 */
21903 while (IS_BLANK_CH(*cur))
21904 cur++;
21905 end = cur;
21906 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21907 end++;
21908 if (end == cur)
21909 break;
21910 count++; /* TODO: Don't use the schema's dict. */
21911 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21912 cur = end;
21913 }
21914 /*
21915 * Get the URI.
21916 */
21917 while (IS_BLANK_CH(*cur))
21918 cur++;
21919 end = cur;
21920 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21921 end++;
21922 if (end == cur) {
21923 if (iattr->metaType ==
21924 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21925 {
21926 /*
21927 * If using @schemaLocation then tuples are expected.
21928 * I.e. the namespace name *and* the document's URI.
21929 */
21930 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21931 iattr->node, NULL,
21932 "The value must consist of tuples: the target namespace "
21933 "name and the document's URI", NULL, NULL, NULL);
21934 }
21935 break;
21936 }
21937 count++; /* TODO: Don't use the schema's dict. */
21938 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21939 cur = end;
21940 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21941 iattr->node, nsname, location);
21942 if (ret == -1) {
21943 VERROR_INT("xmlSchemaAssembleByXSI",
21944 "assembling schemata");
21945 return (-1);
21946 }
21947 } while (*cur != 0);
21948 return (ret);
21949 }
21950
21951 static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,const xmlChar * prefix)21952 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21953 const xmlChar *prefix)
21954 {
21955 if (vctxt->sax != NULL) {
21956 int i, j;
21957 xmlSchemaNodeInfoPtr inode;
21958
21959 for (i = vctxt->depth; i >= 0; i--) {
21960 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21961 inode = vctxt->elemInfos[i];
21962 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21963 if (((prefix == NULL) &&
21964 (inode->nsBindings[j] == NULL)) ||
21965 ((prefix != NULL) && xmlStrEqual(prefix,
21966 inode->nsBindings[j]))) {
21967
21968 /*
21969 * Note that the namespace bindings are already
21970 * in a string dict.
21971 */
21972 return (inode->nsBindings[j+1]);
21973 }
21974 }
21975 }
21976 }
21977 return (NULL);
21978 #ifdef LIBXML_READER_ENABLED
21979 } else if (vctxt->reader != NULL) {
21980 xmlChar *nsName;
21981
21982 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21983 if (nsName != NULL) {
21984 const xmlChar *ret;
21985
21986 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21987 xmlFree(nsName);
21988 return (ret);
21989 } else
21990 return (NULL);
21991 #endif
21992 } else {
21993 xmlNsPtr ns;
21994
21995 if ((vctxt->inode->node == NULL) ||
21996 (vctxt->inode->node->doc == NULL)) {
21997 VERROR_INT("xmlSchemaLookupNamespace",
21998 "no node or node's doc available");
21999 return (NULL);
22000 }
22001 ns = xmlSearchNs(vctxt->inode->node->doc,
22002 vctxt->inode->node, prefix);
22003 if (ns != NULL)
22004 return (ns->href);
22005 return (NULL);
22006 }
22007 }
22008
22009 /*
22010 * This one works on the schema of the validation context.
22011 */
22012 static int
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)22013 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
22014 xmlSchemaPtr schema,
22015 xmlNodePtr node,
22016 const xmlChar *value,
22017 xmlSchemaValPtr *val,
22018 int valNeeded)
22019 {
22020 int ret;
22021
22022 if (vctxt && (vctxt->schema == NULL)) {
22023 VERROR_INT("xmlSchemaValidateNotation",
22024 "a schema is needed on the validation context");
22025 return (-1);
22026 }
22027 ret = xmlValidateQName(value, 1);
22028 if (ret != 0)
22029 return (ret);
22030 {
22031 xmlChar *localName = NULL;
22032 xmlChar *prefix = NULL;
22033
22034 localName = xmlSplitQName2(value, &prefix);
22035 if (prefix != NULL) {
22036 const xmlChar *nsName = NULL;
22037
22038 if (vctxt != NULL)
22039 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
22040 else if (node != NULL) {
22041 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
22042 if (ns != NULL)
22043 nsName = ns->href;
22044 } else {
22045 xmlFree(prefix);
22046 xmlFree(localName);
22047 return (1);
22048 }
22049 if (nsName == NULL) {
22050 xmlFree(prefix);
22051 xmlFree(localName);
22052 return (1);
22053 }
22054 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
22055 if ((valNeeded) && (val != NULL)) {
22056 (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
22057 xmlStrdup(nsName));
22058 if (*val == NULL)
22059 ret = -1;
22060 }
22061 } else
22062 ret = 1;
22063 xmlFree(prefix);
22064 xmlFree(localName);
22065 } else {
22066 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
22067 if (valNeeded && (val != NULL)) {
22068 (*val) = xmlSchemaNewNOTATIONValue(
22069 BAD_CAST xmlStrdup(value), NULL);
22070 if (*val == NULL)
22071 ret = -1;
22072 }
22073 } else
22074 return (1);
22075 }
22076 }
22077 return (ret);
22078 }
22079
22080 static int
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * lname,const xmlChar * nsname)22081 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
22082 const xmlChar* lname,
22083 const xmlChar* nsname)
22084 {
22085 int i;
22086
22087 lname = xmlDictLookup(vctxt->dict, lname, -1);
22088 if (lname == NULL)
22089 return(-1);
22090 if (nsname != NULL) {
22091 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
22092 if (nsname == NULL)
22093 return(-1);
22094 }
22095 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
22096 if ((vctxt->nodeQNames->items [i] == lname) &&
22097 (vctxt->nodeQNames->items[i +1] == nsname))
22098 /* Already there */
22099 return(i);
22100 }
22101 /* Add new entry. */
22102 i = vctxt->nodeQNames->nbItems;
22103 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
22104 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
22105 return(i);
22106 }
22107
22108 /************************************************************************
22109 * *
22110 * Validation of identity-constraints (IDC) *
22111 * *
22112 ************************************************************************/
22113
22114 /**
22115 * xmlSchemaAugmentIDC:
22116 * @idcDef: the IDC definition
22117 *
22118 * Creates an augmented IDC definition item.
22119 *
22120 * Returns the item, or NULL on internal errors.
22121 */
22122 static void
xmlSchemaAugmentIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)22123 xmlSchemaAugmentIDC(void *payload, void *data,
22124 const xmlChar *name ATTRIBUTE_UNUSED)
22125 {
22126 xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
22127 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22128 xmlSchemaIDCAugPtr aidc;
22129
22130 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
22131 if (aidc == NULL) {
22132 xmlSchemaVErrMemory(vctxt,
22133 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
22134 NULL);
22135 return;
22136 }
22137 aidc->keyrefDepth = -1;
22138 aidc->def = idcDef;
22139 aidc->next = NULL;
22140 if (vctxt->aidcs == NULL)
22141 vctxt->aidcs = aidc;
22142 else {
22143 aidc->next = vctxt->aidcs;
22144 vctxt->aidcs = aidc;
22145 }
22146 /*
22147 * Save if we have keyrefs at all.
22148 */
22149 if ((vctxt->hasKeyrefs == 0) &&
22150 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22151 vctxt->hasKeyrefs = 1;
22152 }
22153
22154 /**
22155 * xmlSchemaAugmentImportedIDC:
22156 * @imported: the imported schema
22157 *
22158 * Creates an augmented IDC definition for the imported schema.
22159 */
22160 static void
xmlSchemaAugmentImportedIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)22161 xmlSchemaAugmentImportedIDC(void *payload, void *data,
22162 const xmlChar *name ATTRIBUTE_UNUSED) {
22163 xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
22164 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22165 if (imported->schema->idcDef != NULL) {
22166 xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
22167 }
22168 }
22169
22170 /**
22171 * xmlSchemaIDCNewBinding:
22172 * @idcDef: the IDC definition of this binding
22173 *
22174 * Creates a new IDC binding.
22175 *
22176 * Returns the new IDC binding, NULL on internal errors.
22177 */
22178 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)22179 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22180 {
22181 xmlSchemaPSVIIDCBindingPtr ret;
22182
22183 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22184 sizeof(xmlSchemaPSVIIDCBinding));
22185 if (ret == NULL) {
22186 xmlSchemaVErrMemory(NULL,
22187 "allocating a PSVI IDC binding item", NULL);
22188 return (NULL);
22189 }
22190 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22191 ret->definition = idcDef;
22192 return (ret);
22193 }
22194
22195 /**
22196 * xmlSchemaIDCStoreNodeTableItem:
22197 * @vctxt: the WXS validation context
22198 * @item: the IDC node table item
22199 *
22200 * The validation context is used to store IDC node table items.
22201 * They are stored to avoid copying them if IDC node-tables are merged
22202 * with corresponding parent IDC node-tables (bubbling).
22203 *
22204 * Returns 0 if succeeded, -1 on internal errors.
22205 */
22206 static int
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCNodePtr item)22207 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22208 xmlSchemaPSVIIDCNodePtr item)
22209 {
22210 /*
22211 * Add to global list.
22212 */
22213 if (vctxt->idcNodes == NULL) {
22214 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22215 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22216 if (vctxt->idcNodes == NULL) {
22217 xmlSchemaVErrMemory(vctxt,
22218 "allocating the IDC node table item list", NULL);
22219 return (-1);
22220 }
22221 vctxt->sizeIdcNodes = 20;
22222 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22223 vctxt->sizeIdcNodes *= 2;
22224 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22225 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22226 sizeof(xmlSchemaPSVIIDCNodePtr));
22227 if (vctxt->idcNodes == NULL) {
22228 xmlSchemaVErrMemory(vctxt,
22229 "re-allocating the IDC node table item list", NULL);
22230 return (-1);
22231 }
22232 }
22233 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22234
22235 return (0);
22236 }
22237
22238 /**
22239 * xmlSchemaIDCStoreKey:
22240 * @vctxt: the WXS validation context
22241 * @item: the IDC key
22242 *
22243 * The validation context is used to store an IDC key.
22244 *
22245 * Returns 0 if succeeded, -1 on internal errors.
22246 */
22247 static int
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCKeyPtr key)22248 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22249 xmlSchemaPSVIIDCKeyPtr key)
22250 {
22251 /*
22252 * Add to global list.
22253 */
22254 if (vctxt->idcKeys == NULL) {
22255 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22256 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22257 if (vctxt->idcKeys == NULL) {
22258 xmlSchemaVErrMemory(vctxt,
22259 "allocating the IDC key storage list", NULL);
22260 return (-1);
22261 }
22262 vctxt->sizeIdcKeys = 40;
22263 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22264 vctxt->sizeIdcKeys *= 2;
22265 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22266 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22267 sizeof(xmlSchemaPSVIIDCKeyPtr));
22268 if (vctxt->idcKeys == NULL) {
22269 xmlSchemaVErrMemory(vctxt,
22270 "re-allocating the IDC key storage list", NULL);
22271 return (-1);
22272 }
22273 }
22274 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22275
22276 return (0);
22277 }
22278
22279 /**
22280 * xmlSchemaIDCAppendNodeTableItem:
22281 * @bind: the IDC binding
22282 * @ntItem: the node-table item
22283 *
22284 * Appends the IDC node-table item to the binding.
22285 *
22286 * Returns 0 on success and -1 on internal errors.
22287 */
22288 static int
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,xmlSchemaPSVIIDCNodePtr ntItem)22289 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22290 xmlSchemaPSVIIDCNodePtr ntItem)
22291 {
22292 if (bind->nodeTable == NULL) {
22293 bind->sizeNodes = 10;
22294 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22295 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22296 if (bind->nodeTable == NULL) {
22297 xmlSchemaVErrMemory(NULL,
22298 "allocating an array of IDC node-table items", NULL);
22299 return(-1);
22300 }
22301 } else if (bind->sizeNodes <= bind->nbNodes) {
22302 bind->sizeNodes *= 2;
22303 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22304 xmlRealloc(bind->nodeTable, bind->sizeNodes *
22305 sizeof(xmlSchemaPSVIIDCNodePtr));
22306 if (bind->nodeTable == NULL) {
22307 xmlSchemaVErrMemory(NULL,
22308 "re-allocating an array of IDC node-table items", NULL);
22309 return(-1);
22310 }
22311 }
22312 bind->nodeTable[bind->nbNodes++] = ntItem;
22313 return(0);
22314 }
22315
22316 /**
22317 * xmlSchemaIDCAcquireBinding:
22318 * @vctxt: the WXS validation context
22319 * @matcher: the IDC matcher
22320 *
22321 * Looks up an PSVI IDC binding, for the IDC definition and
22322 * of the given matcher. If none found, a new one is created
22323 * and added to the IDC table.
22324 *
22325 * Returns an IDC binding or NULL on internal errors.
22326 */
22327 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22328 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22329 xmlSchemaIDCMatcherPtr matcher)
22330 {
22331 xmlSchemaNodeInfoPtr ielem;
22332
22333 ielem = vctxt->elemInfos[matcher->depth];
22334
22335 if (ielem->idcTable == NULL) {
22336 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22337 if (ielem->idcTable == NULL)
22338 return (NULL);
22339 return(ielem->idcTable);
22340 } else {
22341 xmlSchemaPSVIIDCBindingPtr bind = NULL;
22342
22343 bind = ielem->idcTable;
22344 do {
22345 if (bind->definition == matcher->aidc->def)
22346 return(bind);
22347 if (bind->next == NULL) {
22348 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22349 if (bind->next == NULL)
22350 return (NULL);
22351 return(bind->next);
22352 }
22353 bind = bind->next;
22354 } while (bind != NULL);
22355 }
22356 return (NULL);
22357 }
22358
22359 static xmlSchemaItemListPtr
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,xmlSchemaIDCMatcherPtr matcher)22360 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22361 xmlSchemaIDCMatcherPtr matcher)
22362 {
22363 if (matcher->targets == NULL)
22364 matcher->targets = xmlSchemaItemListCreate();
22365 return(matcher->targets);
22366 }
22367
22368 /**
22369 * xmlSchemaIDCFreeKey:
22370 * @key: the IDC key
22371 *
22372 * Frees an IDC key together with its compiled value.
22373 */
22374 static void
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)22375 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22376 {
22377 if (key->val != NULL)
22378 xmlSchemaFreeValue(key->val);
22379 xmlFree(key);
22380 }
22381
22382 /**
22383 * xmlSchemaIDCFreeBinding:
22384 *
22385 * Frees an IDC binding. Note that the node table-items
22386 * are not freed.
22387 */
22388 static void
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)22389 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22390 {
22391 if (bind->nodeTable != NULL)
22392 xmlFree(bind->nodeTable);
22393 if (bind->dupls != NULL)
22394 xmlSchemaItemListFree(bind->dupls);
22395 xmlFree(bind);
22396 }
22397
22398 /**
22399 * xmlSchemaIDCFreeIDCTable:
22400 * @bind: the first IDC binding in the list
22401 *
22402 * Frees an IDC table, i.e. all the IDC bindings in the list.
22403 */
22404 static void
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)22405 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22406 {
22407 xmlSchemaPSVIIDCBindingPtr prev;
22408
22409 while (bind != NULL) {
22410 prev = bind;
22411 bind = bind->next;
22412 xmlSchemaIDCFreeBinding(prev);
22413 }
22414 }
22415
22416 static void
xmlFreeIDCHashEntry(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)22417 xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
22418 {
22419 xmlIDCHashEntryPtr e = payload, n;
22420 while (e) {
22421 n = e->next;
22422 xmlFree(e);
22423 e = n;
22424 }
22425 }
22426
22427 /**
22428 * xmlSchemaIDCFreeMatcherList:
22429 * @matcher: the first IDC matcher in the list
22430 *
22431 * Frees a list of IDC matchers.
22432 */
22433 static void
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)22434 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22435 {
22436 xmlSchemaIDCMatcherPtr next;
22437
22438 while (matcher != NULL) {
22439 next = matcher->next;
22440 if (matcher->keySeqs != NULL) {
22441 int i;
22442 for (i = 0; i < matcher->sizeKeySeqs; i++)
22443 if (matcher->keySeqs[i] != NULL)
22444 xmlFree(matcher->keySeqs[i]);
22445 xmlFree(matcher->keySeqs);
22446 }
22447 if (matcher->targets != NULL) {
22448 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22449 int i;
22450 xmlSchemaPSVIIDCNodePtr idcNode;
22451 /*
22452 * Node-table items for keyrefs are not stored globally
22453 * to the validation context, since they are not bubbled.
22454 * We need to free them here.
22455 */
22456 for (i = 0; i < matcher->targets->nbItems; i++) {
22457 idcNode =
22458 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22459 xmlFree(idcNode->keys);
22460 xmlFree(idcNode);
22461 }
22462 }
22463 xmlSchemaItemListFree(matcher->targets);
22464 }
22465 if (matcher->htab != NULL)
22466 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22467 xmlFree(matcher);
22468 matcher = next;
22469 }
22470 }
22471
22472 /**
22473 * xmlSchemaIDCReleaseMatcherList:
22474 * @vctxt: the WXS validation context
22475 * @matcher: the first IDC matcher in the list
22476 *
22477 * Caches a list of IDC matchers for reuse.
22478 */
22479 static void
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22480 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22481 xmlSchemaIDCMatcherPtr matcher)
22482 {
22483 xmlSchemaIDCMatcherPtr next;
22484
22485 while (matcher != NULL) {
22486 next = matcher->next;
22487 if (matcher->keySeqs != NULL) {
22488 int i;
22489 /*
22490 * Don't free the array, but only the content.
22491 */
22492 for (i = 0; i < matcher->sizeKeySeqs; i++)
22493 if (matcher->keySeqs[i] != NULL) {
22494 xmlFree(matcher->keySeqs[i]);
22495 matcher->keySeqs[i] = NULL;
22496 }
22497 }
22498 if (matcher->targets) {
22499 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22500 int i;
22501 xmlSchemaPSVIIDCNodePtr idcNode;
22502 /*
22503 * Node-table items for keyrefs are not stored globally
22504 * to the validation context, since they are not bubbled.
22505 * We need to free them here.
22506 */
22507 for (i = 0; i < matcher->targets->nbItems; i++) {
22508 idcNode =
22509 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22510 xmlFree(idcNode->keys);
22511 xmlFree(idcNode);
22512 }
22513 }
22514 xmlSchemaItemListFree(matcher->targets);
22515 matcher->targets = NULL;
22516 }
22517 if (matcher->htab != NULL) {
22518 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22519 matcher->htab = NULL;
22520 }
22521 matcher->next = NULL;
22522 /*
22523 * Cache the matcher.
22524 */
22525 if (vctxt->idcMatcherCache != NULL)
22526 matcher->nextCached = vctxt->idcMatcherCache;
22527 vctxt->idcMatcherCache = matcher;
22528
22529 matcher = next;
22530 }
22531 }
22532
22533 /**
22534 * xmlSchemaIDCAddStateObject:
22535 * @vctxt: the WXS validation context
22536 * @matcher: the IDC matcher
22537 * @sel: the XPath information
22538 * @parent: the parent "selector" state object if any
22539 * @type: "selector" or "field"
22540 *
22541 * Creates/reuses and activates state objects for the given
22542 * XPath information; if the XPath expression consists of unions,
22543 * multiple state objects are created for every unioned expression.
22544 *
22545 * Returns 0 on success and -1 on internal errors.
22546 */
22547 static int
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher,xmlSchemaIDCSelectPtr sel,int type)22548 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22549 xmlSchemaIDCMatcherPtr matcher,
22550 xmlSchemaIDCSelectPtr sel,
22551 int type)
22552 {
22553 xmlSchemaIDCStateObjPtr sto;
22554
22555 /*
22556 * Reuse the state objects from the pool.
22557 */
22558 if (vctxt->xpathStatePool != NULL) {
22559 sto = vctxt->xpathStatePool;
22560 vctxt->xpathStatePool = sto->next;
22561 sto->next = NULL;
22562 } else {
22563 /*
22564 * Create a new state object.
22565 */
22566 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22567 if (sto == NULL) {
22568 xmlSchemaVErrMemory(NULL,
22569 "allocating an IDC state object", NULL);
22570 return (-1);
22571 }
22572 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22573 }
22574 /*
22575 * Add to global list.
22576 */
22577 if (vctxt->xpathStates != NULL)
22578 sto->next = vctxt->xpathStates;
22579 vctxt->xpathStates = sto;
22580
22581 /*
22582 * Free the old xpath validation context.
22583 */
22584 if (sto->xpathCtxt != NULL)
22585 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22586
22587 /*
22588 * Create a new XPath (pattern) validation context.
22589 */
22590 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22591 (xmlPatternPtr) sel->xpathComp);
22592 if (sto->xpathCtxt == NULL) {
22593 VERROR_INT("xmlSchemaIDCAddStateObject",
22594 "failed to create an XPath validation context");
22595 return (-1);
22596 }
22597 sto->type = type;
22598 sto->depth = vctxt->depth;
22599 sto->matcher = matcher;
22600 sto->sel = sel;
22601 sto->nbHistory = 0;
22602
22603 #ifdef DEBUG_IDC
22604 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22605 sto->sel->xpath);
22606 #endif
22607 return (0);
22608 }
22609
22610 /**
22611 * xmlSchemaXPathEvaluate:
22612 * @vctxt: the WXS validation context
22613 * @nodeType: the nodeType of the current node
22614 *
22615 * Evaluates all active XPath state objects.
22616 *
22617 * Returns the number of IC "field" state objects which resolved to
22618 * this node, 0 if none resolved and -1 on internal errors.
22619 */
22620 static int
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,xmlElementType nodeType)22621 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22622 xmlElementType nodeType)
22623 {
22624 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22625 int res, resolved = 0, depth = vctxt->depth;
22626
22627 if (vctxt->xpathStates == NULL)
22628 return (0);
22629
22630 if (nodeType == XML_ATTRIBUTE_NODE)
22631 depth++;
22632 #ifdef DEBUG_IDC
22633 {
22634 xmlChar *str = NULL;
22635 xmlGenericError(xmlGenericErrorContext,
22636 "IDC: EVAL on %s, depth %d, type %d\n",
22637 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22638 vctxt->inode->localName), depth, nodeType);
22639 FREE_AND_NULL(str)
22640 }
22641 #endif
22642 /*
22643 * Process all active XPath state objects.
22644 */
22645 first = vctxt->xpathStates;
22646 sto = first;
22647 while (sto != head) {
22648 #ifdef DEBUG_IDC
22649 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22650 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22651 sto->matcher->aidc->def->name, sto->sel->xpath);
22652 else
22653 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22654 sto->matcher->aidc->def->name, sto->sel->xpath);
22655 #endif
22656 if (nodeType == XML_ELEMENT_NODE)
22657 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22658 vctxt->inode->localName, vctxt->inode->nsName);
22659 else
22660 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22661 vctxt->inode->localName, vctxt->inode->nsName);
22662
22663 if (res == -1) {
22664 VERROR_INT("xmlSchemaXPathEvaluate",
22665 "calling xmlStreamPush()");
22666 return (-1);
22667 }
22668 if (res == 0)
22669 goto next_sto;
22670 /*
22671 * Full match.
22672 */
22673 #ifdef DEBUG_IDC
22674 xmlGenericError(xmlGenericErrorContext, "IDC: "
22675 "MATCH\n");
22676 #endif
22677 /*
22678 * Register a match in the state object history.
22679 */
22680 if (sto->history == NULL) {
22681 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22682 if (sto->history == NULL) {
22683 xmlSchemaVErrMemory(NULL,
22684 "allocating the state object history", NULL);
22685 return(-1);
22686 }
22687 sto->sizeHistory = 5;
22688 } else if (sto->sizeHistory <= sto->nbHistory) {
22689 sto->sizeHistory *= 2;
22690 sto->history = (int *) xmlRealloc(sto->history,
22691 sto->sizeHistory * sizeof(int));
22692 if (sto->history == NULL) {
22693 xmlSchemaVErrMemory(NULL,
22694 "re-allocating the state object history", NULL);
22695 return(-1);
22696 }
22697 }
22698 sto->history[sto->nbHistory++] = depth;
22699
22700 #ifdef DEBUG_IDC
22701 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22702 vctxt->depth);
22703 #endif
22704
22705 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22706 xmlSchemaIDCSelectPtr sel;
22707 /*
22708 * Activate state objects for the IDC fields of
22709 * the IDC selector.
22710 */
22711 #ifdef DEBUG_IDC
22712 xmlGenericError(xmlGenericErrorContext, "IDC: "
22713 "activating field states\n");
22714 #endif
22715 sel = sto->matcher->aidc->def->fields;
22716 while (sel != NULL) {
22717 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22718 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22719 return (-1);
22720 sel = sel->next;
22721 }
22722 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22723 /*
22724 * An IDC key node was found by the IDC field.
22725 */
22726 #ifdef DEBUG_IDC
22727 xmlGenericError(xmlGenericErrorContext,
22728 "IDC: key found\n");
22729 #endif
22730 /*
22731 * Notify that the character value of this node is
22732 * needed.
22733 */
22734 if (resolved == 0) {
22735 if ((vctxt->inode->flags &
22736 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22737 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22738 }
22739 resolved++;
22740 }
22741 next_sto:
22742 if (sto->next == NULL) {
22743 /*
22744 * Evaluate field state objects created on this node as well.
22745 */
22746 head = first;
22747 sto = vctxt->xpathStates;
22748 } else
22749 sto = sto->next;
22750 }
22751 return (resolved);
22752 }
22753
22754 static const xmlChar *
xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count,int for_hash)22755 xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
22756 xmlChar **buf,
22757 xmlSchemaPSVIIDCKeyPtr *seq,
22758 int count, int for_hash)
22759 {
22760 int i, res;
22761 xmlChar *value = NULL;
22762
22763 *buf = xmlStrdup(BAD_CAST "[");
22764 for (i = 0; i < count; i++) {
22765 *buf = xmlStrcat(*buf, BAD_CAST "'");
22766 if (!for_hash)
22767 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22768 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22769 &value);
22770 else {
22771 res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
22772 }
22773 if (res == 0)
22774 *buf = xmlStrcat(*buf, BAD_CAST value);
22775 else {
22776 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22777 "failed to compute a canonical value");
22778 *buf = xmlStrcat(*buf, BAD_CAST "???");
22779 }
22780 if (i < count -1)
22781 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22782 else
22783 *buf = xmlStrcat(*buf, BAD_CAST "'");
22784 if (value != NULL) {
22785 xmlFree(value);
22786 value = NULL;
22787 }
22788 }
22789 *buf = xmlStrcat(*buf, BAD_CAST "]");
22790
22791 return (BAD_CAST *buf);
22792 }
22793
22794 static const xmlChar *
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22795 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22796 xmlChar **buf,
22797 xmlSchemaPSVIIDCKeyPtr *seq,
22798 int count)
22799 {
22800 return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
22801 }
22802
22803 static const xmlChar *
xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22804 xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
22805 xmlChar **buf,
22806 xmlSchemaPSVIIDCKeyPtr *seq,
22807 int count)
22808 {
22809 return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
22810 }
22811
22812 /**
22813 * xmlSchemaXPathPop:
22814 * @vctxt: the WXS validation context
22815 *
22816 * Pops all XPath states.
22817 *
22818 * Returns 0 on success and -1 on internal errors.
22819 */
22820 static int
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)22821 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22822 {
22823 xmlSchemaIDCStateObjPtr sto;
22824 int res;
22825
22826 if (vctxt->xpathStates == NULL)
22827 return(0);
22828 sto = vctxt->xpathStates;
22829 do {
22830 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22831 if (res == -1)
22832 return (-1);
22833 sto = sto->next;
22834 } while (sto != NULL);
22835 return(0);
22836 }
22837
22838 /**
22839 * xmlSchemaXPathProcessHistory:
22840 * @vctxt: the WXS validation context
22841 * @type: the simple/complex type of the current node if any at all
22842 * @val: the precompiled value
22843 *
22844 * Processes and pops the history items of the IDC state objects.
22845 * IDC key-sequences are validated/created on IDC bindings.
22846 *
22847 * Returns 0 on success and -1 on internal errors.
22848 */
22849 static int
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,int depth)22850 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22851 int depth)
22852 {
22853 xmlSchemaIDCStateObjPtr sto, nextsto;
22854 int res, matchDepth;
22855 xmlSchemaPSVIIDCKeyPtr key = NULL;
22856 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22857
22858 if (vctxt->xpathStates == NULL)
22859 return (0);
22860 sto = vctxt->xpathStates;
22861
22862 #ifdef DEBUG_IDC
22863 {
22864 xmlChar *str = NULL;
22865 xmlGenericError(xmlGenericErrorContext,
22866 "IDC: BACK on %s, depth %d\n",
22867 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22868 vctxt->inode->localName), vctxt->depth);
22869 FREE_AND_NULL(str)
22870 }
22871 #endif
22872 /*
22873 * Evaluate the state objects.
22874 */
22875 while (sto != NULL) {
22876 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22877 if (res == -1) {
22878 VERROR_INT("xmlSchemaXPathProcessHistory",
22879 "calling xmlStreamPop()");
22880 return (-1);
22881 }
22882 #ifdef DEBUG_IDC
22883 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22884 sto->sel->xpath);
22885 #endif
22886 if (sto->nbHistory == 0)
22887 goto deregister_check;
22888
22889 matchDepth = sto->history[sto->nbHistory -1];
22890
22891 /*
22892 * Only matches at the current depth are of interest.
22893 */
22894 if (matchDepth != depth) {
22895 sto = sto->next;
22896 continue;
22897 }
22898 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22899 /*
22900 * NOTE: According to
22901 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22902 * ... the simple-content of complex types is also allowed.
22903 */
22904
22905 if (WXS_IS_COMPLEX(type)) {
22906 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22907 /*
22908 * Sanity check for complex types with simple content.
22909 */
22910 simpleType = type->contentTypeDef;
22911 if (simpleType == NULL) {
22912 VERROR_INT("xmlSchemaXPathProcessHistory",
22913 "field resolves to a CT with simple content "
22914 "but the CT is missing the ST definition");
22915 return (-1);
22916 }
22917 } else
22918 simpleType = NULL;
22919 } else
22920 simpleType = type;
22921 if (simpleType == NULL) {
22922 xmlChar *str = NULL;
22923
22924 /*
22925 * Not qualified if the field resolves to a node of non
22926 * simple type.
22927 */
22928 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22929 XML_SCHEMAV_CVC_IDC, NULL,
22930 WXS_BASIC_CAST sto->matcher->aidc->def,
22931 "The XPath '%s' of a field of %s does evaluate to a node of "
22932 "non-simple type",
22933 sto->sel->xpath,
22934 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22935 FREE_AND_NULL(str);
22936 sto->nbHistory--;
22937 goto deregister_check;
22938 }
22939
22940 if ((key == NULL) && (vctxt->inode->val == NULL)) {
22941 /*
22942 * Failed to provide the normalized value; maybe
22943 * the value was invalid.
22944 */
22945 VERROR(XML_SCHEMAV_CVC_IDC,
22946 WXS_BASIC_CAST sto->matcher->aidc->def,
22947 "Warning: No precomputed value available, the value "
22948 "was either invalid or something strange happened");
22949 sto->nbHistory--;
22950 goto deregister_check;
22951 } else {
22952 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22953 xmlSchemaPSVIIDCKeyPtr *keySeq;
22954 int pos, idx;
22955
22956 /*
22957 * The key will be anchored on the matcher's list of
22958 * key-sequences. The position in this list is determined
22959 * by the target node's depth relative to the matcher's
22960 * depth of creation (i.e. the depth of the scope element).
22961 *
22962 * Element Depth Pos List-entries
22963 * <scope> 0 NULL
22964 * <bar> 1 NULL
22965 * <target/> 2 2 target
22966 * <bar>
22967 * </scope>
22968 *
22969 * The size of the list is only dependent on the depth of
22970 * the tree.
22971 * An entry will be NULLed in selector_leave, i.e. when
22972 * we hit the target's
22973 */
22974 pos = sto->depth - matcher->depth;
22975 idx = sto->sel->index;
22976
22977 /*
22978 * Create/grow the array of key-sequences.
22979 */
22980 if (matcher->keySeqs == NULL) {
22981 if (pos > 9)
22982 matcher->sizeKeySeqs = pos * 2;
22983 else
22984 matcher->sizeKeySeqs = 10;
22985 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22986 xmlMalloc(matcher->sizeKeySeqs *
22987 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22988 if (matcher->keySeqs == NULL) {
22989 xmlSchemaVErrMemory(NULL,
22990 "allocating an array of key-sequences",
22991 NULL);
22992 return(-1);
22993 }
22994 memset(matcher->keySeqs, 0,
22995 matcher->sizeKeySeqs *
22996 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22997 } else if (pos >= matcher->sizeKeySeqs) {
22998 int i = matcher->sizeKeySeqs;
22999
23000 matcher->sizeKeySeqs *= 2;
23001 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
23002 xmlRealloc(matcher->keySeqs,
23003 matcher->sizeKeySeqs *
23004 sizeof(xmlSchemaPSVIIDCKeyPtr *));
23005 if (matcher->keySeqs == NULL) {
23006 xmlSchemaVErrMemory(NULL,
23007 "reallocating an array of key-sequences",
23008 NULL);
23009 return (-1);
23010 }
23011 /*
23012 * The array needs to be NULLed.
23013 * TODO: Use memset?
23014 */
23015 for (; i < matcher->sizeKeySeqs; i++)
23016 matcher->keySeqs[i] = NULL;
23017 }
23018
23019 /*
23020 * Get/create the key-sequence.
23021 */
23022 keySeq = matcher->keySeqs[pos];
23023 if (keySeq == NULL) {
23024 goto create_sequence;
23025 } else if (keySeq[idx] != NULL) {
23026 xmlChar *str = NULL;
23027 /*
23028 * cvc-identity-constraint:
23029 * 3 For each node in the `target node set` all
23030 * of the {fields}, with that node as the context
23031 * node, evaluate to either an empty node-set or
23032 * a node-set with exactly one member, which must
23033 * have a simple type.
23034 *
23035 * The key was already set; report an error.
23036 */
23037 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23038 XML_SCHEMAV_CVC_IDC, NULL,
23039 WXS_BASIC_CAST matcher->aidc->def,
23040 "The XPath '%s' of a field of %s evaluates to a "
23041 "node-set with more than one member",
23042 sto->sel->xpath,
23043 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
23044 FREE_AND_NULL(str);
23045 sto->nbHistory--;
23046 goto deregister_check;
23047 } else
23048 goto create_key;
23049
23050 create_sequence:
23051 /*
23052 * Create a key-sequence.
23053 */
23054 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
23055 matcher->aidc->def->nbFields *
23056 sizeof(xmlSchemaPSVIIDCKeyPtr));
23057 if (keySeq == NULL) {
23058 xmlSchemaVErrMemory(NULL,
23059 "allocating an IDC key-sequence", NULL);
23060 return(-1);
23061 }
23062 memset(keySeq, 0, matcher->aidc->def->nbFields *
23063 sizeof(xmlSchemaPSVIIDCKeyPtr));
23064 matcher->keySeqs[pos] = keySeq;
23065 create_key:
23066 /*
23067 * Create a key once per node only.
23068 */
23069 if (key == NULL) {
23070 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
23071 sizeof(xmlSchemaPSVIIDCKey));
23072 if (key == NULL) {
23073 xmlSchemaVErrMemory(NULL,
23074 "allocating a IDC key", NULL);
23075 xmlFree(keySeq);
23076 matcher->keySeqs[pos] = NULL;
23077 return(-1);
23078 }
23079 /*
23080 * Consume the compiled value.
23081 */
23082 key->type = simpleType;
23083 key->val = vctxt->inode->val;
23084 vctxt->inode->val = NULL;
23085 /*
23086 * Store the key in a global list.
23087 */
23088 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
23089 xmlSchemaIDCFreeKey(key);
23090 return (-1);
23091 }
23092 }
23093 keySeq[idx] = key;
23094 }
23095 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
23096
23097 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
23098 /* xmlSchemaPSVIIDCBindingPtr bind; */
23099 xmlSchemaPSVIIDCNodePtr ntItem;
23100 xmlSchemaIDCMatcherPtr matcher;
23101 xmlSchemaIDCPtr idc;
23102 xmlSchemaItemListPtr targets;
23103 int pos, i, j, nbKeys;
23104 /*
23105 * Here we have the following scenario:
23106 * An IDC 'selector' state object resolved to a target node,
23107 * during the time this target node was in the
23108 * ancestor-or-self axis, the 'field' state object(s) looked
23109 * out for matching nodes to create a key-sequence for this
23110 * target node. Now we are back to this target node and need
23111 * to put the key-sequence, together with the target node
23112 * itself, into the node-table of the corresponding IDC
23113 * binding.
23114 */
23115 matcher = sto->matcher;
23116 idc = matcher->aidc->def;
23117 nbKeys = idc->nbFields;
23118 pos = depth - matcher->depth;
23119 /*
23120 * Check if the matcher has any key-sequences at all, plus
23121 * if it has a key-sequence for the current target node.
23122 */
23123 if ((matcher->keySeqs == NULL) ||
23124 (matcher->sizeKeySeqs <= pos)) {
23125 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23126 goto selector_key_error;
23127 else
23128 goto selector_leave;
23129 }
23130
23131 keySeq = &(matcher->keySeqs[pos]);
23132 if (*keySeq == NULL) {
23133 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23134 goto selector_key_error;
23135 else
23136 goto selector_leave;
23137 }
23138
23139 for (i = 0; i < nbKeys; i++) {
23140 if ((*keySeq)[i] == NULL) {
23141 /*
23142 * Not qualified, if not all fields did resolve.
23143 */
23144 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
23145 /*
23146 * All fields of a "key" IDC must resolve.
23147 */
23148 goto selector_key_error;
23149 }
23150 goto selector_leave;
23151 }
23152 }
23153 /*
23154 * All fields did resolve.
23155 */
23156
23157 /*
23158 * 4.1 If the {identity-constraint category} is unique(/key),
23159 * then no two members of the `qualified node set` have
23160 * `key-sequences` whose members are pairwise equal, as
23161 * defined by Equal in [XML Schemas: Datatypes].
23162 *
23163 * Get the IDC binding from the matcher and check for
23164 * duplicate key-sequences.
23165 */
23166 #if 0
23167 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23168 #endif
23169 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
23170 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
23171 (targets->nbItems != 0)) {
23172 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
23173 xmlIDCHashEntryPtr e;
23174
23175 res = 0;
23176
23177 if (!matcher->htab)
23178 e = NULL;
23179 else {
23180 xmlChar *value = NULL;
23181 xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
23182 e = xmlHashLookup(matcher->htab, value);
23183 FREE_AND_NULL(value);
23184 }
23185
23186 /*
23187 * Compare the key-sequences, key by key.
23188 */
23189 for (;e; e = e->next) {
23190 bkeySeq =
23191 ((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
23192 for (j = 0; j < nbKeys; j++) {
23193 ckey = (*keySeq)[j];
23194 bkey = bkeySeq[j];
23195 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23196 if (res == -1) {
23197 return (-1);
23198 } else if (res == 0) {
23199 /*
23200 * One of the keys differs, so the key-sequence
23201 * won't be equal; get out.
23202 */
23203 break;
23204 }
23205 }
23206 if (res == 1) {
23207 /*
23208 * Duplicate key-sequence found.
23209 */
23210 break;
23211 }
23212 }
23213 if (e) {
23214 xmlChar *str = NULL, *strB = NULL;
23215 /*
23216 * TODO: Try to report the key-sequence.
23217 */
23218 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23219 XML_SCHEMAV_CVC_IDC, NULL,
23220 WXS_BASIC_CAST idc,
23221 "Duplicate key-sequence %s in %s",
23222 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23223 (*keySeq), nbKeys),
23224 xmlSchemaGetIDCDesignation(&strB, idc));
23225 FREE_AND_NULL(str);
23226 FREE_AND_NULL(strB);
23227 goto selector_leave;
23228 }
23229 }
23230 /*
23231 * Add a node-table item to the IDC binding.
23232 */
23233 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23234 sizeof(xmlSchemaPSVIIDCNode));
23235 if (ntItem == NULL) {
23236 xmlSchemaVErrMemory(NULL,
23237 "allocating an IDC node-table item", NULL);
23238 xmlFree(*keySeq);
23239 *keySeq = NULL;
23240 return(-1);
23241 }
23242 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23243
23244 /*
23245 * Store the node-table item in a global list.
23246 */
23247 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23248 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23249 xmlFree(ntItem);
23250 xmlFree(*keySeq);
23251 *keySeq = NULL;
23252 return (-1);
23253 }
23254 ntItem->nodeQNameID = -1;
23255 } else {
23256 /*
23257 * Save a cached QName for this node on the IDC node, to be
23258 * able to report it, even if the node is not saved.
23259 */
23260 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23261 vctxt->inode->localName, vctxt->inode->nsName);
23262 if (ntItem->nodeQNameID == -1) {
23263 xmlFree(ntItem);
23264 xmlFree(*keySeq);
23265 *keySeq = NULL;
23266 return (-1);
23267 }
23268 }
23269 /*
23270 * Init the node-table item: Save the node, position and
23271 * consume the key-sequence.
23272 */
23273 ntItem->node = vctxt->node;
23274 ntItem->nodeLine = vctxt->inode->nodeLine;
23275 ntItem->keys = *keySeq;
23276 *keySeq = NULL;
23277 #if 0
23278 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23279 #endif
23280 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23281 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23282 /*
23283 * Free the item, since keyref items won't be
23284 * put on a global list.
23285 */
23286 xmlFree(ntItem->keys);
23287 xmlFree(ntItem);
23288 }
23289 return (-1);
23290 }
23291 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23292 xmlChar *value = NULL;
23293 xmlIDCHashEntryPtr r, e;
23294 if (!matcher->htab)
23295 matcher->htab = xmlHashCreate(4);
23296 xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
23297 e = xmlMalloc(sizeof *e);
23298 e->index = targets->nbItems - 1;
23299 r = xmlHashLookup(matcher->htab, value);
23300 if (r) {
23301 e->next = r->next;
23302 r->next = e;
23303 } else {
23304 e->next = NULL;
23305 xmlHashAddEntry(matcher->htab, value, e);
23306 }
23307 FREE_AND_NULL(value);
23308 }
23309
23310 goto selector_leave;
23311 selector_key_error:
23312 {
23313 xmlChar *str = NULL;
23314 /*
23315 * 4.2.1 (KEY) The `target node set` and the
23316 * `qualified node set` are equal, that is, every
23317 * member of the `target node set` is also a member
23318 * of the `qualified node set` and vice versa.
23319 */
23320 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23321 XML_SCHEMAV_CVC_IDC, NULL,
23322 WXS_BASIC_CAST idc,
23323 "Not all fields of %s evaluate to a node",
23324 xmlSchemaGetIDCDesignation(&str, idc), NULL);
23325 FREE_AND_NULL(str);
23326 }
23327 selector_leave:
23328 /*
23329 * Free the key-sequence if not added to the IDC table.
23330 */
23331 if ((keySeq != NULL) && (*keySeq != NULL)) {
23332 xmlFree(*keySeq);
23333 *keySeq = NULL;
23334 }
23335 } /* if selector */
23336
23337 sto->nbHistory--;
23338
23339 deregister_check:
23340 /*
23341 * Deregister state objects if they reach the depth of creation.
23342 */
23343 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23344 #ifdef DEBUG_IDC
23345 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
23346 sto->sel->xpath);
23347 #endif
23348 if (vctxt->xpathStates != sto) {
23349 VERROR_INT("xmlSchemaXPathProcessHistory",
23350 "The state object to be removed is not the first "
23351 "in the list");
23352 }
23353 nextsto = sto->next;
23354 /*
23355 * Unlink from the list of active XPath state objects.
23356 */
23357 vctxt->xpathStates = sto->next;
23358 sto->next = vctxt->xpathStatePool;
23359 /*
23360 * Link it to the pool of reusable state objects.
23361 */
23362 vctxt->xpathStatePool = sto;
23363 sto = nextsto;
23364 } else
23365 sto = sto->next;
23366 } /* while (sto != NULL) */
23367 return (0);
23368 }
23369
23370 /**
23371 * xmlSchemaIDCRegisterMatchers:
23372 * @vctxt: the WXS validation context
23373 * @elemDecl: the element declaration
23374 *
23375 * Creates helper objects to evaluate IDC selectors/fields
23376 * successively.
23377 *
23378 * Returns 0 if OK and -1 on internal errors.
23379 */
23380 static int
xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,xmlSchemaElementPtr elemDecl)23381 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23382 xmlSchemaElementPtr elemDecl)
23383 {
23384 xmlSchemaIDCMatcherPtr matcher, last = NULL;
23385 xmlSchemaIDCPtr idc, refIdc;
23386 xmlSchemaIDCAugPtr aidc;
23387
23388 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23389 if (idc == NULL)
23390 return (0);
23391
23392 #ifdef DEBUG_IDC
23393 {
23394 xmlChar *str = NULL;
23395 xmlGenericError(xmlGenericErrorContext,
23396 "IDC: REGISTER on %s, depth %d\n",
23397 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23398 vctxt->inode->localName), vctxt->depth);
23399 FREE_AND_NULL(str)
23400 }
23401 #endif
23402 if (vctxt->inode->idcMatchers != NULL) {
23403 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23404 "The chain of IDC matchers is expected to be empty");
23405 return (-1);
23406 }
23407 do {
23408 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23409 /*
23410 * Since IDCs bubbles are expensive we need to know the
23411 * depth at which the bubbles should stop; this will be
23412 * the depth of the top-most keyref IDC. If no keyref
23413 * references a key/unique IDC, the keyrefDepth will
23414 * be -1, indicating that no bubbles are needed.
23415 */
23416 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23417 if (refIdc != NULL) {
23418 /*
23419 * Remember that we have keyrefs on this node.
23420 */
23421 vctxt->inode->hasKeyrefs = 1;
23422 /*
23423 * Lookup the referenced augmented IDC info.
23424 */
23425 aidc = vctxt->aidcs;
23426 while (aidc != NULL) {
23427 if (aidc->def == refIdc)
23428 break;
23429 aidc = aidc->next;
23430 }
23431 if (aidc == NULL) {
23432 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23433 "Could not find an augmented IDC item for an IDC "
23434 "definition");
23435 return (-1);
23436 }
23437 if ((aidc->keyrefDepth == -1) ||
23438 (vctxt->depth < aidc->keyrefDepth))
23439 aidc->keyrefDepth = vctxt->depth;
23440 }
23441 }
23442 /*
23443 * Lookup the augmented IDC item for the IDC definition.
23444 */
23445 aidc = vctxt->aidcs;
23446 while (aidc != NULL) {
23447 if (aidc->def == idc)
23448 break;
23449 aidc = aidc->next;
23450 }
23451 if (aidc == NULL) {
23452 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23453 "Could not find an augmented IDC item for an IDC definition");
23454 return (-1);
23455 }
23456 /*
23457 * Create an IDC matcher for every IDC definition.
23458 */
23459 if (vctxt->idcMatcherCache != NULL) {
23460 /*
23461 * Reuse a cached matcher.
23462 */
23463 matcher = vctxt->idcMatcherCache;
23464 vctxt->idcMatcherCache = matcher->nextCached;
23465 matcher->nextCached = NULL;
23466 } else {
23467 matcher = (xmlSchemaIDCMatcherPtr)
23468 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23469 if (matcher == NULL) {
23470 xmlSchemaVErrMemory(vctxt,
23471 "allocating an IDC matcher", NULL);
23472 return (-1);
23473 }
23474 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23475 }
23476 if (last == NULL)
23477 vctxt->inode->idcMatchers = matcher;
23478 else
23479 last->next = matcher;
23480 last = matcher;
23481
23482 matcher->type = IDC_MATCHER;
23483 matcher->depth = vctxt->depth;
23484 matcher->aidc = aidc;
23485 matcher->idcType = aidc->def->type;
23486 #ifdef DEBUG_IDC
23487 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
23488 #endif
23489 /*
23490 * Init the automaton state object.
23491 */
23492 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23493 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23494 return (-1);
23495
23496 idc = idc->next;
23497 } while (idc != NULL);
23498 return (0);
23499 }
23500
23501 static int
xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23502 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23503 xmlSchemaNodeInfoPtr ielem)
23504 {
23505 xmlSchemaPSVIIDCBindingPtr bind;
23506 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23507 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23508 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23509
23510 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23511 /* vctxt->createIDCNodeTables */
23512 while (matcher != NULL) {
23513 /*
23514 * Skip keyref IDCs and empty IDC target-lists.
23515 */
23516 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23517 WXS_ILIST_IS_EMPTY(matcher->targets))
23518 {
23519 matcher = matcher->next;
23520 continue;
23521 }
23522 /*
23523 * If we _want_ the IDC node-table to be created in any case
23524 * then do so. Otherwise create them only if keyrefs need them.
23525 */
23526 if ((! vctxt->createIDCNodeTables) &&
23527 ((matcher->aidc->keyrefDepth == -1) ||
23528 (matcher->aidc->keyrefDepth > vctxt->depth)))
23529 {
23530 matcher = matcher->next;
23531 continue;
23532 }
23533 /*
23534 * Get/create the IDC binding on this element for the IDC definition.
23535 */
23536 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23537 if (bind == NULL)
23538 goto internal_error;
23539
23540 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23541 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23542 nbDupls = bind->dupls->nbItems;
23543 } else {
23544 dupls = NULL;
23545 nbDupls = 0;
23546 }
23547 if (bind->nodeTable != NULL) {
23548 nbNodeTable = bind->nbNodes;
23549 } else {
23550 nbNodeTable = 0;
23551 }
23552
23553 if ((nbNodeTable == 0) && (nbDupls == 0)) {
23554 /*
23555 * Transfer all IDC target-nodes to the IDC node-table.
23556 */
23557 bind->nodeTable =
23558 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23559 bind->sizeNodes = matcher->targets->sizeItems;
23560 bind->nbNodes = matcher->targets->nbItems;
23561
23562 matcher->targets->items = NULL;
23563 matcher->targets->sizeItems = 0;
23564 matcher->targets->nbItems = 0;
23565 if (matcher->htab) {
23566 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
23567 matcher->htab = NULL;
23568 }
23569 } else {
23570 /*
23571 * Compare the key-sequences and add to the IDC node-table.
23572 */
23573 nbTargets = matcher->targets->nbItems;
23574 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23575 nbFields = matcher->aidc->def->nbFields;
23576 i = 0;
23577 do {
23578 keys = targets[i]->keys;
23579 if (nbDupls) {
23580 /*
23581 * Search in already found duplicates first.
23582 */
23583 j = 0;
23584 do {
23585 if (nbFields == 1) {
23586 res = xmlSchemaAreValuesEqual(keys[0]->val,
23587 dupls[j]->keys[0]->val);
23588 if (res == -1)
23589 goto internal_error;
23590 if (res == 1) {
23591 /*
23592 * Equal key-sequence.
23593 */
23594 goto next_target;
23595 }
23596 } else {
23597 res = 0;
23598 ntkeys = dupls[j]->keys;
23599 for (k = 0; k < nbFields; k++) {
23600 res = xmlSchemaAreValuesEqual(keys[k]->val,
23601 ntkeys[k]->val);
23602 if (res == -1)
23603 goto internal_error;
23604 if (res == 0) {
23605 /*
23606 * One of the keys differs.
23607 */
23608 break;
23609 }
23610 }
23611 if (res == 1) {
23612 /*
23613 * Equal key-sequence found.
23614 */
23615 goto next_target;
23616 }
23617 }
23618 j++;
23619 } while (j < nbDupls);
23620 }
23621 if (nbNodeTable) {
23622 j = 0;
23623 do {
23624 if (nbFields == 1) {
23625 res = xmlSchemaAreValuesEqual(keys[0]->val,
23626 bind->nodeTable[j]->keys[0]->val);
23627 if (res == -1)
23628 goto internal_error;
23629 if (res == 0) {
23630 /*
23631 * The key-sequence differs.
23632 */
23633 goto next_node_table_entry;
23634 }
23635 } else {
23636 res = 0;
23637 ntkeys = bind->nodeTable[j]->keys;
23638 for (k = 0; k < nbFields; k++) {
23639 res = xmlSchemaAreValuesEqual(keys[k]->val,
23640 ntkeys[k]->val);
23641 if (res == -1)
23642 goto internal_error;
23643 if (res == 0) {
23644 /*
23645 * One of the keys differs.
23646 */
23647 goto next_node_table_entry;
23648 }
23649 }
23650 }
23651 /*
23652 * Add the duplicate to the list of duplicates.
23653 */
23654 if (bind->dupls == NULL) {
23655 bind->dupls = xmlSchemaItemListCreate();
23656 if (bind->dupls == NULL)
23657 goto internal_error;
23658 }
23659 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23660 goto internal_error;
23661 /*
23662 * Remove the duplicate entry from the IDC node-table.
23663 */
23664 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23665 bind->nbNodes--;
23666
23667 goto next_target;
23668
23669 next_node_table_entry:
23670 j++;
23671 } while (j < nbNodeTable);
23672 }
23673 /*
23674 * If everything is fine, then add the IDC target-node to
23675 * the IDC node-table.
23676 */
23677 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23678 goto internal_error;
23679
23680 next_target:
23681 i++;
23682 } while (i < nbTargets);
23683 }
23684 matcher = matcher->next;
23685 }
23686 return(0);
23687
23688 internal_error:
23689 return(-1);
23690 }
23691
23692 /**
23693 * xmlSchemaBubbleIDCNodeTables:
23694 * @depth: the current tree depth
23695 *
23696 * Merges IDC bindings of an element at @depth into the corresponding IDC
23697 * bindings of its parent element. If a duplicate note-table entry is found,
23698 * both, the parent node-table entry and child entry are discarded from the
23699 * node-table of the parent.
23700 *
23701 * Returns 0 if OK and -1 on internal errors.
23702 */
23703 static int
xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)23704 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23705 {
23706 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23707 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23708 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23709 xmlSchemaIDCAugPtr aidc;
23710 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23711
23712 bind = vctxt->inode->idcTable;
23713 if (bind == NULL) {
23714 /* Fine, no table, no bubbles. */
23715 return (0);
23716 }
23717
23718 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23719 /*
23720 * Walk all bindings; create new or add to existing bindings.
23721 * Remove duplicate key-sequences.
23722 */
23723 while (bind != NULL) {
23724
23725 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23726 goto next_binding;
23727 /*
23728 * Check if the key/unique IDC table needs to be bubbled.
23729 */
23730 if (! vctxt->createIDCNodeTables) {
23731 aidc = vctxt->aidcs;
23732 do {
23733 if (aidc->def == bind->definition) {
23734 if ((aidc->keyrefDepth == -1) ||
23735 (aidc->keyrefDepth >= vctxt->depth)) {
23736 goto next_binding;
23737 }
23738 break;
23739 }
23740 aidc = aidc->next;
23741 } while (aidc != NULL);
23742 }
23743
23744 if (parTable != NULL)
23745 parBind = *parTable;
23746 /*
23747 * Search a matching parent binding for the
23748 * IDC definition.
23749 */
23750 while (parBind != NULL) {
23751 if (parBind->definition == bind->definition)
23752 break;
23753 parBind = parBind->next;
23754 }
23755
23756 if (parBind != NULL) {
23757 /*
23758 * Compare every node-table entry of the child node,
23759 * i.e. the key-sequence within, ...
23760 */
23761 oldNum = parBind->nbNodes; /* Skip newly added items. */
23762
23763 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23764 oldDupls = parBind->dupls->nbItems;
23765 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23766 } else {
23767 dupls = NULL;
23768 oldDupls = 0;
23769 }
23770
23771 parNodes = parBind->nodeTable;
23772 nbFields = bind->definition->nbFields;
23773
23774 for (i = 0; i < bind->nbNodes; i++) {
23775 node = bind->nodeTable[i];
23776 if (node == NULL)
23777 continue;
23778 /*
23779 * ...with every key-sequence of the parent node, already
23780 * evaluated to be a duplicate key-sequence.
23781 */
23782 if (oldDupls) {
23783 j = 0;
23784 while (j < oldDupls) {
23785 if (nbFields == 1) {
23786 ret = xmlSchemaAreValuesEqual(
23787 node->keys[0]->val,
23788 dupls[j]->keys[0]->val);
23789 if (ret == -1)
23790 goto internal_error;
23791 if (ret == 0) {
23792 j++;
23793 continue;
23794 }
23795 } else {
23796 parNode = dupls[j];
23797 for (k = 0; k < nbFields; k++) {
23798 ret = xmlSchemaAreValuesEqual(
23799 node->keys[k]->val,
23800 parNode->keys[k]->val);
23801 if (ret == -1)
23802 goto internal_error;
23803 if (ret == 0)
23804 break;
23805 }
23806 }
23807 if (ret == 1)
23808 /* Duplicate found. */
23809 break;
23810 j++;
23811 }
23812 if (j != oldDupls) {
23813 /* Duplicate found. Skip this entry. */
23814 continue;
23815 }
23816 }
23817 /*
23818 * ... and with every key-sequence of the parent node.
23819 */
23820 if (oldNum) {
23821 j = 0;
23822 while (j < oldNum) {
23823 parNode = parNodes[j];
23824 if (nbFields == 1) {
23825 ret = xmlSchemaAreValuesEqual(
23826 node->keys[0]->val,
23827 parNode->keys[0]->val);
23828 if (ret == -1)
23829 goto internal_error;
23830 if (ret == 0) {
23831 j++;
23832 continue;
23833 }
23834 } else {
23835 for (k = 0; k < nbFields; k++) {
23836 ret = xmlSchemaAreValuesEqual(
23837 node->keys[k]->val,
23838 parNode->keys[k]->val);
23839 if (ret == -1)
23840 goto internal_error;
23841 if (ret == 0)
23842 break;
23843 }
23844 }
23845 if (ret == 1)
23846 /* Duplicate found. */
23847 break;
23848 j++;
23849 }
23850 if (j != oldNum) {
23851 /*
23852 * Handle duplicates. Move the duplicate in
23853 * the parent's node-table to the list of
23854 * duplicates.
23855 */
23856 oldNum--;
23857 parBind->nbNodes--;
23858 /*
23859 * Move last old item to pos of duplicate.
23860 */
23861 parNodes[j] = parNodes[oldNum];
23862
23863 if (parBind->nbNodes != oldNum) {
23864 /*
23865 * If new items exist, move last new item to
23866 * last of old items.
23867 */
23868 parNodes[oldNum] =
23869 parNodes[parBind->nbNodes];
23870 }
23871 if (parBind->dupls == NULL) {
23872 parBind->dupls = xmlSchemaItemListCreate();
23873 if (parBind->dupls == NULL)
23874 goto internal_error;
23875 }
23876 xmlSchemaItemListAdd(parBind->dupls, parNode);
23877 } else {
23878 /*
23879 * Add the node-table entry (node and key-sequence) of
23880 * the child node to the node table of the parent node.
23881 */
23882 if (parBind->nodeTable == NULL) {
23883 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23884 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23885 if (parBind->nodeTable == NULL) {
23886 xmlSchemaVErrMemory(NULL,
23887 "allocating IDC list of node-table items", NULL);
23888 goto internal_error;
23889 }
23890 parBind->sizeNodes = 1;
23891 } else if (parBind->nbNodes >= parBind->sizeNodes) {
23892 parBind->sizeNodes *= 2;
23893 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23894 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23895 sizeof(xmlSchemaPSVIIDCNodePtr));
23896 if (parBind->nodeTable == NULL) {
23897 xmlSchemaVErrMemory(NULL,
23898 "re-allocating IDC list of node-table items", NULL);
23899 goto internal_error;
23900 }
23901 }
23902 parNodes = parBind->nodeTable;
23903 /*
23904 * Append the new node-table entry to the 'new node-table
23905 * entries' section.
23906 */
23907 parNodes[parBind->nbNodes++] = node;
23908 }
23909
23910 }
23911
23912 }
23913 } else {
23914 /*
23915 * No binding for the IDC was found: create a new one and
23916 * copy all node-tables.
23917 */
23918 parBind = xmlSchemaIDCNewBinding(bind->definition);
23919 if (parBind == NULL)
23920 goto internal_error;
23921
23922 /*
23923 * TODO: Hmm, how to optimize the initial number of
23924 * allocated entries?
23925 */
23926 if (bind->nbNodes != 0) {
23927 /*
23928 * Add all IDC node-table entries.
23929 */
23930 if (! vctxt->psviExposeIDCNodeTables) {
23931 /*
23932 * Just move the entries.
23933 * NOTE: this is quite save here, since
23934 * all the keyref lookups have already been
23935 * performed.
23936 */
23937 parBind->nodeTable = bind->nodeTable;
23938 bind->nodeTable = NULL;
23939 parBind->sizeNodes = bind->sizeNodes;
23940 bind->sizeNodes = 0;
23941 parBind->nbNodes = bind->nbNodes;
23942 bind->nbNodes = 0;
23943 } else {
23944 /*
23945 * Copy the entries.
23946 */
23947 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23948 xmlMalloc(bind->nbNodes *
23949 sizeof(xmlSchemaPSVIIDCNodePtr));
23950 if (parBind->nodeTable == NULL) {
23951 xmlSchemaVErrMemory(NULL,
23952 "allocating an array of IDC node-table "
23953 "items", NULL);
23954 xmlSchemaIDCFreeBinding(parBind);
23955 goto internal_error;
23956 }
23957 parBind->sizeNodes = bind->nbNodes;
23958 parBind->nbNodes = bind->nbNodes;
23959 memcpy(parBind->nodeTable, bind->nodeTable,
23960 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23961 }
23962 }
23963 if (bind->dupls) {
23964 /*
23965 * Move the duplicates.
23966 */
23967 if (parBind->dupls != NULL)
23968 xmlSchemaItemListFree(parBind->dupls);
23969 parBind->dupls = bind->dupls;
23970 bind->dupls = NULL;
23971 }
23972 if (parTable != NULL) {
23973 if (*parTable == NULL)
23974 *parTable = parBind;
23975 else {
23976 parBind->next = *parTable;
23977 *parTable = parBind;
23978 }
23979 }
23980 }
23981
23982 next_binding:
23983 bind = bind->next;
23984 }
23985 return (0);
23986
23987 internal_error:
23988 return(-1);
23989 }
23990
23991 /**
23992 * xmlSchemaCheckCVCIDCKeyRef:
23993 * @vctxt: the WXS validation context
23994 * @elemDecl: the element declaration
23995 *
23996 * Check the cvc-idc-keyref constraints.
23997 */
23998 static int
xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)23999 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
24000 {
24001 xmlSchemaIDCMatcherPtr matcher;
24002 xmlSchemaPSVIIDCBindingPtr bind;
24003
24004 matcher = vctxt->inode->idcMatchers;
24005 /*
24006 * Find a keyref.
24007 */
24008 while (matcher != NULL) {
24009 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
24010 matcher->targets &&
24011 matcher->targets->nbItems)
24012 {
24013 int i, j, k, res, nbFields, hasDupls;
24014 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
24015 xmlSchemaPSVIIDCNodePtr refNode = NULL;
24016 xmlHashTablePtr table = NULL;
24017
24018 nbFields = matcher->aidc->def->nbFields;
24019
24020 /*
24021 * Find the IDC node-table for the referenced IDC key/unique.
24022 */
24023 bind = vctxt->inode->idcTable;
24024 while (bind != NULL) {
24025 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
24026 bind->definition)
24027 break;
24028 bind = bind->next;
24029 }
24030 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
24031 /*
24032 * Search for a matching key-sequences.
24033 */
24034 if (bind) {
24035 table = xmlHashCreate(bind->nbNodes * 2);
24036 for (j = 0; j < bind->nbNodes; j++) {
24037 xmlChar *value;
24038 xmlIDCHashEntryPtr r, e;
24039 keys = bind->nodeTable[j]->keys;
24040 xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
24041 e = xmlMalloc(sizeof *e);
24042 e->index = j;
24043 r = xmlHashLookup(table, value);
24044 if (r) {
24045 e->next = r->next;
24046 r->next = e;
24047 } else {
24048 e->next = NULL;
24049 xmlHashAddEntry(table, value, e);
24050 }
24051 FREE_AND_NULL(value);
24052 }
24053 }
24054 for (i = 0; i < matcher->targets->nbItems; i++) {
24055 res = 0;
24056 refNode = matcher->targets->items[i];
24057 if (bind != NULL) {
24058 xmlChar *value;
24059 xmlIDCHashEntryPtr e;
24060 refKeys = refNode->keys;
24061 xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
24062 e = xmlHashLookup(table, value);
24063 FREE_AND_NULL(value);
24064 res = 0;
24065 for (;e; e = e->next) {
24066 keys = bind->nodeTable[e->index]->keys;
24067 for (k = 0; k < nbFields; k++) {
24068 res = xmlSchemaAreValuesEqual(keys[k]->val,
24069 refKeys[k]->val);
24070 if (res == 0)
24071 break;
24072 else if (res == -1) {
24073 return (-1);
24074 }
24075 }
24076 if (res == 1) {
24077 /*
24078 * Match found.
24079 */
24080 break;
24081 }
24082 }
24083 if ((res == 0) && hasDupls) {
24084 /*
24085 * Search in duplicates
24086 */
24087 for (j = 0; j < bind->dupls->nbItems; j++) {
24088 keys = ((xmlSchemaPSVIIDCNodePtr)
24089 bind->dupls->items[j])->keys;
24090 for (k = 0; k < nbFields; k++) {
24091 res = xmlSchemaAreValuesEqual(keys[k]->val,
24092 refKeys[k]->val);
24093 if (res == 0)
24094 break;
24095 else if (res == -1) {
24096 return (-1);
24097 }
24098 }
24099 if (res == 1) {
24100 /*
24101 * Match in duplicates found.
24102 */
24103 xmlChar *str = NULL, *strB = NULL;
24104 xmlSchemaKeyrefErr(vctxt,
24105 XML_SCHEMAV_CVC_IDC, refNode,
24106 (xmlSchemaTypePtr) matcher->aidc->def,
24107 "More than one match found for "
24108 "key-sequence %s of keyref '%s'",
24109 xmlSchemaFormatIDCKeySequence(vctxt, &str,
24110 refNode->keys, nbFields),
24111 xmlSchemaGetComponentQName(&strB,
24112 matcher->aidc->def));
24113 FREE_AND_NULL(str);
24114 FREE_AND_NULL(strB);
24115 break;
24116 }
24117 }
24118 }
24119 }
24120
24121 if (res == 0) {
24122 xmlChar *str = NULL, *strB = NULL;
24123 xmlSchemaKeyrefErr(vctxt,
24124 XML_SCHEMAV_CVC_IDC, refNode,
24125 (xmlSchemaTypePtr) matcher->aidc->def,
24126 "No match found for key-sequence %s of keyref '%s'",
24127 xmlSchemaFormatIDCKeySequence(vctxt, &str,
24128 refNode->keys, nbFields),
24129 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
24130 FREE_AND_NULL(str);
24131 FREE_AND_NULL(strB);
24132 }
24133 }
24134 if (table) {
24135 xmlHashFree(table, xmlFreeIDCHashEntry);
24136 }
24137 }
24138 matcher = matcher->next;
24139 }
24140 /* TODO: Return an error if any error encountered. */
24141 return (0);
24142 }
24143
24144 /************************************************************************
24145 * *
24146 * XML Reader validation code *
24147 * *
24148 ************************************************************************/
24149
24150 static xmlSchemaAttrInfoPtr
xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)24151 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
24152 {
24153 xmlSchemaAttrInfoPtr iattr;
24154 /*
24155 * Grow/create list of attribute infos.
24156 */
24157 if (vctxt->attrInfos == NULL) {
24158 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24159 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
24160 vctxt->sizeAttrInfos = 1;
24161 if (vctxt->attrInfos == NULL) {
24162 xmlSchemaVErrMemory(vctxt,
24163 "allocating attribute info list", NULL);
24164 return (NULL);
24165 }
24166 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
24167 vctxt->sizeAttrInfos++;
24168 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24169 xmlRealloc(vctxt->attrInfos,
24170 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
24171 if (vctxt->attrInfos == NULL) {
24172 xmlSchemaVErrMemory(vctxt,
24173 "re-allocating attribute info list", NULL);
24174 return (NULL);
24175 }
24176 } else {
24177 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
24178 if (iattr->localName != NULL) {
24179 VERROR_INT("xmlSchemaGetFreshAttrInfo",
24180 "attr info not cleared");
24181 return (NULL);
24182 }
24183 iattr->nodeType = XML_ATTRIBUTE_NODE;
24184 return (iattr);
24185 }
24186 /*
24187 * Create an attribute info.
24188 */
24189 iattr = (xmlSchemaAttrInfoPtr)
24190 xmlMalloc(sizeof(xmlSchemaAttrInfo));
24191 if (iattr == NULL) {
24192 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
24193 return (NULL);
24194 }
24195 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
24196 iattr->nodeType = XML_ATTRIBUTE_NODE;
24197 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
24198
24199 return (iattr);
24200 }
24201
24202 static int
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,xmlNodePtr attrNode,int nodeLine,const xmlChar * localName,const xmlChar * nsName,int ownedNames,xmlChar * value,int ownedValue)24203 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
24204 xmlNodePtr attrNode,
24205 int nodeLine,
24206 const xmlChar *localName,
24207 const xmlChar *nsName,
24208 int ownedNames,
24209 xmlChar *value,
24210 int ownedValue)
24211 {
24212 xmlSchemaAttrInfoPtr attr;
24213
24214 attr = xmlSchemaGetFreshAttrInfo(vctxt);
24215 if (attr == NULL) {
24216 VERROR_INT("xmlSchemaPushAttribute",
24217 "calling xmlSchemaGetFreshAttrInfo()");
24218 return (-1);
24219 }
24220 attr->node = attrNode;
24221 attr->nodeLine = nodeLine;
24222 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
24223 attr->localName = localName;
24224 attr->nsName = nsName;
24225 if (ownedNames)
24226 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
24227 /*
24228 * Evaluate if it's an XSI attribute.
24229 */
24230 if (nsName != NULL) {
24231 if (xmlStrEqual(localName, BAD_CAST "nil")) {
24232 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24233 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
24234 }
24235 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
24236 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24237 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
24238 }
24239 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
24240 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24241 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
24242 }
24243 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
24244 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24245 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24246 }
24247 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24248 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24249 }
24250 }
24251 attr->value = value;
24252 if (ownedValue)
24253 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24254 if (attr->metaType != 0)
24255 attr->state = XML_SCHEMAS_ATTR_META;
24256 return (0);
24257 }
24258
24259 /**
24260 * xmlSchemaClearElemInfo:
24261 * @vctxt: the WXS validation context
24262 * @ielem: the element information item
24263 */
24264 static void
xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)24265 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24266 xmlSchemaNodeInfoPtr ielem)
24267 {
24268 ielem->hasKeyrefs = 0;
24269 ielem->appliedXPath = 0;
24270 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24271 FREE_AND_NULL(ielem->localName);
24272 FREE_AND_NULL(ielem->nsName);
24273 } else {
24274 ielem->localName = NULL;
24275 ielem->nsName = NULL;
24276 }
24277 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24278 FREE_AND_NULL(ielem->value);
24279 } else {
24280 ielem->value = NULL;
24281 }
24282 if (ielem->val != NULL) {
24283 /*
24284 * PSVI TODO: Be careful not to free it when the value is
24285 * exposed via PSVI.
24286 */
24287 xmlSchemaFreeValue(ielem->val);
24288 ielem->val = NULL;
24289 }
24290 if (ielem->idcMatchers != NULL) {
24291 /*
24292 * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24293 * Does it work?
24294 */
24295 xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24296 #if 0
24297 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24298 #endif
24299 ielem->idcMatchers = NULL;
24300 }
24301 if (ielem->idcTable != NULL) {
24302 /*
24303 * OPTIMIZE TODO: Use a pool of IDC tables??.
24304 */
24305 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24306 ielem->idcTable = NULL;
24307 }
24308 if (ielem->regexCtxt != NULL) {
24309 xmlRegFreeExecCtxt(ielem->regexCtxt);
24310 ielem->regexCtxt = NULL;
24311 }
24312 if (ielem->nsBindings != NULL) {
24313 xmlFree((xmlChar **)ielem->nsBindings);
24314 ielem->nsBindings = NULL;
24315 ielem->nbNsBindings = 0;
24316 ielem->sizeNsBindings = 0;
24317 }
24318 }
24319
24320 /**
24321 * xmlSchemaGetFreshElemInfo:
24322 * @vctxt: the schema validation context
24323 *
24324 * Creates/reuses and initializes the element info item for
24325 * the current tree depth.
24326 *
24327 * Returns the element info item or NULL on API or internal errors.
24328 */
24329 static xmlSchemaNodeInfoPtr
xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)24330 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24331 {
24332 xmlSchemaNodeInfoPtr info = NULL;
24333
24334 if (vctxt->depth > vctxt->sizeElemInfos) {
24335 VERROR_INT("xmlSchemaGetFreshElemInfo",
24336 "inconsistent depth encountered");
24337 return (NULL);
24338 }
24339 if (vctxt->elemInfos == NULL) {
24340 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24341 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24342 if (vctxt->elemInfos == NULL) {
24343 xmlSchemaVErrMemory(vctxt,
24344 "allocating the element info array", NULL);
24345 return (NULL);
24346 }
24347 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24348 vctxt->sizeElemInfos = 10;
24349 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24350 int i = vctxt->sizeElemInfos;
24351
24352 vctxt->sizeElemInfos *= 2;
24353 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24354 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24355 sizeof(xmlSchemaNodeInfoPtr));
24356 if (vctxt->elemInfos == NULL) {
24357 xmlSchemaVErrMemory(vctxt,
24358 "re-allocating the element info array", NULL);
24359 return (NULL);
24360 }
24361 /*
24362 * We need the new memory to be NULLed.
24363 * TODO: Use memset instead?
24364 */
24365 for (; i < vctxt->sizeElemInfos; i++)
24366 vctxt->elemInfos[i] = NULL;
24367 } else
24368 info = vctxt->elemInfos[vctxt->depth];
24369
24370 if (info == NULL) {
24371 info = (xmlSchemaNodeInfoPtr)
24372 xmlMalloc(sizeof(xmlSchemaNodeInfo));
24373 if (info == NULL) {
24374 xmlSchemaVErrMemory(vctxt,
24375 "allocating an element info", NULL);
24376 return (NULL);
24377 }
24378 vctxt->elemInfos[vctxt->depth] = info;
24379 } else {
24380 if (info->localName != NULL) {
24381 VERROR_INT("xmlSchemaGetFreshElemInfo",
24382 "elem info has not been cleared");
24383 return (NULL);
24384 }
24385 }
24386 memset(info, 0, sizeof(xmlSchemaNodeInfo));
24387 info->nodeType = XML_ELEMENT_NODE;
24388 info->depth = vctxt->depth;
24389
24390 return (info);
24391 }
24392
24393 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24394 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24395 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24396
24397 static int
xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long length,int fireErrors)24398 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24399 xmlNodePtr node,
24400 xmlSchemaTypePtr type,
24401 xmlSchemaValType valType,
24402 const xmlChar * value,
24403 xmlSchemaValPtr val,
24404 unsigned long length,
24405 int fireErrors)
24406 {
24407 int ret, error = 0, found;
24408
24409 xmlSchemaTypePtr tmpType;
24410 xmlSchemaFacetLinkPtr facetLink;
24411 xmlSchemaFacetPtr facet;
24412 unsigned long len = 0;
24413 xmlSchemaWhitespaceValueType ws;
24414
24415 /*
24416 * In Libxml2, derived built-in types have currently no explicit facets.
24417 */
24418 if (type->type == XML_SCHEMA_TYPE_BASIC)
24419 return (0);
24420
24421 /*
24422 * NOTE: Do not jump away, if the facetSet of the given type is
24423 * empty: until now, "pattern" and "enumeration" facets of the
24424 * *base types* need to be checked as well.
24425 */
24426 if (type->facetSet == NULL)
24427 goto pattern_and_enum;
24428
24429 if (! WXS_IS_ATOMIC(type)) {
24430 if (WXS_IS_LIST(type))
24431 goto WXS_IS_LIST;
24432 else
24433 goto pattern_and_enum;
24434 }
24435
24436 /*
24437 * Whitespace handling is only of importance for string-based
24438 * types.
24439 */
24440 tmpType = xmlSchemaGetPrimitiveType(type);
24441 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24442 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24443 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24444 } else
24445 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24446
24447 /*
24448 * If the value was not computed (for string or
24449 * anySimpleType based types), then use the provided
24450 * type.
24451 */
24452 if (val != NULL)
24453 valType = xmlSchemaGetValType(val);
24454
24455 ret = 0;
24456 for (facetLink = type->facetSet; facetLink != NULL;
24457 facetLink = facetLink->next) {
24458 /*
24459 * Skip the pattern "whiteSpace": it is used to
24460 * format the character content beforehand.
24461 */
24462 switch (facetLink->facet->type) {
24463 case XML_SCHEMA_FACET_WHITESPACE:
24464 case XML_SCHEMA_FACET_PATTERN:
24465 case XML_SCHEMA_FACET_ENUMERATION:
24466 continue;
24467 case XML_SCHEMA_FACET_LENGTH:
24468 case XML_SCHEMA_FACET_MINLENGTH:
24469 case XML_SCHEMA_FACET_MAXLENGTH:
24470 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24471 valType, value, val, &len, ws);
24472 break;
24473 default:
24474 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24475 valType, value, val, ws);
24476 break;
24477 }
24478 if (ret < 0) {
24479 AERROR_INT("xmlSchemaValidateFacets",
24480 "validating against a atomic type facet");
24481 return (-1);
24482 } else if (ret > 0) {
24483 if (fireErrors)
24484 xmlSchemaFacetErr(actxt, ret, node,
24485 value, len, type, facetLink->facet, NULL, NULL, NULL);
24486 else
24487 return (ret);
24488 if (error == 0)
24489 error = ret;
24490 }
24491 ret = 0;
24492 }
24493
24494 WXS_IS_LIST:
24495 if (! WXS_IS_LIST(type))
24496 goto pattern_and_enum;
24497 /*
24498 * "length", "minLength" and "maxLength" of list types.
24499 */
24500 ret = 0;
24501 for (facetLink = type->facetSet; facetLink != NULL;
24502 facetLink = facetLink->next) {
24503
24504 switch (facetLink->facet->type) {
24505 case XML_SCHEMA_FACET_LENGTH:
24506 case XML_SCHEMA_FACET_MINLENGTH:
24507 case XML_SCHEMA_FACET_MAXLENGTH:
24508 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24509 value, length, NULL);
24510 break;
24511 default:
24512 continue;
24513 }
24514 if (ret < 0) {
24515 AERROR_INT("xmlSchemaValidateFacets",
24516 "validating against a list type facet");
24517 return (-1);
24518 } else if (ret > 0) {
24519 if (fireErrors)
24520 xmlSchemaFacetErr(actxt, ret, node,
24521 value, length, type, facetLink->facet, NULL, NULL, NULL);
24522 else
24523 return (ret);
24524 if (error == 0)
24525 error = ret;
24526 }
24527 ret = 0;
24528 }
24529
24530 pattern_and_enum:
24531 found = 0;
24532 /*
24533 * Process enumerations. Facet values are in the value space
24534 * of the defining type's base type. This seems to be a bug in the
24535 * XML Schema 1.0 spec. Use the whitespace type of the base type.
24536 * Only the first set of enumerations in the ancestor-or-self axis
24537 * is used for validation.
24538 */
24539 ret = 0;
24540 tmpType = type;
24541 do {
24542 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24543 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24544 continue;
24545 found = 1;
24546 ret = xmlSchemaAreValuesEqual(facet->val, val);
24547 if (ret == 1)
24548 break;
24549 else if (ret < 0) {
24550 AERROR_INT("xmlSchemaValidateFacets",
24551 "validating against an enumeration facet");
24552 return (-1);
24553 }
24554 }
24555 if (ret != 0)
24556 break;
24557 /*
24558 * Break on the first set of enumerations. Any additional
24559 * enumerations which might be existent on the ancestors
24560 * of the current type are restricted by this set; thus
24561 * *must* *not* be taken into account.
24562 */
24563 if (found)
24564 break;
24565 tmpType = tmpType->baseType;
24566 } while ((tmpType != NULL) &&
24567 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24568 if (found && (ret == 0)) {
24569 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24570 if (fireErrors) {
24571 xmlSchemaFacetErr(actxt, ret, node,
24572 value, 0, type, NULL, NULL, NULL, NULL);
24573 } else
24574 return (ret);
24575 if (error == 0)
24576 error = ret;
24577 }
24578
24579 /*
24580 * Process patters. Pattern facets are ORed at type level
24581 * and ANDed if derived. Walk the base type axis.
24582 */
24583 tmpType = type;
24584 facet = NULL;
24585 do {
24586 found = 0;
24587 for (facetLink = tmpType->facetSet; facetLink != NULL;
24588 facetLink = facetLink->next) {
24589 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24590 continue;
24591 found = 1;
24592 /*
24593 * NOTE that for patterns, @value needs to be the
24594 * normalized value.
24595 */
24596 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24597 if (ret == 1)
24598 break;
24599 else if (ret < 0) {
24600 AERROR_INT("xmlSchemaValidateFacets",
24601 "validating against a pattern facet");
24602 return (-1);
24603 } else {
24604 /*
24605 * Save the last non-validating facet.
24606 */
24607 facet = facetLink->facet;
24608 }
24609 }
24610 if (found && (ret != 1)) {
24611 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24612 if (fireErrors) {
24613 xmlSchemaFacetErr(actxt, ret, node,
24614 value, 0, type, facet, NULL, NULL, NULL);
24615 } else
24616 return (ret);
24617 if (error == 0)
24618 error = ret;
24619 break;
24620 }
24621 tmpType = tmpType->baseType;
24622 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24623
24624 return (error);
24625 }
24626
24627 static xmlChar *
xmlSchemaNormalizeValue(xmlSchemaTypePtr type,const xmlChar * value)24628 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24629 const xmlChar *value)
24630 {
24631 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24632 case XML_SCHEMA_WHITESPACE_COLLAPSE:
24633 return (xmlSchemaCollapseString(value));
24634 case XML_SCHEMA_WHITESPACE_REPLACE:
24635 return (xmlSchemaWhiteSpaceReplace(value));
24636 default:
24637 return (NULL);
24638 }
24639 }
24640
24641 static int
xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)24642 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24643 const xmlChar *value,
24644 xmlSchemaValPtr *val,
24645 int valNeeded)
24646 {
24647 int ret;
24648 const xmlChar *nsName;
24649 xmlChar *local, *prefix = NULL;
24650
24651 ret = xmlValidateQName(value, 1);
24652 if (ret != 0) {
24653 if (ret == -1) {
24654 VERROR_INT("xmlSchemaValidateQName",
24655 "calling xmlValidateQName()");
24656 return (-1);
24657 }
24658 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24659 }
24660 /*
24661 * NOTE: xmlSplitQName2 will always return a duplicated
24662 * strings.
24663 */
24664 local = xmlSplitQName2(value, &prefix);
24665 if (local == NULL)
24666 local = xmlStrdup(value);
24667 /*
24668 * OPTIMIZE TODO: Use flags for:
24669 * - is there any namespace binding?
24670 * - is there a default namespace?
24671 */
24672 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24673
24674 if (prefix != NULL) {
24675 xmlFree(prefix);
24676 /*
24677 * A namespace must be found if the prefix is
24678 * NOT NULL.
24679 */
24680 if (nsName == NULL) {
24681 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24682 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24683 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24684 "The QName value '%s' has no "
24685 "corresponding namespace declaration in "
24686 "scope", value, NULL);
24687 if (local != NULL)
24688 xmlFree(local);
24689 return (ret);
24690 }
24691 }
24692 if (valNeeded && val) {
24693 if (nsName != NULL)
24694 *val = xmlSchemaNewQNameValue(
24695 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24696 else
24697 *val = xmlSchemaNewQNameValue(NULL,
24698 BAD_CAST local);
24699 } else
24700 xmlFree(local);
24701 return (0);
24702 }
24703
24704 /*
24705 * cvc-simple-type
24706 */
24707 static int
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * retVal,int fireErrors,int normalize,int isNormalized)24708 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24709 xmlNodePtr node,
24710 xmlSchemaTypePtr type,
24711 const xmlChar *value,
24712 xmlSchemaValPtr *retVal,
24713 int fireErrors,
24714 int normalize,
24715 int isNormalized)
24716 {
24717 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24718 xmlSchemaValPtr val = NULL;
24719 /* xmlSchemaWhitespaceValueType ws; */
24720 xmlChar *normValue = NULL;
24721
24722 #define NORMALIZE(atype) \
24723 if ((! isNormalized) && \
24724 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24725 normValue = xmlSchemaNormalizeValue(atype, value); \
24726 if (normValue != NULL) \
24727 value = normValue; \
24728 isNormalized = 1; \
24729 }
24730
24731 if ((retVal != NULL) && (*retVal != NULL)) {
24732 xmlSchemaFreeValue(*retVal);
24733 *retVal = NULL;
24734 }
24735 /*
24736 * 3.14.4 Simple Type Definition Validation Rules
24737 * Validation Rule: String Valid
24738 */
24739 /*
24740 * 1 It is schema-valid with respect to that definition as defined
24741 * by Datatype Valid in [XML Schemas: Datatypes].
24742 */
24743 /*
24744 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24745 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24746 * the string must be a `declared entity name`.
24747 */
24748 /*
24749 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24750 * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24751 * then every whitespace-delimited substring of the string must be a `declared
24752 * entity name`.
24753 */
24754 /*
24755 * 2.3 otherwise no further condition applies.
24756 */
24757 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24758 valNeeded = 1;
24759 if (value == NULL)
24760 value = BAD_CAST "";
24761 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24762 xmlSchemaTypePtr biType; /* The built-in type. */
24763 /*
24764 * SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24765 * a literal in the `lexical space` of {base type definition}"
24766 */
24767 /*
24768 * Whitespace-normalize.
24769 */
24770 NORMALIZE(type);
24771 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24772 /*
24773 * Get the built-in type.
24774 */
24775 biType = type->baseType;
24776 while ((biType != NULL) &&
24777 (biType->type != XML_SCHEMA_TYPE_BASIC))
24778 biType = biType->baseType;
24779
24780 if (biType == NULL) {
24781 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24782 "could not get the built-in type");
24783 goto internal_error;
24784 }
24785 } else
24786 biType = type;
24787 /*
24788 * NOTATIONs need to be processed here, since they need
24789 * to lookup in the hashtable of NOTATION declarations of the schema.
24790 */
24791 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24792 switch (biType->builtInType) {
24793 case XML_SCHEMAS_NOTATION:
24794 ret = xmlSchemaValidateNotation(
24795 (xmlSchemaValidCtxtPtr) actxt,
24796 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24797 NULL, value, &val, valNeeded);
24798 break;
24799 case XML_SCHEMAS_QNAME:
24800 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24801 value, &val, valNeeded);
24802 break;
24803 default:
24804 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24805 if (valNeeded)
24806 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24807 value, &val, node);
24808 else
24809 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24810 value, NULL, node);
24811 break;
24812 }
24813 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24814 switch (biType->builtInType) {
24815 case XML_SCHEMAS_NOTATION:
24816 ret = xmlSchemaValidateNotation(NULL,
24817 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24818 value, &val, valNeeded);
24819 break;
24820 default:
24821 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24822 if (valNeeded)
24823 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24824 value, &val, node);
24825 else
24826 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24827 value, NULL, node);
24828 break;
24829 }
24830 } else {
24831 /*
24832 * Validation via a public API is not implemented yet.
24833 */
24834 TODO
24835 goto internal_error;
24836 }
24837 if (ret != 0) {
24838 if (ret < 0) {
24839 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24840 "validating against a built-in type");
24841 goto internal_error;
24842 }
24843 if (WXS_IS_LIST(type))
24844 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24845 else
24846 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24847 }
24848 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24849 /*
24850 * Check facets.
24851 */
24852 ret = xmlSchemaValidateFacets(actxt, node, type,
24853 (xmlSchemaValType) biType->builtInType, value, val,
24854 0, fireErrors);
24855 if (ret != 0) {
24856 if (ret < 0) {
24857 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24858 "validating facets of atomic simple type");
24859 goto internal_error;
24860 }
24861 if (WXS_IS_LIST(type))
24862 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24863 else
24864 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24865 }
24866 }
24867 else if (fireErrors && (ret > 0))
24868 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24869 } else if (WXS_IS_LIST(type)) {
24870
24871 xmlSchemaTypePtr itemType;
24872 const xmlChar *cur, *end;
24873 xmlChar *tmpValue = NULL;
24874 unsigned long len = 0;
24875 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24876 /* 1.2.2 if {variety} is `list` then the string must be a sequence
24877 * of white space separated tokens, each of which `match`es a literal
24878 * in the `lexical space` of {item type definition}
24879 */
24880 /*
24881 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24882 * the list type has an enum or pattern facet.
24883 */
24884 NORMALIZE(type);
24885 /*
24886 * VAL TODO: Optimize validation of empty values.
24887 * VAL TODO: We do not have computed values for lists.
24888 */
24889 itemType = WXS_LIST_ITEMTYPE(type);
24890 cur = value;
24891 do {
24892 while (IS_BLANK_CH(*cur))
24893 cur++;
24894 end = cur;
24895 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24896 end++;
24897 if (end == cur)
24898 break;
24899 tmpValue = xmlStrndup(cur, end - cur);
24900 len++;
24901
24902 if (valNeeded)
24903 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24904 tmpValue, &curVal, fireErrors, 0, 1);
24905 else
24906 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24907 tmpValue, NULL, fireErrors, 0, 1);
24908 FREE_AND_NULL(tmpValue);
24909 if (curVal != NULL) {
24910 /*
24911 * Add to list of computed values.
24912 */
24913 if (val == NULL)
24914 val = curVal;
24915 else
24916 xmlSchemaValueAppend(prevVal, curVal);
24917 prevVal = curVal;
24918 curVal = NULL;
24919 }
24920 if (ret != 0) {
24921 if (ret < 0) {
24922 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24923 "validating an item of list simple type");
24924 goto internal_error;
24925 }
24926 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24927 break;
24928 }
24929 cur = end;
24930 } while (*cur != 0);
24931 FREE_AND_NULL(tmpValue);
24932 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24933 /*
24934 * Apply facets (pattern, enumeration).
24935 */
24936 ret = xmlSchemaValidateFacets(actxt, node, type,
24937 XML_SCHEMAS_UNKNOWN, value, val,
24938 len, fireErrors);
24939 if (ret != 0) {
24940 if (ret < 0) {
24941 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24942 "validating facets of list simple type");
24943 goto internal_error;
24944 }
24945 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24946 }
24947 }
24948 if (fireErrors && (ret > 0)) {
24949 /*
24950 * Report the normalized value.
24951 */
24952 normalize = 1;
24953 NORMALIZE(type);
24954 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24955 }
24956 } else if (WXS_IS_UNION(type)) {
24957 xmlSchemaTypeLinkPtr memberLink;
24958 /*
24959 * TODO: For all datatypes `derived` by `union` whiteSpace does
24960 * not apply directly; however, the normalization behavior of `union`
24961 * types is controlled by the value of whiteSpace on that one of the
24962 * `memberTypes` against which the `union` is successfully validated.
24963 *
24964 * This means that the value is normalized by the first validating
24965 * member type, then the facets of the union type are applied. This
24966 * needs changing of the value!
24967 */
24968
24969 /*
24970 * 1.2.3 if {variety} is `union` then the string must `match` a
24971 * literal in the `lexical space` of at least one member of
24972 * {member type definitions}
24973 */
24974 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24975 if (memberLink == NULL) {
24976 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24977 "union simple type has no member types");
24978 goto internal_error;
24979 }
24980 /*
24981 * Always normalize union type values, since we currently
24982 * cannot store the whitespace information with the value
24983 * itself; otherwise a later value-comparison would be
24984 * not possible.
24985 */
24986 while (memberLink != NULL) {
24987 if (valNeeded)
24988 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24989 memberLink->type, value, &val, 0, 1, 0);
24990 else
24991 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24992 memberLink->type, value, NULL, 0, 1, 0);
24993 if (ret <= 0)
24994 break;
24995 memberLink = memberLink->next;
24996 }
24997 if (ret != 0) {
24998 if (ret < 0) {
24999 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
25000 "validating members of union simple type");
25001 goto internal_error;
25002 }
25003 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
25004 }
25005 /*
25006 * Apply facets (pattern, enumeration).
25007 */
25008 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
25009 /*
25010 * The normalization behavior of `union` types is controlled by
25011 * the value of whiteSpace on that one of the `memberTypes`
25012 * against which the `union` is successfully validated.
25013 */
25014 NORMALIZE(memberLink->type);
25015 ret = xmlSchemaValidateFacets(actxt, node, type,
25016 XML_SCHEMAS_UNKNOWN, value, val,
25017 0, fireErrors);
25018 if (ret != 0) {
25019 if (ret < 0) {
25020 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
25021 "validating facets of union simple type");
25022 goto internal_error;
25023 }
25024 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
25025 }
25026 }
25027 if (fireErrors && (ret > 0))
25028 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
25029 }
25030
25031 if (normValue != NULL)
25032 xmlFree(normValue);
25033 if (ret == 0) {
25034 if (retVal != NULL)
25035 *retVal = val;
25036 else if (val != NULL)
25037 xmlSchemaFreeValue(val);
25038 } else if (val != NULL)
25039 xmlSchemaFreeValue(val);
25040 return (ret);
25041 internal_error:
25042 if (normValue != NULL)
25043 xmlFree(normValue);
25044 if (val != NULL)
25045 xmlSchemaFreeValue(val);
25046 return (-1);
25047 }
25048
25049 static int
xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,const xmlChar ** nsName,const xmlChar ** localName)25050 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
25051 const xmlChar *value,
25052 const xmlChar **nsName,
25053 const xmlChar **localName)
25054 {
25055 int ret = 0;
25056
25057 if ((nsName == NULL) || (localName == NULL))
25058 return (-1);
25059 *nsName = NULL;
25060 *localName = NULL;
25061
25062 ret = xmlValidateQName(value, 1);
25063 if (ret == -1)
25064 return (-1);
25065 if (ret > 0) {
25066 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
25067 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25068 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
25069 return (1);
25070 }
25071 {
25072 xmlChar *local = NULL;
25073 xmlChar *prefix;
25074
25075 /*
25076 * NOTE: xmlSplitQName2 will return a duplicated
25077 * string.
25078 */
25079 local = xmlSplitQName2(value, &prefix);
25080 if (local == NULL)
25081 *localName = xmlDictLookup(vctxt->dict, value, -1);
25082 else {
25083 *localName = xmlDictLookup(vctxt->dict, local, -1);
25084 xmlFree(local);
25085 }
25086
25087 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
25088
25089 if (prefix != NULL) {
25090 xmlFree(prefix);
25091 /*
25092 * A namespace must be found if the prefix is NOT NULL.
25093 */
25094 if (*nsName == NULL) {
25095 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25096 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25097 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
25098 "The QName value '%s' has no "
25099 "corresponding namespace declaration in scope",
25100 value, NULL);
25101 return (2);
25102 }
25103 }
25104 }
25105 return (0);
25106 }
25107
25108 static int
xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaAttrInfoPtr iattr,xmlSchemaTypePtr * localType,xmlSchemaElementPtr elemDecl)25109 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
25110 xmlSchemaAttrInfoPtr iattr,
25111 xmlSchemaTypePtr *localType,
25112 xmlSchemaElementPtr elemDecl)
25113 {
25114 int ret = 0;
25115 /*
25116 * cvc-elt (3.3.4) : (4)
25117 * AND
25118 * Schema-Validity Assessment (Element) (cvc-assess-elt)
25119 * (1.2.1.2.1) - (1.2.1.2.4)
25120 * Handle 'xsi:type'.
25121 */
25122 if (localType == NULL)
25123 return (-1);
25124 *localType = NULL;
25125 if (iattr == NULL)
25126 return (0);
25127 else {
25128 const xmlChar *nsName = NULL, *local = NULL;
25129 /*
25130 * TODO: We should report a *warning* that the type was overridden
25131 * by the instance.
25132 */
25133 ACTIVATE_ATTRIBUTE(iattr);
25134 /*
25135 * (cvc-elt) (3.3.4) : (4.1)
25136 * (cvc-assess-elt) (1.2.1.2.2)
25137 */
25138 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
25139 &nsName, &local);
25140 if (ret != 0) {
25141 if (ret < 0) {
25142 VERROR_INT("xmlSchemaValidateElementByDeclaration",
25143 "calling xmlSchemaQNameExpand() to validate the "
25144 "attribute 'xsi:type'");
25145 goto internal_error;
25146 }
25147 goto exit;
25148 }
25149 /*
25150 * (cvc-elt) (3.3.4) : (4.2)
25151 * (cvc-assess-elt) (1.2.1.2.3)
25152 */
25153 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
25154 if (*localType == NULL) {
25155 xmlChar *str = NULL;
25156
25157 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25158 XML_SCHEMAV_CVC_ELT_4_2, NULL,
25159 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
25160 "The QName value '%s' of the xsi:type attribute does not "
25161 "resolve to a type definition",
25162 xmlSchemaFormatQName(&str, nsName, local), NULL);
25163 FREE_AND_NULL(str);
25164 ret = vctxt->err;
25165 goto exit;
25166 }
25167 if (elemDecl != NULL) {
25168 int set = 0;
25169
25170 /*
25171 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
25172 * "The `local type definition` must be validly
25173 * derived from the {type definition} given the union of
25174 * the {disallowed substitutions} and the {type definition}'s
25175 * {prohibited substitutions}, as defined in
25176 * Type Derivation OK (Complex) ($3.4.6)
25177 * (if it is a complex type definition),
25178 * or given {disallowed substitutions} as defined in Type
25179 * Derivation OK (Simple) ($3.14.6) (if it is a simple type
25180 * definition)."
25181 *
25182 * {disallowed substitutions}: the "block" on the element decl.
25183 * {prohibited substitutions}: the "block" on the type def.
25184 */
25185 /*
25186 * OPTIMIZE TODO: We could map types already evaluated
25187 * to be validly derived from other types to avoid checking
25188 * this over and over for the same types.
25189 */
25190 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
25191 (elemDecl->subtypes->flags &
25192 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
25193 set |= SUBSET_EXTENSION;
25194
25195 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
25196 (elemDecl->subtypes->flags &
25197 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
25198 set |= SUBSET_RESTRICTION;
25199
25200 /*
25201 * REMOVED and CHANGED since this produced a parser context
25202 * which adds to the string dict of the schema. So this would
25203 * change the schema and we don't want this. We don't need
25204 * the parser context anymore.
25205 *
25206 * if ((vctxt->pctxt == NULL) &&
25207 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
25208 * return (-1);
25209 */
25210
25211 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
25212 elemDecl->subtypes, set) != 0) {
25213 xmlChar *str = NULL;
25214
25215 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25216 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
25217 "The type definition '%s', specified by xsi:type, is "
25218 "blocked or not validly derived from the type definition "
25219 "of the element declaration",
25220 xmlSchemaFormatQName(&str,
25221 (*localType)->targetNamespace,
25222 (*localType)->name),
25223 NULL);
25224 FREE_AND_NULL(str);
25225 ret = vctxt->err;
25226 *localType = NULL;
25227 }
25228 }
25229 }
25230 exit:
25231 ACTIVATE_ELEM;
25232 return (ret);
25233 internal_error:
25234 ACTIVATE_ELEM;
25235 return (-1);
25236 }
25237
25238 static int
xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)25239 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
25240 {
25241 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
25242 xmlSchemaTypePtr actualType;
25243
25244 /*
25245 * cvc-elt (3.3.4) : 1
25246 */
25247 if (elemDecl == NULL) {
25248 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25249 "No matching declaration available");
25250 return (vctxt->err);
25251 }
25252 actualType = WXS_ELEM_TYPEDEF(elemDecl);
25253 /*
25254 * cvc-elt (3.3.4) : 2
25255 */
25256 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25257 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25258 "The element declaration is abstract");
25259 return (vctxt->err);
25260 }
25261 if (actualType == NULL) {
25262 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25263 "The type definition is absent");
25264 return (XML_SCHEMAV_CVC_TYPE_1);
25265 }
25266 if (vctxt->nbAttrInfos != 0) {
25267 int ret;
25268 xmlSchemaAttrInfoPtr iattr;
25269 /*
25270 * cvc-elt (3.3.4) : 3
25271 * Handle 'xsi:nil'.
25272 */
25273 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25274 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25275 if (iattr) {
25276 ACTIVATE_ATTRIBUTE(iattr);
25277 /*
25278 * Validate the value.
25279 */
25280 ret = xmlSchemaVCheckCVCSimpleType(
25281 ACTXT_CAST vctxt, NULL,
25282 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25283 iattr->value, &(iattr->val), 1, 0, 0);
25284 ACTIVATE_ELEM;
25285 if (ret < 0) {
25286 VERROR_INT("xmlSchemaValidateElemDecl",
25287 "calling xmlSchemaVCheckCVCSimpleType() to "
25288 "validate the attribute 'xsi:nil'");
25289 return (-1);
25290 }
25291 if (ret == 0) {
25292 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25293 /*
25294 * cvc-elt (3.3.4) : 3.1
25295 */
25296 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25297 "The element is not 'nillable'");
25298 /* Does not return an error on purpose. */
25299 } else {
25300 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25301 /*
25302 * cvc-elt (3.3.4) : 3.2.2
25303 */
25304 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25305 (elemDecl->value != NULL)) {
25306 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25307 "The element cannot be 'nilled' because "
25308 "there is a fixed value constraint defined "
25309 "for it");
25310 /* Does not return an error on purpose. */
25311 } else
25312 vctxt->inode->flags |=
25313 XML_SCHEMA_ELEM_INFO_NILLED;
25314 }
25315 }
25316 }
25317 }
25318 /*
25319 * cvc-elt (3.3.4) : 4
25320 * Handle 'xsi:type'.
25321 */
25322 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25323 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25324 if (iattr) {
25325 xmlSchemaTypePtr localType = NULL;
25326
25327 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25328 elemDecl);
25329 if (ret != 0) {
25330 if (ret == -1) {
25331 VERROR_INT("xmlSchemaValidateElemDecl",
25332 "calling xmlSchemaProcessXSIType() to "
25333 "process the attribute 'xsi:type'");
25334 return (-1);
25335 }
25336 /* Does not return an error on purpose. */
25337 }
25338 if (localType != NULL) {
25339 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25340 actualType = localType;
25341 }
25342 }
25343 }
25344 /*
25345 * IDC: Register identity-constraint XPath matchers.
25346 */
25347 if ((elemDecl->idcs != NULL) &&
25348 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25349 return (-1);
25350 /*
25351 * No actual type definition.
25352 */
25353 if (actualType == NULL) {
25354 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25355 "The type definition is absent");
25356 return (XML_SCHEMAV_CVC_TYPE_1);
25357 }
25358 /*
25359 * Remember the actual type definition.
25360 */
25361 vctxt->inode->typeDef = actualType;
25362
25363 return (0);
25364 }
25365
25366 static int
xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)25367 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25368 {
25369 xmlSchemaAttrInfoPtr iattr;
25370 int ret = 0, i;
25371
25372 /*
25373 * SPEC cvc-type (3.1.1)
25374 * "The attributes of must be empty, excepting those whose namespace
25375 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25376 * whose local name is one of type, nil, schemaLocation or
25377 * noNamespaceSchemaLocation."
25378 */
25379 if (vctxt->nbAttrInfos == 0)
25380 return (0);
25381 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25382 iattr = vctxt->attrInfos[i];
25383 if (! iattr->metaType) {
25384 ACTIVATE_ATTRIBUTE(iattr)
25385 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25386 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25387 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25388 }
25389 }
25390 ACTIVATE_ELEM
25391 return (ret);
25392 }
25393
25394 /*
25395 * Cleanup currently used attribute infos.
25396 */
25397 static void
xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)25398 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25399 {
25400 int i;
25401 xmlSchemaAttrInfoPtr attr;
25402
25403 if (vctxt->nbAttrInfos == 0)
25404 return;
25405 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25406 attr = vctxt->attrInfos[i];
25407 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25408 if (attr->localName != NULL)
25409 xmlFree((xmlChar *) attr->localName);
25410 if (attr->nsName != NULL)
25411 xmlFree((xmlChar *) attr->nsName);
25412 }
25413 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25414 if (attr->value != NULL)
25415 xmlFree((xmlChar *) attr->value);
25416 }
25417 if (attr->val != NULL) {
25418 xmlSchemaFreeValue(attr->val);
25419 attr->val = NULL;
25420 }
25421 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25422 }
25423 vctxt->nbAttrInfos = 0;
25424 }
25425
25426 /*
25427 * 3.4.4 Complex Type Definition Validation Rules
25428 * Element Locally Valid (Complex Type) (cvc-complex-type)
25429 * 3.2.4 Attribute Declaration Validation Rules
25430 * Validation Rule: Attribute Locally Valid (cvc-attribute)
25431 * Attribute Locally Valid (Use) (cvc-au)
25432 *
25433 * Only "assessed" attribute information items will be visible to
25434 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25435 */
25436 static int
xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)25437 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25438 {
25439 xmlSchemaTypePtr type = vctxt->inode->typeDef;
25440 xmlSchemaItemListPtr attrUseList;
25441 xmlSchemaAttributeUsePtr attrUse = NULL;
25442 xmlSchemaAttributePtr attrDecl = NULL;
25443 xmlSchemaAttrInfoPtr iattr, tmpiattr;
25444 int i, j, found, nbAttrs, nbUses;
25445 int xpathRes = 0, res, wildIDs = 0, fixed;
25446 xmlNodePtr defAttrOwnerElem = NULL;
25447
25448 /*
25449 * SPEC (cvc-attribute)
25450 * (1) "The declaration must not be `absent` (see Missing
25451 * Sub-components ($5.3) for how this can fail to be
25452 * the case)."
25453 * (2) "Its {type definition} must not be absent."
25454 *
25455 * NOTE (1) + (2): This is not handled here, since we currently do not
25456 * allow validation against schemas which have missing sub-components.
25457 *
25458 * SPEC (cvc-complex-type)
25459 * (3) "For each attribute information item in the element information
25460 * item's [attributes] excepting those whose [namespace name] is
25461 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25462 * [local name] is one of type, nil, schemaLocation or
25463 * noNamespaceSchemaLocation, the appropriate case among the following
25464 * must be true:
25465 *
25466 */
25467 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25468 /*
25469 * @nbAttrs is the number of attributes present in the instance.
25470 */
25471 nbAttrs = vctxt->nbAttrInfos;
25472 if (attrUseList != NULL)
25473 nbUses = attrUseList->nbItems;
25474 else
25475 nbUses = 0;
25476 for (i = 0; i < nbUses; i++) {
25477 found = 0;
25478 attrUse = attrUseList->items[i];
25479 attrDecl = WXS_ATTRUSE_DECL(attrUse);
25480 for (j = 0; j < nbAttrs; j++) {
25481 iattr = vctxt->attrInfos[j];
25482 /*
25483 * SPEC (cvc-complex-type) (3)
25484 * Skip meta attributes.
25485 */
25486 if (iattr->metaType)
25487 continue;
25488 if (iattr->localName[0] != attrDecl->name[0])
25489 continue;
25490 if (!xmlStrEqual(iattr->localName, attrDecl->name))
25491 continue;
25492 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25493 continue;
25494 found = 1;
25495 /*
25496 * SPEC (cvc-complex-type)
25497 * (3.1) "If there is among the {attribute uses} an attribute
25498 * use with an {attribute declaration} whose {name} matches
25499 * the attribute information item's [local name] and whose
25500 * {target namespace} is identical to the attribute information
25501 * item's [namespace name] (where an `absent` {target namespace}
25502 * is taken to be identical to a [namespace name] with no value),
25503 * then the attribute information must be `valid` with respect
25504 * to that attribute use as per Attribute Locally Valid (Use)
25505 * ($3.5.4). In this case the {attribute declaration} of that
25506 * attribute use is the `context-determined declaration` for the
25507 * attribute information item with respect to Schema-Validity
25508 * Assessment (Attribute) ($3.2.4) and
25509 * Assessment Outcome (Attribute) ($3.2.5).
25510 */
25511 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25512 iattr->use = attrUse;
25513 /*
25514 * Context-determined declaration.
25515 */
25516 iattr->decl = attrDecl;
25517 iattr->typeDef = attrDecl->subtypes;
25518 break;
25519 }
25520
25521 if (found)
25522 continue;
25523
25524 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25525 /*
25526 * Handle non-existent, required attributes.
25527 *
25528 * SPEC (cvc-complex-type)
25529 * (4) "The {attribute declaration} of each attribute use in
25530 * the {attribute uses} whose {required} is true matches one
25531 * of the attribute information items in the element information
25532 * item's [attributes] as per clause 3.1 above."
25533 */
25534 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25535 if (tmpiattr == NULL) {
25536 VERROR_INT(
25537 "xmlSchemaVAttributesComplex",
25538 "calling xmlSchemaGetFreshAttrInfo()");
25539 return (-1);
25540 }
25541 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25542 tmpiattr->use = attrUse;
25543 tmpiattr->decl = attrDecl;
25544 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25545 ((attrUse->defValue != NULL) ||
25546 (attrDecl->defValue != NULL))) {
25547 /*
25548 * Handle non-existent, optional, default/fixed attributes.
25549 */
25550 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25551 if (tmpiattr == NULL) {
25552 VERROR_INT(
25553 "xmlSchemaVAttributesComplex",
25554 "calling xmlSchemaGetFreshAttrInfo()");
25555 return (-1);
25556 }
25557 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25558 tmpiattr->use = attrUse;
25559 tmpiattr->decl = attrDecl;
25560 tmpiattr->typeDef = attrDecl->subtypes;
25561 tmpiattr->localName = attrDecl->name;
25562 tmpiattr->nsName = attrDecl->targetNamespace;
25563 }
25564 }
25565
25566 if (vctxt->nbAttrInfos == 0)
25567 return (0);
25568 /*
25569 * Validate against the wildcard.
25570 */
25571 if (type->attributeWildcard != NULL) {
25572 /*
25573 * SPEC (cvc-complex-type)
25574 * (3.2.1) "There must be an {attribute wildcard}."
25575 */
25576 for (i = 0; i < nbAttrs; i++) {
25577 iattr = vctxt->attrInfos[i];
25578 /*
25579 * SPEC (cvc-complex-type) (3)
25580 * Skip meta attributes.
25581 */
25582 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25583 continue;
25584 /*
25585 * SPEC (cvc-complex-type)
25586 * (3.2.2) "The attribute information item must be `valid` with
25587 * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25588 *
25589 * SPEC Item Valid (Wildcard) (cvc-wildcard)
25590 * "... its [namespace name] must be `valid` with respect to
25591 * the wildcard constraint, as defined in Wildcard allows
25592 * Namespace Name ($3.10.4)."
25593 */
25594 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25595 iattr->nsName) == 0) {
25596 /*
25597 * Handle processContents.
25598 *
25599 * SPEC (cvc-wildcard):
25600 * processContents | context-determined declaration:
25601 * "strict" "mustFind"
25602 * "lax" "none"
25603 * "skip" "skip"
25604 */
25605 if (type->attributeWildcard->processContents ==
25606 XML_SCHEMAS_ANY_SKIP) {
25607 /*
25608 * context-determined declaration = "skip"
25609 *
25610 * SPEC PSVI Assessment Outcome (Attribute)
25611 * [validity] = "notKnown"
25612 * [validation attempted] = "none"
25613 */
25614 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25615 continue;
25616 }
25617 /*
25618 * Find an attribute declaration.
25619 */
25620 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25621 iattr->localName, iattr->nsName);
25622 if (iattr->decl != NULL) {
25623 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25624 /*
25625 * SPEC (cvc-complex-type)
25626 * (5) "Let [Definition:] the wild IDs be the set of
25627 * all attribute information item to which clause 3.2
25628 * applied and whose `validation` resulted in a
25629 * `context-determined declaration` of mustFind or no
25630 * `context-determined declaration` at all, and whose
25631 * [local name] and [namespace name] resolve (as
25632 * defined by QName resolution (Instance) ($3.15.4)) to
25633 * an attribute declaration whose {type definition} is
25634 * or is derived from ID. Then all of the following
25635 * must be true:"
25636 */
25637 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25638 if (xmlSchemaIsDerivedFromBuiltInType(
25639 iattr->typeDef, XML_SCHEMAS_ID)) {
25640 /*
25641 * SPEC (5.1) "There must be no more than one
25642 * item in `wild IDs`."
25643 */
25644 if (wildIDs != 0) {
25645 /* VAL TODO */
25646 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25647 TODO
25648 continue;
25649 }
25650 wildIDs++;
25651 /*
25652 * SPEC (cvc-complex-type)
25653 * (5.2) "If `wild IDs` is non-empty, there must not
25654 * be any attribute uses among the {attribute uses}
25655 * whose {attribute declaration}'s {type definition}
25656 * is or is derived from ID."
25657 */
25658 if (attrUseList != NULL) {
25659 for (j = 0; j < attrUseList->nbItems; j++) {
25660 if (xmlSchemaIsDerivedFromBuiltInType(
25661 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25662 XML_SCHEMAS_ID)) {
25663 /* URGENT VAL TODO: implement */
25664 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25665 TODO
25666 break;
25667 }
25668 }
25669 }
25670 }
25671 } else if (type->attributeWildcard->processContents ==
25672 XML_SCHEMAS_ANY_LAX) {
25673 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25674 /*
25675 * SPEC PSVI Assessment Outcome (Attribute)
25676 * [validity] = "notKnown"
25677 * [validation attempted] = "none"
25678 */
25679 } else {
25680 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25681 }
25682 }
25683 }
25684 }
25685
25686 if (vctxt->nbAttrInfos == 0)
25687 return (0);
25688
25689 /*
25690 * Get the owner element; needed for creation of default attributes.
25691 * This fixes bug #341337, reported by David Grohmann.
25692 */
25693 if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25694 xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25695 if (ielem && ielem->node && ielem->node->doc)
25696 defAttrOwnerElem = ielem->node;
25697 }
25698 /*
25699 * Validate values, create default attributes, evaluate IDCs.
25700 */
25701 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25702 iattr = vctxt->attrInfos[i];
25703 /*
25704 * VAL TODO: Note that we won't try to resolve IDCs to
25705 * "lax" and "skip" validated attributes. Check what to
25706 * do in this case.
25707 */
25708 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25709 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25710 continue;
25711 /*
25712 * VAL TODO: What to do if the type definition is missing?
25713 */
25714 if (iattr->typeDef == NULL) {
25715 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25716 continue;
25717 }
25718
25719 ACTIVATE_ATTRIBUTE(iattr);
25720 fixed = 0;
25721 xpathRes = 0;
25722
25723 if (vctxt->xpathStates != NULL) {
25724 /*
25725 * Evaluate IDCs.
25726 */
25727 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25728 XML_ATTRIBUTE_NODE);
25729 if (xpathRes == -1) {
25730 VERROR_INT("xmlSchemaVAttributesComplex",
25731 "calling xmlSchemaXPathEvaluate()");
25732 goto internal_error;
25733 }
25734 }
25735
25736 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25737 /*
25738 * Default/fixed attributes.
25739 * We need the value only if we need to resolve IDCs or
25740 * will create default attributes.
25741 */
25742 if ((xpathRes) || (defAttrOwnerElem)) {
25743 if (iattr->use->defValue != NULL) {
25744 iattr->value = (xmlChar *) iattr->use->defValue;
25745 iattr->val = iattr->use->defVal;
25746 } else {
25747 iattr->value = (xmlChar *) iattr->decl->defValue;
25748 iattr->val = iattr->decl->defVal;
25749 }
25750 /*
25751 * IDCs will consume the precomputed default value,
25752 * so we need to clone it.
25753 */
25754 if (iattr->val == NULL) {
25755 VERROR_INT("xmlSchemaVAttributesComplex",
25756 "default/fixed value on an attribute use was "
25757 "not precomputed");
25758 goto internal_error;
25759 }
25760 iattr->val = xmlSchemaCopyValue(iattr->val);
25761 if (iattr->val == NULL) {
25762 VERROR_INT("xmlSchemaVAttributesComplex",
25763 "calling xmlSchemaCopyValue()");
25764 goto internal_error;
25765 }
25766 }
25767 /*
25768 * PSVI: Add the default attribute to the current element.
25769 * VAL TODO: Should we use the *normalized* value? This currently
25770 * uses the *initial* value.
25771 */
25772
25773 if (defAttrOwnerElem) {
25774 xmlChar *normValue;
25775 const xmlChar *value;
25776
25777 value = iattr->value;
25778 /*
25779 * Normalize the value.
25780 */
25781 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25782 iattr->value);
25783 if (normValue != NULL)
25784 value = BAD_CAST normValue;
25785
25786 if (iattr->nsName == NULL) {
25787 if (xmlNewProp(defAttrOwnerElem,
25788 iattr->localName, value) == NULL) {
25789 VERROR_INT("xmlSchemaVAttributesComplex",
25790 "calling xmlNewProp()");
25791 if (normValue != NULL)
25792 xmlFree(normValue);
25793 goto internal_error;
25794 }
25795 } else {
25796 xmlNsPtr ns;
25797
25798 ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25799 defAttrOwnerElem, iattr->nsName);
25800 if (ns == NULL) {
25801 xmlChar prefix[12];
25802 int counter = 0;
25803
25804 /*
25805 * Create a namespace declaration on the validation
25806 * root node if no namespace declaration is in scope.
25807 */
25808 do {
25809 snprintf((char *) prefix, 12, "p%d", counter++);
25810 ns = xmlSearchNs(defAttrOwnerElem->doc,
25811 defAttrOwnerElem, BAD_CAST prefix);
25812 if (counter > 1000) {
25813 VERROR_INT(
25814 "xmlSchemaVAttributesComplex",
25815 "could not compute a ns prefix for a "
25816 "default/fixed attribute");
25817 if (normValue != NULL)
25818 xmlFree(normValue);
25819 goto internal_error;
25820 }
25821 } while (ns != NULL);
25822 ns = xmlNewNs(vctxt->validationRoot,
25823 iattr->nsName, BAD_CAST prefix);
25824 }
25825 /*
25826 * TODO:
25827 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25828 * If we have QNames: do we need to ensure there's a
25829 * prefix defined for the QName?
25830 */
25831 xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25832 }
25833 if (normValue != NULL)
25834 xmlFree(normValue);
25835 }
25836 /*
25837 * Go directly to IDC evaluation.
25838 */
25839 goto eval_idcs;
25840 }
25841 /*
25842 * Validate the value.
25843 */
25844 if (vctxt->value != NULL) {
25845 /*
25846 * Free last computed value; just for safety reasons.
25847 */
25848 xmlSchemaFreeValue(vctxt->value);
25849 vctxt->value = NULL;
25850 }
25851 /*
25852 * Note that the attribute *use* can be unavailable, if
25853 * the attribute was a wild attribute.
25854 */
25855 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25856 ((iattr->use != NULL) &&
25857 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25858 fixed = 1;
25859 else
25860 fixed = 0;
25861 /*
25862 * SPEC (cvc-attribute)
25863 * (3) "The item's `normalized value` must be locally `valid`
25864 * with respect to that {type definition} as per
25865 * String Valid ($3.14.4)."
25866 *
25867 * VAL TODO: Do we already have the
25868 * "normalized attribute value" here?
25869 */
25870 if (xpathRes || fixed) {
25871 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25872 /*
25873 * Request a computed value.
25874 */
25875 res = xmlSchemaVCheckCVCSimpleType(
25876 ACTXT_CAST vctxt,
25877 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25878 1, 1, 0);
25879 } else {
25880 res = xmlSchemaVCheckCVCSimpleType(
25881 ACTXT_CAST vctxt,
25882 iattr->node, iattr->typeDef, iattr->value, NULL,
25883 1, 0, 0);
25884 }
25885
25886 if (res != 0) {
25887 if (res == -1) {
25888 VERROR_INT("xmlSchemaVAttributesComplex",
25889 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25890 goto internal_error;
25891 }
25892 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25893 /*
25894 * SPEC PSVI Assessment Outcome (Attribute)
25895 * [validity] = "invalid"
25896 */
25897 goto eval_idcs;
25898 }
25899
25900 if (fixed) {
25901 /*
25902 * SPEC Attribute Locally Valid (Use) (cvc-au)
25903 * "For an attribute information item to be `valid`
25904 * with respect to an attribute use its *normalized*
25905 * value must match the *canonical* lexical
25906 * representation of the attribute use's {value
25907 * constraint}value, if it is present and fixed."
25908 *
25909 * VAL TODO: The requirement for the *canonical* value
25910 * will be removed in XML Schema 1.1.
25911 */
25912 /*
25913 * SPEC Attribute Locally Valid (cvc-attribute)
25914 * (4) "The item's *actual* value must match the *value* of
25915 * the {value constraint}, if it is present and fixed."
25916 */
25917 if (iattr->val == NULL) {
25918 /* VAL TODO: A value was not precomputed. */
25919 TODO
25920 goto eval_idcs;
25921 }
25922 if ((iattr->use != NULL) &&
25923 (iattr->use->defValue != NULL)) {
25924 if (iattr->use->defVal == NULL) {
25925 /* VAL TODO: A default value was not precomputed. */
25926 TODO
25927 goto eval_idcs;
25928 }
25929 iattr->vcValue = iattr->use->defValue;
25930 /*
25931 if (xmlSchemaCompareValuesWhtsp(attr->val,
25932 (xmlSchemaWhitespaceValueType) ws,
25933 attr->use->defVal,
25934 (xmlSchemaWhitespaceValueType) ws) != 0) {
25935 */
25936 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25937 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25938 } else {
25939 if (iattr->decl->defVal == NULL) {
25940 /* VAL TODO: A default value was not precomputed. */
25941 TODO
25942 goto eval_idcs;
25943 }
25944 iattr->vcValue = iattr->decl->defValue;
25945 /*
25946 if (xmlSchemaCompareValuesWhtsp(attr->val,
25947 (xmlSchemaWhitespaceValueType) ws,
25948 attrDecl->defVal,
25949 (xmlSchemaWhitespaceValueType) ws) != 0) {
25950 */
25951 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25952 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25953 }
25954 /*
25955 * [validity] = "valid"
25956 */
25957 }
25958 eval_idcs:
25959 /*
25960 * Evaluate IDCs.
25961 */
25962 if (xpathRes) {
25963 if (xmlSchemaXPathProcessHistory(vctxt,
25964 vctxt->depth +1) == -1) {
25965 VERROR_INT("xmlSchemaVAttributesComplex",
25966 "calling xmlSchemaXPathEvaluate()");
25967 goto internal_error;
25968 }
25969 } else if (vctxt->xpathStates != NULL)
25970 xmlSchemaXPathPop(vctxt);
25971 }
25972
25973 /*
25974 * Report errors.
25975 */
25976 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25977 iattr = vctxt->attrInfos[i];
25978 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25979 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25980 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25981 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25982 continue;
25983 ACTIVATE_ATTRIBUTE(iattr);
25984 switch (iattr->state) {
25985 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25986 xmlChar *str = NULL;
25987 ACTIVATE_ELEM;
25988 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25989 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25990 "The attribute '%s' is required but missing",
25991 xmlSchemaFormatQName(&str,
25992 iattr->decl->targetNamespace,
25993 iattr->decl->name),
25994 NULL);
25995 FREE_AND_NULL(str)
25996 break;
25997 }
25998 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25999 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
26000 "The type definition is absent");
26001 break;
26002 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
26003 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26004 XML_SCHEMAV_CVC_AU, NULL, NULL,
26005 "The value '%s' does not match the fixed "
26006 "value constraint '%s'",
26007 iattr->value, iattr->vcValue);
26008 break;
26009 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
26010 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
26011 "No matching global attribute declaration available, but "
26012 "demanded by the strict wildcard");
26013 break;
26014 case XML_SCHEMAS_ATTR_UNKNOWN:
26015 if (iattr->metaType)
26016 break;
26017 /*
26018 * MAYBE VAL TODO: One might report different error messages
26019 * for the following errors.
26020 */
26021 if (type->attributeWildcard == NULL) {
26022 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
26023 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
26024 } else {
26025 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
26026 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
26027 }
26028 break;
26029 default:
26030 break;
26031 }
26032 }
26033
26034 ACTIVATE_ELEM;
26035 return (0);
26036 internal_error:
26037 ACTIVATE_ELEM;
26038 return (-1);
26039 }
26040
26041 static int
xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,int * skip)26042 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
26043 int *skip)
26044 {
26045 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
26046 /*
26047 * The namespace of the element was already identified to be
26048 * matching the wildcard.
26049 */
26050 if ((skip == NULL) || (wild == NULL) ||
26051 (wild->type != XML_SCHEMA_TYPE_ANY)) {
26052 VERROR_INT("xmlSchemaValidateElemWildcard",
26053 "bad arguments");
26054 return (-1);
26055 }
26056 *skip = 0;
26057 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
26058 /*
26059 * URGENT VAL TODO: Either we need to position the stream to the
26060 * next sibling, or walk the whole subtree.
26061 */
26062 *skip = 1;
26063 return (0);
26064 }
26065 {
26066 xmlSchemaElementPtr decl = NULL;
26067
26068 decl = xmlSchemaGetElem(vctxt->schema,
26069 vctxt->inode->localName, vctxt->inode->nsName);
26070 if (decl != NULL) {
26071 vctxt->inode->decl = decl;
26072 return (0);
26073 }
26074 }
26075 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
26076 /* VAL TODO: Change to proper error code. */
26077 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
26078 "No matching global element declaration available, but "
26079 "demanded by the strict wildcard");
26080 return (vctxt->err);
26081 }
26082 if (vctxt->nbAttrInfos != 0) {
26083 xmlSchemaAttrInfoPtr iattr;
26084 /*
26085 * SPEC Validation Rule: Schema-Validity Assessment (Element)
26086 * (1.2.1.2.1) - (1.2.1.2.3 )
26087 *
26088 * Use the xsi:type attribute for the type definition.
26089 */
26090 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26091 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26092 if (iattr != NULL) {
26093 if (xmlSchemaProcessXSIType(vctxt, iattr,
26094 &(vctxt->inode->typeDef), NULL) == -1) {
26095 VERROR_INT("xmlSchemaValidateElemWildcard",
26096 "calling xmlSchemaProcessXSIType() to "
26097 "process the attribute 'xsi:nil'");
26098 return (-1);
26099 }
26100 /*
26101 * Don't return an error on purpose.
26102 */
26103 return (0);
26104 }
26105 }
26106 /*
26107 * SPEC Validation Rule: Schema-Validity Assessment (Element)
26108 *
26109 * Fallback to "anyType".
26110 */
26111 vctxt->inode->typeDef =
26112 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26113 return (0);
26114 }
26115
26116 /*
26117 * xmlSchemaCheckCOSValidDefault:
26118 *
26119 * This will be called if: not nilled, no content and a default/fixed
26120 * value is provided.
26121 */
26122
26123 static int
xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val)26124 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
26125 const xmlChar *value,
26126 xmlSchemaValPtr *val)
26127 {
26128 int ret = 0;
26129 xmlSchemaNodeInfoPtr inode = vctxt->inode;
26130
26131 /*
26132 * cos-valid-default:
26133 * Schema Component Constraint: Element Default Valid (Immediate)
26134 * For a string to be a valid default with respect to a type
26135 * definition the appropriate case among the following must be true:
26136 */
26137 if WXS_IS_COMPLEX(inode->typeDef) {
26138 /*
26139 * Complex type.
26140 *
26141 * SPEC (2.1) "its {content type} must be a simple type definition
26142 * or mixed."
26143 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
26144 * type}'s particle must be `emptiable` as defined by
26145 * Particle Emptiable ($3.9.6)."
26146 */
26147 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
26148 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
26149 (! WXS_EMPTIABLE(inode->typeDef)))) {
26150 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
26151 /* NOTE that this covers (2.2.2) as well. */
26152 VERROR(ret, NULL,
26153 "For a string to be a valid default, the type definition "
26154 "must be a simple type or a complex type with simple content "
26155 "or mixed content and a particle emptiable");
26156 return(ret);
26157 }
26158 }
26159 /*
26160 * 1 If the type definition is a simple type definition, then the string
26161 * must be `valid` with respect to that definition as defined by String
26162 * Valid ($3.14.4).
26163 *
26164 * AND
26165 *
26166 * 2.2.1 If the {content type} is a simple type definition, then the
26167 * string must be `valid` with respect to that simple type definition
26168 * as defined by String Valid ($3.14.4).
26169 */
26170 if (WXS_IS_SIMPLE(inode->typeDef)) {
26171
26172 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26173 NULL, inode->typeDef, value, val, 1, 1, 0);
26174
26175 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26176
26177 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26178 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
26179 }
26180 if (ret < 0) {
26181 VERROR_INT("xmlSchemaCheckCOSValidDefault",
26182 "calling xmlSchemaVCheckCVCSimpleType()");
26183 }
26184 return (ret);
26185 }
26186
26187 static void
xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED,void * transdata,void * inputdata)26188 xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
26189 const xmlChar * name ATTRIBUTE_UNUSED,
26190 void *transdata, void *inputdata)
26191 {
26192 xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
26193 xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
26194 inode->decl = item;
26195 #ifdef DEBUG_CONTENT
26196 {
26197 xmlChar *str = NULL;
26198
26199 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
26200 xmlGenericError(xmlGenericErrorContext,
26201 "AUTOMATON callback for '%s' [declaration]\n",
26202 xmlSchemaFormatQName(&str,
26203 inode->localName, inode->nsName));
26204 } else {
26205 xmlGenericError(xmlGenericErrorContext,
26206 "AUTOMATON callback for '%s' [wildcard]\n",
26207 xmlSchemaFormatQName(&str,
26208 inode->localName, inode->nsName));
26209
26210 }
26211 FREE_AND_NULL(str)
26212 }
26213 #endif
26214 }
26215
26216 static int
xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)26217 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
26218 {
26219 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
26220 if (vctxt->inode == NULL) {
26221 VERROR_INT("xmlSchemaValidatorPushElem",
26222 "calling xmlSchemaGetFreshElemInfo()");
26223 return (-1);
26224 }
26225 vctxt->nbAttrInfos = 0;
26226 return (0);
26227 }
26228
26229 static int
xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr inode,xmlSchemaTypePtr type,const xmlChar * value)26230 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
26231 xmlSchemaNodeInfoPtr inode,
26232 xmlSchemaTypePtr type,
26233 const xmlChar *value)
26234 {
26235 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
26236 return (xmlSchemaVCheckCVCSimpleType(
26237 ACTXT_CAST vctxt, NULL,
26238 type, value, &(inode->val), 1, 1, 0));
26239 else
26240 return (xmlSchemaVCheckCVCSimpleType(
26241 ACTXT_CAST vctxt, NULL,
26242 type, value, NULL, 1, 0, 0));
26243 }
26244
26245
26246
26247 /*
26248 * Process END of element.
26249 */
26250 static int
xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)26251 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26252 {
26253 int ret = 0;
26254 xmlSchemaNodeInfoPtr inode = vctxt->inode;
26255
26256 if (vctxt->nbAttrInfos != 0)
26257 xmlSchemaClearAttrInfos(vctxt);
26258 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26259 /*
26260 * This element was not expected;
26261 * we will not validate child elements of broken parents.
26262 * Skip validation of all content of the parent.
26263 */
26264 vctxt->skipDepth = vctxt->depth -1;
26265 goto end_elem;
26266 }
26267 if ((inode->typeDef == NULL) ||
26268 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26269 /*
26270 * 1. the type definition might be missing if the element was
26271 * error prone
26272 * 2. it might be abstract.
26273 */
26274 goto end_elem;
26275 }
26276 /*
26277 * Check the content model.
26278 */
26279 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26280 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26281
26282 /*
26283 * Workaround for "anyType".
26284 */
26285 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26286 goto character_content;
26287
26288 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26289 xmlChar *values[10];
26290 int terminal, nbval = 10, nbneg;
26291
26292 if (inode->regexCtxt == NULL) {
26293 /*
26294 * Create the regex context.
26295 */
26296 inode->regexCtxt =
26297 xmlRegNewExecCtxt(inode->typeDef->contModel,
26298 xmlSchemaVContentModelCallback, vctxt);
26299 if (inode->regexCtxt == NULL) {
26300 VERROR_INT("xmlSchemaValidatorPopElem",
26301 "failed to create a regex context");
26302 goto internal_error;
26303 }
26304 #ifdef DEBUG_AUTOMATA
26305 xmlGenericError(xmlGenericErrorContext,
26306 "AUTOMATON create on '%s'\n", inode->localName);
26307 #endif
26308 }
26309
26310 /*
26311 * Do not check further content if the node has been nilled
26312 */
26313 if (INODE_NILLED(inode)) {
26314 ret = 0;
26315 #ifdef DEBUG_AUTOMATA
26316 xmlGenericError(xmlGenericErrorContext,
26317 "AUTOMATON succeeded on nilled '%s'\n",
26318 inode->localName);
26319 #endif
26320 goto skip_nilled;
26321 }
26322
26323 /*
26324 * Get hold of the still expected content, since a further
26325 * call to xmlRegExecPushString() will lose this information.
26326 */
26327 xmlRegExecNextValues(inode->regexCtxt,
26328 &nbval, &nbneg, &values[0], &terminal);
26329 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26330 if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26331 /*
26332 * Still missing something.
26333 */
26334 ret = 1;
26335 inode->flags |=
26336 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26337 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26338 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26339 "Missing child element(s)",
26340 nbval, nbneg, values);
26341 #ifdef DEBUG_AUTOMATA
26342 xmlGenericError(xmlGenericErrorContext,
26343 "AUTOMATON missing ERROR on '%s'\n",
26344 inode->localName);
26345 #endif
26346 } else {
26347 /*
26348 * Content model is satisfied.
26349 */
26350 ret = 0;
26351 #ifdef DEBUG_AUTOMATA
26352 xmlGenericError(xmlGenericErrorContext,
26353 "AUTOMATON succeeded on '%s'\n",
26354 inode->localName);
26355 #endif
26356 }
26357
26358 }
26359 }
26360
26361 skip_nilled:
26362
26363 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26364 goto end_elem;
26365
26366 character_content:
26367
26368 if (vctxt->value != NULL) {
26369 xmlSchemaFreeValue(vctxt->value);
26370 vctxt->value = NULL;
26371 }
26372 /*
26373 * Check character content.
26374 */
26375 if (inode->decl == NULL) {
26376 /*
26377 * Speedup if no declaration exists.
26378 */
26379 if (WXS_IS_SIMPLE(inode->typeDef)) {
26380 ret = xmlSchemaVCheckINodeDataType(vctxt,
26381 inode, inode->typeDef, inode->value);
26382 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26383 ret = xmlSchemaVCheckINodeDataType(vctxt,
26384 inode, inode->typeDef->contentTypeDef,
26385 inode->value);
26386 }
26387 if (ret < 0) {
26388 VERROR_INT("xmlSchemaValidatorPopElem",
26389 "calling xmlSchemaVCheckCVCSimpleType()");
26390 goto internal_error;
26391 }
26392 goto end_elem;
26393 }
26394 /*
26395 * cvc-elt (3.3.4) : 5
26396 * The appropriate case among the following must be true:
26397 */
26398 /*
26399 * cvc-elt (3.3.4) : 5.1
26400 * If the declaration has a {value constraint},
26401 * the item has neither element nor character [children] and
26402 * clause 3.2 has not applied, then all of the following must be true:
26403 */
26404 if ((inode->decl->value != NULL) &&
26405 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26406 (! INODE_NILLED(inode))) {
26407 /*
26408 * cvc-elt (3.3.4) : 5.1.1
26409 * If the `actual type definition` is a `local type definition`
26410 * then the canonical lexical representation of the {value constraint}
26411 * value must be a valid default for the `actual type definition` as
26412 * defined in Element Default Valid (Immediate) ($3.3.6).
26413 */
26414 /*
26415 * NOTE: 'local' above means types acquired by xsi:type.
26416 * NOTE: Although the *canonical* value is stated, it is not
26417 * relevant if canonical or not. Additionally XML Schema 1.1
26418 * will removed this requirement as well.
26419 */
26420 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26421
26422 ret = xmlSchemaCheckCOSValidDefault(vctxt,
26423 inode->decl->value, &(inode->val));
26424 if (ret != 0) {
26425 if (ret < 0) {
26426 VERROR_INT("xmlSchemaValidatorPopElem",
26427 "calling xmlSchemaCheckCOSValidDefault()");
26428 goto internal_error;
26429 }
26430 goto end_elem;
26431 }
26432 /*
26433 * Stop here, to avoid redundant validation of the value
26434 * (see following).
26435 */
26436 goto default_psvi;
26437 }
26438 /*
26439 * cvc-elt (3.3.4) : 5.1.2
26440 * The element information item with the canonical lexical
26441 * representation of the {value constraint} value used as its
26442 * `normalized value` must be `valid` with respect to the
26443 * `actual type definition` as defined by Element Locally Valid (Type)
26444 * ($3.3.4).
26445 */
26446 if (WXS_IS_SIMPLE(inode->typeDef)) {
26447 ret = xmlSchemaVCheckINodeDataType(vctxt,
26448 inode, inode->typeDef, inode->decl->value);
26449 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26450 ret = xmlSchemaVCheckINodeDataType(vctxt,
26451 inode, inode->typeDef->contentTypeDef,
26452 inode->decl->value);
26453 }
26454 if (ret != 0) {
26455 if (ret < 0) {
26456 VERROR_INT("xmlSchemaValidatorPopElem",
26457 "calling xmlSchemaVCheckCVCSimpleType()");
26458 goto internal_error;
26459 }
26460 goto end_elem;
26461 }
26462
26463 default_psvi:
26464 /*
26465 * PSVI: Create a text node on the instance element.
26466 */
26467 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26468 (inode->node != NULL)) {
26469 xmlNodePtr textChild;
26470 xmlChar *normValue;
26471 /*
26472 * VAL TODO: Normalize the value.
26473 */
26474 normValue = xmlSchemaNormalizeValue(inode->typeDef,
26475 inode->decl->value);
26476 if (normValue != NULL) {
26477 textChild = xmlNewText(BAD_CAST normValue);
26478 xmlFree(normValue);
26479 } else
26480 textChild = xmlNewText(inode->decl->value);
26481 if (textChild == NULL) {
26482 VERROR_INT("xmlSchemaValidatorPopElem",
26483 "calling xmlNewText()");
26484 goto internal_error;
26485 } else
26486 xmlAddChild(inode->node, textChild);
26487 }
26488
26489 } else if (! INODE_NILLED(inode)) {
26490 /*
26491 * 5.2.1 The element information item must be `valid` with respect
26492 * to the `actual type definition` as defined by Element Locally
26493 * Valid (Type) ($3.3.4).
26494 */
26495 if (WXS_IS_SIMPLE(inode->typeDef)) {
26496 /*
26497 * SPEC (cvc-type) (3.1)
26498 * "If the type definition is a simple type definition, ..."
26499 * (3.1.3) "If clause 3.2 of Element Locally Valid
26500 * (Element) ($3.3.4) did not apply, then the `normalized value`
26501 * must be `valid` with respect to the type definition as defined
26502 * by String Valid ($3.14.4).
26503 */
26504 ret = xmlSchemaVCheckINodeDataType(vctxt,
26505 inode, inode->typeDef, inode->value);
26506 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26507 /*
26508 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26509 * definition, then the element information item must be
26510 * `valid` with respect to the type definition as per
26511 * Element Locally Valid (Complex Type) ($3.4.4);"
26512 *
26513 * SPEC (cvc-complex-type) (2.2)
26514 * "If the {content type} is a simple type definition, ...
26515 * the `normalized value` of the element information item is
26516 * `valid` with respect to that simple type definition as
26517 * defined by String Valid ($3.14.4)."
26518 */
26519 ret = xmlSchemaVCheckINodeDataType(vctxt,
26520 inode, inode->typeDef->contentTypeDef, inode->value);
26521 }
26522 if (ret != 0) {
26523 if (ret < 0) {
26524 VERROR_INT("xmlSchemaValidatorPopElem",
26525 "calling xmlSchemaVCheckCVCSimpleType()");
26526 goto internal_error;
26527 }
26528 goto end_elem;
26529 }
26530 /*
26531 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26532 * not applied, all of the following must be true:
26533 */
26534 if ((inode->decl->value != NULL) &&
26535 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26536
26537 /*
26538 * TODO: We will need a computed value, when comparison is
26539 * done on computed values.
26540 */
26541 /*
26542 * 5.2.2.1 The element information item must have no element
26543 * information item [children].
26544 */
26545 if (inode->flags &
26546 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26547 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26548 VERROR(ret, NULL,
26549 "The content must not contain element nodes since "
26550 "there is a fixed value constraint");
26551 goto end_elem;
26552 } else {
26553 /*
26554 * 5.2.2.2 The appropriate case among the following must
26555 * be true:
26556 */
26557 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26558 /*
26559 * 5.2.2.2.1 If the {content type} of the `actual type
26560 * definition` is mixed, then the *initial value* of the
26561 * item must match the canonical lexical representation
26562 * of the {value constraint} value.
26563 *
26564 * ... the *initial value* of an element information
26565 * item is the string composed of, in order, the
26566 * [character code] of each character information item in
26567 * the [children] of that element information item.
26568 */
26569 if (! xmlStrEqual(inode->value, inode->decl->value)){
26570 /*
26571 * VAL TODO: Report invalid & expected values as well.
26572 * VAL TODO: Implement the canonical stuff.
26573 */
26574 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26575 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26576 ret, NULL, NULL,
26577 "The initial value '%s' does not match the fixed "
26578 "value constraint '%s'",
26579 inode->value, inode->decl->value);
26580 goto end_elem;
26581 }
26582 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26583 /*
26584 * 5.2.2.2.2 If the {content type} of the `actual type
26585 * definition` is a simple type definition, then the
26586 * *actual value* of the item must match the canonical
26587 * lexical representation of the {value constraint} value.
26588 */
26589 /*
26590 * VAL TODO: *actual value* is the normalized value, impl.
26591 * this.
26592 * VAL TODO: Report invalid & expected values as well.
26593 * VAL TODO: Implement a comparison with the computed values.
26594 */
26595 if (! xmlStrEqual(inode->value,
26596 inode->decl->value)) {
26597 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26598 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26599 ret, NULL, NULL,
26600 "The actual value '%s' does not match the fixed "
26601 "value constraint '%s'",
26602 inode->value,
26603 inode->decl->value);
26604 goto end_elem;
26605 }
26606 }
26607 }
26608 }
26609 }
26610
26611 end_elem:
26612 if (vctxt->depth < 0) {
26613 /* TODO: raise error? */
26614 return (0);
26615 }
26616 if (vctxt->depth == vctxt->skipDepth)
26617 vctxt->skipDepth = -1;
26618 /*
26619 * Evaluate the history of XPath state objects.
26620 */
26621 if (inode->appliedXPath &&
26622 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26623 goto internal_error;
26624 /*
26625 * MAYBE TODO:
26626 * SPEC (6) "The element information item must be `valid` with
26627 * respect to each of the {identity-constraint definitions} as per
26628 * Identity-constraint Satisfied ($3.11.4)."
26629 */
26630 /*
26631 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26632 * need to be built in any case.
26633 * We will currently build IDC node-tables and bubble them only if
26634 * keyrefs do exist.
26635 */
26636
26637 /*
26638 * Add the current IDC target-nodes to the IDC node-tables.
26639 */
26640 if ((inode->idcMatchers != NULL) &&
26641 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26642 {
26643 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26644 goto internal_error;
26645 }
26646 /*
26647 * Validate IDC keyrefs.
26648 */
26649 if (vctxt->inode->hasKeyrefs)
26650 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26651 goto internal_error;
26652 /*
26653 * Merge/free the IDC table.
26654 */
26655 if (inode->idcTable != NULL) {
26656 #ifdef DEBUG_IDC_NODE_TABLE
26657 xmlSchemaDebugDumpIDCTable(stdout,
26658 inode->nsName,
26659 inode->localName,
26660 inode->idcTable);
26661 #endif
26662 if ((vctxt->depth > 0) &&
26663 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26664 {
26665 /*
26666 * Merge the IDC node table with the table of the parent node.
26667 */
26668 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26669 goto internal_error;
26670 }
26671 }
26672 /*
26673 * Clear the current ielem.
26674 * VAL TODO: Don't free the PSVI IDC tables if they are
26675 * requested for the PSVI.
26676 */
26677 xmlSchemaClearElemInfo(vctxt, inode);
26678 /*
26679 * Skip further processing if we are on the validation root.
26680 */
26681 if (vctxt->depth == 0) {
26682 vctxt->depth--;
26683 vctxt->inode = NULL;
26684 return (0);
26685 }
26686 /*
26687 * Reset the keyrefDepth if needed.
26688 */
26689 if (vctxt->aidcs != NULL) {
26690 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26691 do {
26692 if (aidc->keyrefDepth == vctxt->depth) {
26693 /*
26694 * A 'keyrefDepth' of a key/unique IDC matches the current
26695 * depth, this means that we are leaving the scope of the
26696 * top-most keyref IDC which refers to this IDC.
26697 */
26698 aidc->keyrefDepth = -1;
26699 }
26700 aidc = aidc->next;
26701 } while (aidc != NULL);
26702 }
26703 vctxt->depth--;
26704 vctxt->inode = vctxt->elemInfos[vctxt->depth];
26705 /*
26706 * VAL TODO: 7 If the element information item is the `validation root`, it must be
26707 * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26708 */
26709 return (ret);
26710
26711 internal_error:
26712 vctxt->err = -1;
26713 return (-1);
26714 }
26715
26716 /*
26717 * 3.4.4 Complex Type Definition Validation Rules
26718 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26719 */
26720 static int
xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)26721 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26722 {
26723 xmlSchemaNodeInfoPtr pielem;
26724 xmlSchemaTypePtr ptype;
26725 int ret = 0;
26726
26727 if (vctxt->depth <= 0) {
26728 VERROR_INT("xmlSchemaValidateChildElem",
26729 "not intended for the validation root");
26730 return (-1);
26731 }
26732 pielem = vctxt->elemInfos[vctxt->depth -1];
26733 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26734 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26735 /*
26736 * Handle 'nilled' elements.
26737 */
26738 if (INODE_NILLED(pielem)) {
26739 /*
26740 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26741 */
26742 ACTIVATE_PARENT_ELEM;
26743 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26744 VERROR(ret, NULL,
26745 "Neither character nor element content is allowed, "
26746 "because the element was 'nilled'");
26747 ACTIVATE_ELEM;
26748 goto unexpected_elem;
26749 }
26750
26751 ptype = pielem->typeDef;
26752
26753 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26754 /*
26755 * Workaround for "anyType": we have currently no content model
26756 * assigned for "anyType", so handle it explicitly.
26757 * "anyType" has an unbounded, lax "any" wildcard.
26758 */
26759 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26760 vctxt->inode->localName,
26761 vctxt->inode->nsName);
26762
26763 if (vctxt->inode->decl == NULL) {
26764 xmlSchemaAttrInfoPtr iattr;
26765 /*
26766 * Process "xsi:type".
26767 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26768 */
26769 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26770 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26771 if (iattr != NULL) {
26772 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26773 &(vctxt->inode->typeDef), NULL);
26774 if (ret != 0) {
26775 if (ret == -1) {
26776 VERROR_INT("xmlSchemaValidateChildElem",
26777 "calling xmlSchemaProcessXSIType() to "
26778 "process the attribute 'xsi:nil'");
26779 return (-1);
26780 }
26781 return (ret);
26782 }
26783 } else {
26784 /*
26785 * Fallback to "anyType".
26786 *
26787 * SPEC (cvc-assess-elt)
26788 * "If the item cannot be `strictly assessed`, [...]
26789 * an element information item's schema validity may be laxly
26790 * assessed if its `context-determined declaration` is not
26791 * skip by `validating` with respect to the `ur-type
26792 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26793 */
26794 vctxt->inode->typeDef =
26795 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26796 }
26797 }
26798 return (0);
26799 }
26800
26801 switch (ptype->contentType) {
26802 case XML_SCHEMA_CONTENT_EMPTY:
26803 /*
26804 * SPEC (2.1) "If the {content type} is empty, then the
26805 * element information item has no character or element
26806 * information item [children]."
26807 */
26808 ACTIVATE_PARENT_ELEM
26809 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26810 VERROR(ret, NULL,
26811 "Element content is not allowed, "
26812 "because the content type is empty");
26813 ACTIVATE_ELEM
26814 goto unexpected_elem;
26815 break;
26816
26817 case XML_SCHEMA_CONTENT_MIXED:
26818 case XML_SCHEMA_CONTENT_ELEMENTS: {
26819 xmlRegExecCtxtPtr regexCtxt;
26820 xmlChar *values[10];
26821 int terminal, nbval = 10, nbneg;
26822
26823 /* VAL TODO: Optimized "anyType" validation.*/
26824
26825 if (ptype->contModel == NULL) {
26826 VERROR_INT("xmlSchemaValidateChildElem",
26827 "type has elem content but no content model");
26828 return (-1);
26829 }
26830 /*
26831 * Safety belt for evaluation if the cont. model was already
26832 * examined to be invalid.
26833 */
26834 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26835 VERROR_INT("xmlSchemaValidateChildElem",
26836 "validating elem, but elem content is already invalid");
26837 return (-1);
26838 }
26839
26840 regexCtxt = pielem->regexCtxt;
26841 if (regexCtxt == NULL) {
26842 /*
26843 * Create the regex context.
26844 */
26845 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26846 xmlSchemaVContentModelCallback, vctxt);
26847 if (regexCtxt == NULL) {
26848 VERROR_INT("xmlSchemaValidateChildElem",
26849 "failed to create a regex context");
26850 return (-1);
26851 }
26852 pielem->regexCtxt = regexCtxt;
26853 #ifdef DEBUG_AUTOMATA
26854 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26855 pielem->localName);
26856 #endif
26857 }
26858
26859 /*
26860 * SPEC (2.4) "If the {content type} is element-only or mixed,
26861 * then the sequence of the element information item's
26862 * element information item [children], if any, taken in
26863 * order, is `valid` with respect to the {content type}'s
26864 * particle, as defined in Element Sequence Locally Valid
26865 * (Particle) ($3.9.4)."
26866 */
26867 ret = xmlRegExecPushString2(regexCtxt,
26868 vctxt->inode->localName,
26869 vctxt->inode->nsName,
26870 vctxt->inode);
26871 #ifdef DEBUG_AUTOMATA
26872 if (ret < 0)
26873 xmlGenericError(xmlGenericErrorContext,
26874 "AUTOMATON push ERROR for '%s' on '%s'\n",
26875 vctxt->inode->localName, pielem->localName);
26876 else
26877 xmlGenericError(xmlGenericErrorContext,
26878 "AUTOMATON push OK for '%s' on '%s'\n",
26879 vctxt->inode->localName, pielem->localName);
26880 #endif
26881 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26882 VERROR_INT("xmlSchemaValidateChildElem",
26883 "calling xmlRegExecPushString2()");
26884 return (-1);
26885 }
26886 if (ret < 0) {
26887 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26888 &values[0], &terminal);
26889 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26890 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26891 "This element is not expected",
26892 nbval, nbneg, values);
26893 ret = vctxt->err;
26894 goto unexpected_elem;
26895 } else
26896 ret = 0;
26897 }
26898 break;
26899 case XML_SCHEMA_CONTENT_SIMPLE:
26900 case XML_SCHEMA_CONTENT_BASIC:
26901 ACTIVATE_PARENT_ELEM
26902 if (WXS_IS_COMPLEX(ptype)) {
26903 /*
26904 * SPEC (cvc-complex-type) (2.2)
26905 * "If the {content type} is a simple type definition, then
26906 * the element information item has no element information
26907 * item [children], ..."
26908 */
26909 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26910 VERROR(ret, NULL, "Element content is not allowed, "
26911 "because the content type is a simple type definition");
26912 } else {
26913 /*
26914 * SPEC (cvc-type) (3.1.2) "The element information item must
26915 * have no element information item [children]."
26916 */
26917 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26918 VERROR(ret, NULL, "Element content is not allowed, "
26919 "because the type definition is simple");
26920 }
26921 ACTIVATE_ELEM
26922 ret = vctxt->err;
26923 goto unexpected_elem;
26924 break;
26925
26926 default:
26927 break;
26928 }
26929 return (ret);
26930 unexpected_elem:
26931 /*
26932 * Pop this element and set the skipDepth to skip
26933 * all further content of the parent element.
26934 */
26935 vctxt->skipDepth = vctxt->depth;
26936 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26937 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26938 return (ret);
26939 }
26940
26941 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26942 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26943 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26944
26945 static int
xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,int nodeType,const xmlChar * value,int len,int mode,int * consumed)26946 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26947 int nodeType, const xmlChar *value, int len,
26948 int mode, int *consumed)
26949 {
26950 /*
26951 * Unfortunately we have to duplicate the text sometimes.
26952 * OPTIMIZE: Maybe we could skip it, if:
26953 * 1. content type is simple
26954 * 2. whitespace is "collapse"
26955 * 3. it consists of whitespace only
26956 *
26957 * Process character content.
26958 */
26959 if (consumed != NULL)
26960 *consumed = 0;
26961 if (INODE_NILLED(vctxt->inode)) {
26962 /*
26963 * SPEC cvc-elt (3.3.4 - 3.2.1)
26964 * "The element information item must have no character or
26965 * element information item [children]."
26966 */
26967 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26968 "Neither character nor element content is allowed "
26969 "because the element is 'nilled'");
26970 return (vctxt->err);
26971 }
26972 /*
26973 * SPEC (2.1) "If the {content type} is empty, then the
26974 * element information item has no character or element
26975 * information item [children]."
26976 */
26977 if (vctxt->inode->typeDef->contentType ==
26978 XML_SCHEMA_CONTENT_EMPTY) {
26979 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26980 "Character content is not allowed, "
26981 "because the content type is empty");
26982 return (vctxt->err);
26983 }
26984
26985 if (vctxt->inode->typeDef->contentType ==
26986 XML_SCHEMA_CONTENT_ELEMENTS) {
26987 if ((nodeType != XML_TEXT_NODE) ||
26988 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26989 /*
26990 * SPEC cvc-complex-type (2.3)
26991 * "If the {content type} is element-only, then the
26992 * element information item has no character information
26993 * item [children] other than those whose [character
26994 * code] is defined as a white space in [XML 1.0 (Second
26995 * Edition)]."
26996 */
26997 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26998 "Character content other than whitespace is not allowed "
26999 "because the content type is 'element-only'");
27000 return (vctxt->err);
27001 }
27002 return (0);
27003 }
27004
27005 if ((value == NULL) || (value[0] == 0))
27006 return (0);
27007 /*
27008 * Save the value.
27009 * NOTE that even if the content type is *mixed*, we need the
27010 * *initial value* for default/fixed value constraints.
27011 */
27012 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
27013 ((vctxt->inode->decl == NULL) ||
27014 (vctxt->inode->decl->value == NULL)))
27015 return (0);
27016
27017 if (vctxt->inode->value == NULL) {
27018 /*
27019 * Set the value.
27020 */
27021 switch (mode) {
27022 case XML_SCHEMA_PUSH_TEXT_PERSIST:
27023 /*
27024 * When working on a tree.
27025 */
27026 vctxt->inode->value = value;
27027 break;
27028 case XML_SCHEMA_PUSH_TEXT_CREATED:
27029 /*
27030 * When working with the reader.
27031 * The value will be freed by the element info.
27032 */
27033 vctxt->inode->value = value;
27034 if (consumed != NULL)
27035 *consumed = 1;
27036 vctxt->inode->flags |=
27037 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27038 break;
27039 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
27040 /*
27041 * When working with SAX.
27042 * The value will be freed by the element info.
27043 */
27044 if (len != -1)
27045 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
27046 else
27047 vctxt->inode->value = BAD_CAST xmlStrdup(value);
27048 vctxt->inode->flags |=
27049 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27050 break;
27051 default:
27052 break;
27053 }
27054 } else {
27055 if (len < 0)
27056 len = xmlStrlen(value);
27057 /*
27058 * Concat the value.
27059 */
27060 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
27061 vctxt->inode->value = BAD_CAST xmlStrncat(
27062 (xmlChar *) vctxt->inode->value, value, len);
27063 } else {
27064 vctxt->inode->value =
27065 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
27066 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27067 }
27068 }
27069
27070 return (0);
27071 }
27072
27073 static int
xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)27074 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
27075 {
27076 int ret = 0;
27077
27078 if ((vctxt->skipDepth != -1) &&
27079 (vctxt->depth >= vctxt->skipDepth)) {
27080 VERROR_INT("xmlSchemaValidateElem",
27081 "in skip-state");
27082 goto internal_error;
27083 }
27084 if (vctxt->xsiAssemble) {
27085 /*
27086 * We will stop validation if there was an error during
27087 * dynamic schema construction.
27088 * Note that we simply set @skipDepth to 0, this could
27089 * mean that a streaming document via SAX would be
27090 * still read to the end but it won't be validated any more.
27091 * TODO: If we are sure how to stop the validation at once
27092 * for all input scenarios, then this should be changed to
27093 * instantly stop the validation.
27094 */
27095 ret = xmlSchemaAssembleByXSI(vctxt);
27096 if (ret != 0) {
27097 if (ret == -1)
27098 goto internal_error;
27099 vctxt->skipDepth = 0;
27100 return(ret);
27101 }
27102 /*
27103 * Augment the IDC definitions for the main schema and all imported ones
27104 * NOTE: main schema is the first in the imported list
27105 */
27106 xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
27107 vctxt);
27108 }
27109 if (vctxt->depth > 0) {
27110 /*
27111 * Validate this element against the content model
27112 * of the parent.
27113 */
27114 ret = xmlSchemaValidateChildElem(vctxt);
27115 if (ret != 0) {
27116 if (ret < 0) {
27117 VERROR_INT("xmlSchemaValidateElem",
27118 "calling xmlSchemaStreamValidateChildElement()");
27119 goto internal_error;
27120 }
27121 goto exit;
27122 }
27123 if (vctxt->depth == vctxt->skipDepth)
27124 goto exit;
27125 if ((vctxt->inode->decl == NULL) &&
27126 (vctxt->inode->typeDef == NULL)) {
27127 VERROR_INT("xmlSchemaValidateElem",
27128 "the child element was valid but neither the "
27129 "declaration nor the type was set");
27130 goto internal_error;
27131 }
27132 } else {
27133 /*
27134 * Get the declaration of the validation root.
27135 */
27136 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
27137 vctxt->inode->localName,
27138 vctxt->inode->nsName);
27139 if (vctxt->inode->decl == NULL) {
27140 ret = XML_SCHEMAV_CVC_ELT_1;
27141 VERROR(ret, NULL,
27142 "No matching global declaration available "
27143 "for the validation root");
27144 goto exit;
27145 }
27146 }
27147
27148 if (vctxt->inode->decl == NULL)
27149 goto type_validation;
27150
27151 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
27152 int skip;
27153 /*
27154 * Wildcards.
27155 */
27156 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
27157 if (ret != 0) {
27158 if (ret < 0) {
27159 VERROR_INT("xmlSchemaValidateElem",
27160 "calling xmlSchemaValidateElemWildcard()");
27161 goto internal_error;
27162 }
27163 goto exit;
27164 }
27165 if (skip) {
27166 vctxt->skipDepth = vctxt->depth;
27167 goto exit;
27168 }
27169 /*
27170 * The declaration might be set by the wildcard validation,
27171 * when the processContents is "lax" or "strict".
27172 */
27173 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
27174 /*
27175 * Clear the "decl" field to not confuse further processing.
27176 */
27177 vctxt->inode->decl = NULL;
27178 goto type_validation;
27179 }
27180 }
27181 /*
27182 * Validate against the declaration.
27183 */
27184 ret = xmlSchemaValidateElemDecl(vctxt);
27185 if (ret != 0) {
27186 if (ret < 0) {
27187 VERROR_INT("xmlSchemaValidateElem",
27188 "calling xmlSchemaValidateElemDecl()");
27189 goto internal_error;
27190 }
27191 goto exit;
27192 }
27193 /*
27194 * Validate against the type definition.
27195 */
27196 type_validation:
27197
27198 if (vctxt->inode->typeDef == NULL) {
27199 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27200 ret = XML_SCHEMAV_CVC_TYPE_1;
27201 VERROR(ret, NULL,
27202 "The type definition is absent");
27203 goto exit;
27204 }
27205 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
27206 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27207 ret = XML_SCHEMAV_CVC_TYPE_2;
27208 VERROR(ret, NULL,
27209 "The type definition is abstract");
27210 goto exit;
27211 }
27212 /*
27213 * Evaluate IDCs. Do it here, since new IDC matchers are registered
27214 * during validation against the declaration. This must be done
27215 * _before_ attribute validation.
27216 */
27217 if (vctxt->xpathStates != NULL) {
27218 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
27219 vctxt->inode->appliedXPath = 1;
27220 if (ret == -1) {
27221 VERROR_INT("xmlSchemaValidateElem",
27222 "calling xmlSchemaXPathEvaluate()");
27223 goto internal_error;
27224 }
27225 }
27226 /*
27227 * Validate attributes.
27228 */
27229 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
27230 if ((vctxt->nbAttrInfos != 0) ||
27231 (vctxt->inode->typeDef->attrUses != NULL)) {
27232
27233 ret = xmlSchemaVAttributesComplex(vctxt);
27234 }
27235 } else if (vctxt->nbAttrInfos != 0) {
27236
27237 ret = xmlSchemaVAttributesSimple(vctxt);
27238 }
27239 /*
27240 * Clear registered attributes.
27241 */
27242 if (vctxt->nbAttrInfos != 0)
27243 xmlSchemaClearAttrInfos(vctxt);
27244 if (ret == -1) {
27245 VERROR_INT("xmlSchemaValidateElem",
27246 "calling attributes validation");
27247 goto internal_error;
27248 }
27249 /*
27250 * Don't return an error if attributes are invalid on purpose.
27251 */
27252 ret = 0;
27253
27254 exit:
27255 if (ret != 0)
27256 vctxt->skipDepth = vctxt->depth;
27257 return (ret);
27258 internal_error:
27259 return (-1);
27260 }
27261
27262 #ifdef XML_SCHEMA_READER_ENABLED
27263 static int
xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)27264 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27265 {
27266 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27267 int depth, nodeType, ret = 0, consumed;
27268 xmlSchemaNodeInfoPtr ielem;
27269
27270 vctxt->depth = -1;
27271 ret = xmlTextReaderRead(vctxt->reader);
27272 /*
27273 * Move to the document element.
27274 */
27275 while (ret == 1) {
27276 nodeType = xmlTextReaderNodeType(vctxt->reader);
27277 if (nodeType == XML_ELEMENT_NODE)
27278 goto root_found;
27279 ret = xmlTextReaderRead(vctxt->reader);
27280 }
27281 goto exit;
27282
27283 root_found:
27284
27285 do {
27286 depth = xmlTextReaderDepth(vctxt->reader);
27287 nodeType = xmlTextReaderNodeType(vctxt->reader);
27288
27289 if (nodeType == XML_ELEMENT_NODE) {
27290
27291 vctxt->depth++;
27292 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27293 VERROR_INT("xmlSchemaVReaderWalk",
27294 "calling xmlSchemaValidatorPushElem()");
27295 goto internal_error;
27296 }
27297 ielem = vctxt->inode;
27298 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27299 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27300 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27301 /*
27302 * Is the element empty?
27303 */
27304 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27305 if (ret == -1) {
27306 VERROR_INT("xmlSchemaVReaderWalk",
27307 "calling xmlTextReaderIsEmptyElement()");
27308 goto internal_error;
27309 }
27310 if (ret) {
27311 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27312 }
27313 /*
27314 * Register attributes.
27315 */
27316 vctxt->nbAttrInfos = 0;
27317 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27318 if (ret == -1) {
27319 VERROR_INT("xmlSchemaVReaderWalk",
27320 "calling xmlTextReaderMoveToFirstAttribute()");
27321 goto internal_error;
27322 }
27323 if (ret == 1) {
27324 do {
27325 /*
27326 * VAL TODO: How do we know that the reader works on a
27327 * node tree, to be able to pass a node here?
27328 */
27329 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27330 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27331 xmlTextReaderNamespaceUri(vctxt->reader), 1,
27332 xmlTextReaderValue(vctxt->reader), 1) == -1) {
27333
27334 VERROR_INT("xmlSchemaVReaderWalk",
27335 "calling xmlSchemaValidatorPushAttribute()");
27336 goto internal_error;
27337 }
27338 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27339 if (ret == -1) {
27340 VERROR_INT("xmlSchemaVReaderWalk",
27341 "calling xmlTextReaderMoveToFirstAttribute()");
27342 goto internal_error;
27343 }
27344 } while (ret == 1);
27345 /*
27346 * Back to element position.
27347 */
27348 ret = xmlTextReaderMoveToElement(vctxt->reader);
27349 if (ret == -1) {
27350 VERROR_INT("xmlSchemaVReaderWalk",
27351 "calling xmlTextReaderMoveToElement()");
27352 goto internal_error;
27353 }
27354 }
27355 /*
27356 * Validate the element.
27357 */
27358 ret= xmlSchemaValidateElem(vctxt);
27359 if (ret != 0) {
27360 if (ret == -1) {
27361 VERROR_INT("xmlSchemaVReaderWalk",
27362 "calling xmlSchemaValidateElem()");
27363 goto internal_error;
27364 }
27365 goto exit;
27366 }
27367 if (vctxt->depth == vctxt->skipDepth) {
27368 int curDepth;
27369 /*
27370 * Skip all content.
27371 */
27372 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27373 ret = xmlTextReaderRead(vctxt->reader);
27374 curDepth = xmlTextReaderDepth(vctxt->reader);
27375 while ((ret == 1) && (curDepth != depth)) {
27376 ret = xmlTextReaderRead(vctxt->reader);
27377 curDepth = xmlTextReaderDepth(vctxt->reader);
27378 }
27379 if (ret < 0) {
27380 /*
27381 * VAL TODO: A reader error occurred; what to do here?
27382 */
27383 ret = 1;
27384 goto exit;
27385 }
27386 }
27387 goto leave_elem;
27388 }
27389 /*
27390 * READER VAL TODO: Is an END_ELEM really never called
27391 * if the elem is empty?
27392 */
27393 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27394 goto leave_elem;
27395 } else if (nodeType == END_ELEM) {
27396 /*
27397 * Process END of element.
27398 */
27399 leave_elem:
27400 ret = xmlSchemaValidatorPopElem(vctxt);
27401 if (ret != 0) {
27402 if (ret < 0) {
27403 VERROR_INT("xmlSchemaVReaderWalk",
27404 "calling xmlSchemaValidatorPopElem()");
27405 goto internal_error;
27406 }
27407 goto exit;
27408 }
27409 if (vctxt->depth >= 0)
27410 ielem = vctxt->inode;
27411 else
27412 ielem = NULL;
27413 } else if ((nodeType == XML_TEXT_NODE) ||
27414 (nodeType == XML_CDATA_SECTION_NODE) ||
27415 (nodeType == WHTSP) ||
27416 (nodeType == SIGN_WHTSP)) {
27417 /*
27418 * Process character content.
27419 */
27420 xmlChar *value;
27421
27422 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27423 nodeType = XML_TEXT_NODE;
27424
27425 value = xmlTextReaderValue(vctxt->reader);
27426 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27427 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27428 if (! consumed)
27429 xmlFree(value);
27430 if (ret == -1) {
27431 VERROR_INT("xmlSchemaVReaderWalk",
27432 "calling xmlSchemaVPushText()");
27433 goto internal_error;
27434 }
27435 } else if ((nodeType == XML_ENTITY_NODE) ||
27436 (nodeType == XML_ENTITY_REF_NODE)) {
27437 /*
27438 * VAL TODO: What to do with entities?
27439 */
27440 TODO
27441 }
27442 /*
27443 * Read next node.
27444 */
27445 ret = xmlTextReaderRead(vctxt->reader);
27446 } while (ret == 1);
27447
27448 exit:
27449 return (ret);
27450 internal_error:
27451 return (-1);
27452 }
27453 #endif
27454
27455 /************************************************************************
27456 * *
27457 * SAX validation handlers *
27458 * *
27459 ************************************************************************/
27460
27461 /*
27462 * Process text content.
27463 */
27464 static void
xmlSchemaSAXHandleText(void * ctx,const xmlChar * ch,int len)27465 xmlSchemaSAXHandleText(void *ctx,
27466 const xmlChar * ch,
27467 int len)
27468 {
27469 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27470
27471 if (vctxt->depth < 0)
27472 return;
27473 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27474 return;
27475 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27476 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27477 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27478 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27479 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27480 "calling xmlSchemaVPushText()");
27481 vctxt->err = -1;
27482 xmlStopParser(vctxt->parserCtxt);
27483 }
27484 }
27485
27486 /*
27487 * Process CDATA content.
27488 */
27489 static void
xmlSchemaSAXHandleCDataSection(void * ctx,const xmlChar * ch,int len)27490 xmlSchemaSAXHandleCDataSection(void *ctx,
27491 const xmlChar * ch,
27492 int len)
27493 {
27494 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27495
27496 if (vctxt->depth < 0)
27497 return;
27498 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27499 return;
27500 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27501 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27502 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27503 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27504 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27505 "calling xmlSchemaVPushText()");
27506 vctxt->err = -1;
27507 xmlStopParser(vctxt->parserCtxt);
27508 }
27509 }
27510
27511 static void
xmlSchemaSAXHandleReference(void * ctx ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED)27512 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27513 const xmlChar * name ATTRIBUTE_UNUSED)
27514 {
27515 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27516
27517 if (vctxt->depth < 0)
27518 return;
27519 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27520 return;
27521 /* SAX VAL TODO: What to do here? */
27522 TODO
27523 }
27524
27525 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)27526 xmlSchemaSAXHandleStartElementNs(void *ctx,
27527 const xmlChar * localname,
27528 const xmlChar * prefix ATTRIBUTE_UNUSED,
27529 const xmlChar * URI,
27530 int nb_namespaces,
27531 const xmlChar ** namespaces,
27532 int nb_attributes,
27533 int nb_defaulted ATTRIBUTE_UNUSED,
27534 const xmlChar ** attributes)
27535 {
27536 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27537 int ret;
27538 xmlSchemaNodeInfoPtr ielem;
27539 int i, j;
27540
27541 /*
27542 * SAX VAL TODO: What to do with nb_defaulted?
27543 */
27544 /*
27545 * Skip elements if inside a "skip" wildcard or invalid.
27546 */
27547 vctxt->depth++;
27548 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27549 return;
27550 /*
27551 * Push the element.
27552 */
27553 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27554 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27555 "calling xmlSchemaValidatorPushElem()");
27556 goto internal_error;
27557 }
27558 ielem = vctxt->inode;
27559 /*
27560 * TODO: Is this OK?
27561 */
27562 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27563 ielem->localName = localname;
27564 ielem->nsName = URI;
27565 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27566 /*
27567 * Register namespaces on the elem info.
27568 */
27569 if (nb_namespaces != 0) {
27570 /*
27571 * Although the parser builds its own namespace list,
27572 * we have no access to it, so we'll use an own one.
27573 */
27574 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27575 /*
27576 * Store prefix and namespace name.
27577 */
27578 if (ielem->nsBindings == NULL) {
27579 ielem->nsBindings =
27580 (const xmlChar **) xmlMalloc(10 *
27581 sizeof(const xmlChar *));
27582 if (ielem->nsBindings == NULL) {
27583 xmlSchemaVErrMemory(vctxt,
27584 "allocating namespace bindings for SAX validation",
27585 NULL);
27586 goto internal_error;
27587 }
27588 ielem->nbNsBindings = 0;
27589 ielem->sizeNsBindings = 5;
27590 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27591 ielem->sizeNsBindings *= 2;
27592 ielem->nsBindings =
27593 (const xmlChar **) xmlRealloc(
27594 (void *) ielem->nsBindings,
27595 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27596 if (ielem->nsBindings == NULL) {
27597 xmlSchemaVErrMemory(vctxt,
27598 "re-allocating namespace bindings for SAX validation",
27599 NULL);
27600 goto internal_error;
27601 }
27602 }
27603
27604 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27605 if (namespaces[j+1][0] == 0) {
27606 /*
27607 * Handle xmlns="".
27608 */
27609 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27610 } else
27611 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27612 namespaces[j+1];
27613 ielem->nbNsBindings++;
27614 }
27615 }
27616 /*
27617 * Register attributes.
27618 * SAX VAL TODO: We are not adding namespace declaration
27619 * attributes yet.
27620 */
27621 if (nb_attributes != 0) {
27622 int valueLen, k, l;
27623 xmlChar *value;
27624
27625 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27626 /*
27627 * Duplicate the value, changing any & to a literal ampersand.
27628 *
27629 * libxml2 differs from normal SAX here in that it escapes all ampersands
27630 * as & instead of delivering the raw converted string. Changing the
27631 * behavior at this point would break applications that use this API, so
27632 * we are forced to work around it.
27633 */
27634 valueLen = attributes[j+4] - attributes[j+3];
27635 value = xmlMallocAtomic(valueLen + 1);
27636 if (value == NULL) {
27637 xmlSchemaVErrMemory(vctxt,
27638 "allocating string for decoded attribute",
27639 NULL);
27640 goto internal_error;
27641 }
27642 for (k = 0, l = 0; k < valueLen; l++) {
27643 if (k < valueLen - 4 &&
27644 attributes[j+3][k+0] == '&' &&
27645 attributes[j+3][k+1] == '#' &&
27646 attributes[j+3][k+2] == '3' &&
27647 attributes[j+3][k+3] == '8' &&
27648 attributes[j+3][k+4] == ';') {
27649 value[l] = '&';
27650 k += 5;
27651 } else {
27652 value[l] = attributes[j+3][k];
27653 k++;
27654 }
27655 }
27656 value[l] = '\0';
27657 /*
27658 * TODO: Set the node line.
27659 */
27660 ret = xmlSchemaValidatorPushAttribute(vctxt,
27661 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27662 value, 1);
27663 if (ret == -1) {
27664 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27665 "calling xmlSchemaValidatorPushAttribute()");
27666 goto internal_error;
27667 }
27668 }
27669 }
27670 /*
27671 * Validate the element.
27672 */
27673 ret = xmlSchemaValidateElem(vctxt);
27674 if (ret != 0) {
27675 if (ret == -1) {
27676 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27677 "calling xmlSchemaValidateElem()");
27678 goto internal_error;
27679 }
27680 goto exit;
27681 }
27682
27683 exit:
27684 return;
27685 internal_error:
27686 vctxt->err = -1;
27687 xmlStopParser(vctxt->parserCtxt);
27688 return;
27689 }
27690
27691 static void
xmlSchemaSAXHandleEndElementNs(void * ctx,const xmlChar * localname ATTRIBUTE_UNUSED,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI ATTRIBUTE_UNUSED)27692 xmlSchemaSAXHandleEndElementNs(void *ctx,
27693 const xmlChar * localname ATTRIBUTE_UNUSED,
27694 const xmlChar * prefix ATTRIBUTE_UNUSED,
27695 const xmlChar * URI ATTRIBUTE_UNUSED)
27696 {
27697 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27698 int res;
27699
27700 /*
27701 * Skip elements if inside a "skip" wildcard or if invalid.
27702 */
27703 if (vctxt->skipDepth != -1) {
27704 if (vctxt->depth > vctxt->skipDepth) {
27705 vctxt->depth--;
27706 return;
27707 } else
27708 vctxt->skipDepth = -1;
27709 }
27710 /*
27711 * SAX VAL TODO: Just a temporary check.
27712 */
27713 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27714 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27715 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27716 "elem pop mismatch");
27717 }
27718 res = xmlSchemaValidatorPopElem(vctxt);
27719 if (res != 0) {
27720 if (res < 0) {
27721 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27722 "calling xmlSchemaValidatorPopElem()");
27723 goto internal_error;
27724 }
27725 goto exit;
27726 }
27727 exit:
27728 return;
27729 internal_error:
27730 vctxt->err = -1;
27731 xmlStopParser(vctxt->parserCtxt);
27732 return;
27733 }
27734
27735 /************************************************************************
27736 * *
27737 * Validation interfaces *
27738 * *
27739 ************************************************************************/
27740
27741 /**
27742 * xmlSchemaNewValidCtxt:
27743 * @schema: a precompiled XML Schemas
27744 *
27745 * Create an XML Schemas validation context based on the given schema.
27746 *
27747 * Returns the validation context or NULL in case of error
27748 */
27749 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)27750 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27751 {
27752 xmlSchemaValidCtxtPtr ret;
27753
27754 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27755 if (ret == NULL) {
27756 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27757 return (NULL);
27758 }
27759 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27760 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27761 ret->dict = xmlDictCreate();
27762 ret->nodeQNames = xmlSchemaItemListCreate();
27763 ret->schema = schema;
27764 return (ret);
27765 }
27766
27767 /**
27768 * xmlSchemaValidateSetFilename:
27769 * @vctxt: the schema validation context
27770 * @filename: the file name
27771 *
27772 * Workaround to provide file error reporting information when this is
27773 * not provided by current APIs
27774 */
27775 void
xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt,const char * filename)27776 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27777 if (vctxt == NULL)
27778 return;
27779 if (vctxt->filename != NULL)
27780 xmlFree(vctxt->filename);
27781 if (filename != NULL)
27782 vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27783 else
27784 vctxt->filename = NULL;
27785 }
27786
27787 /**
27788 * xmlSchemaClearValidCtxt:
27789 * @vctxt: the schema validation context
27790 *
27791 * Free the resources associated to the schema validation context;
27792 * leaves some fields alive intended for reuse of the context.
27793 */
27794 static void
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)27795 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27796 {
27797 if (vctxt == NULL)
27798 return;
27799
27800 /*
27801 * TODO: Should we clear the flags?
27802 * Might be problematic if one reuses the context
27803 * and assumes that the options remain the same.
27804 */
27805 vctxt->flags = 0;
27806 vctxt->validationRoot = NULL;
27807 vctxt->doc = NULL;
27808 #ifdef LIBXML_READER_ENABLED
27809 vctxt->reader = NULL;
27810 #endif
27811 vctxt->hasKeyrefs = 0;
27812
27813 if (vctxt->value != NULL) {
27814 xmlSchemaFreeValue(vctxt->value);
27815 vctxt->value = NULL;
27816 }
27817 /*
27818 * Augmented IDC information.
27819 */
27820 if (vctxt->aidcs != NULL) {
27821 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27822 do {
27823 next = cur->next;
27824 xmlFree(cur);
27825 cur = next;
27826 } while (cur != NULL);
27827 vctxt->aidcs = NULL;
27828 }
27829 if (vctxt->idcMatcherCache != NULL) {
27830 xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27831
27832 while (matcher) {
27833 tmp = matcher;
27834 matcher = matcher->nextCached;
27835 xmlSchemaIDCFreeMatcherList(tmp);
27836 }
27837 vctxt->idcMatcherCache = NULL;
27838 }
27839
27840
27841 if (vctxt->idcNodes != NULL) {
27842 int i;
27843 xmlSchemaPSVIIDCNodePtr item;
27844
27845 for (i = 0; i < vctxt->nbIdcNodes; i++) {
27846 item = vctxt->idcNodes[i];
27847 xmlFree(item->keys);
27848 xmlFree(item);
27849 }
27850 xmlFree(vctxt->idcNodes);
27851 vctxt->idcNodes = NULL;
27852 vctxt->nbIdcNodes = 0;
27853 vctxt->sizeIdcNodes = 0;
27854 }
27855
27856 if (vctxt->idcKeys != NULL) {
27857 int i;
27858 for (i = 0; i < vctxt->nbIdcKeys; i++)
27859 xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27860 xmlFree(vctxt->idcKeys);
27861 vctxt->idcKeys = NULL;
27862 vctxt->nbIdcKeys = 0;
27863 vctxt->sizeIdcKeys = 0;
27864 }
27865
27866 /*
27867 * Note that we won't delete the XPath state pool here.
27868 */
27869 if (vctxt->xpathStates != NULL) {
27870 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27871 vctxt->xpathStates = NULL;
27872 }
27873 /*
27874 * Attribute info.
27875 */
27876 if (vctxt->nbAttrInfos != 0) {
27877 xmlSchemaClearAttrInfos(vctxt);
27878 }
27879 /*
27880 * Element info.
27881 */
27882 if (vctxt->elemInfos != NULL) {
27883 int i;
27884 xmlSchemaNodeInfoPtr ei;
27885
27886 for (i = 0; i < vctxt->sizeElemInfos; i++) {
27887 ei = vctxt->elemInfos[i];
27888 if (ei == NULL)
27889 break;
27890 xmlSchemaClearElemInfo(vctxt, ei);
27891 }
27892 }
27893 xmlSchemaItemListClear(vctxt->nodeQNames);
27894 /* Recreate the dict. */
27895 xmlDictFree(vctxt->dict);
27896 /*
27897 * TODO: Is is save to recreate it? Do we have a scenario
27898 * where the user provides the dict?
27899 */
27900 vctxt->dict = xmlDictCreate();
27901
27902 if (vctxt->filename != NULL) {
27903 xmlFree(vctxt->filename);
27904 vctxt->filename = NULL;
27905 }
27906 }
27907
27908 /**
27909 * xmlSchemaFreeValidCtxt:
27910 * @ctxt: the schema validation context
27911 *
27912 * Free the resources associated to the schema validation context
27913 */
27914 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)27915 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27916 {
27917 if (ctxt == NULL)
27918 return;
27919 if (ctxt->value != NULL)
27920 xmlSchemaFreeValue(ctxt->value);
27921 if (ctxt->pctxt != NULL)
27922 xmlSchemaFreeParserCtxt(ctxt->pctxt);
27923 if (ctxt->idcNodes != NULL) {
27924 int i;
27925 xmlSchemaPSVIIDCNodePtr item;
27926
27927 for (i = 0; i < ctxt->nbIdcNodes; i++) {
27928 item = ctxt->idcNodes[i];
27929 xmlFree(item->keys);
27930 xmlFree(item);
27931 }
27932 xmlFree(ctxt->idcNodes);
27933 }
27934 if (ctxt->idcKeys != NULL) {
27935 int i;
27936 for (i = 0; i < ctxt->nbIdcKeys; i++)
27937 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27938 xmlFree(ctxt->idcKeys);
27939 }
27940
27941 if (ctxt->xpathStates != NULL) {
27942 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27943 ctxt->xpathStates = NULL;
27944 }
27945 if (ctxt->xpathStatePool != NULL) {
27946 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27947 ctxt->xpathStatePool = NULL;
27948 }
27949
27950 /*
27951 * Augmented IDC information.
27952 */
27953 if (ctxt->aidcs != NULL) {
27954 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27955 do {
27956 next = cur->next;
27957 xmlFree(cur);
27958 cur = next;
27959 } while (cur != NULL);
27960 }
27961 if (ctxt->attrInfos != NULL) {
27962 int i;
27963 xmlSchemaAttrInfoPtr attr;
27964
27965 /* Just a paranoid call to the cleanup. */
27966 if (ctxt->nbAttrInfos != 0)
27967 xmlSchemaClearAttrInfos(ctxt);
27968 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27969 attr = ctxt->attrInfos[i];
27970 xmlFree(attr);
27971 }
27972 xmlFree(ctxt->attrInfos);
27973 }
27974 if (ctxt->elemInfos != NULL) {
27975 int i;
27976 xmlSchemaNodeInfoPtr ei;
27977
27978 for (i = 0; i < ctxt->sizeElemInfos; i++) {
27979 ei = ctxt->elemInfos[i];
27980 if (ei == NULL)
27981 break;
27982 xmlSchemaClearElemInfo(ctxt, ei);
27983 xmlFree(ei);
27984 }
27985 xmlFree(ctxt->elemInfos);
27986 }
27987 if (ctxt->nodeQNames != NULL)
27988 xmlSchemaItemListFree(ctxt->nodeQNames);
27989 if (ctxt->dict != NULL)
27990 xmlDictFree(ctxt->dict);
27991 if (ctxt->filename != NULL)
27992 xmlFree(ctxt->filename);
27993 xmlFree(ctxt);
27994 }
27995
27996 /**
27997 * xmlSchemaIsValid:
27998 * @ctxt: the schema validation context
27999 *
28000 * Check if any error was detected during validation.
28001 *
28002 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
28003 * of internal error.
28004 */
28005 int
xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)28006 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
28007 {
28008 if (ctxt == NULL)
28009 return(-1);
28010 return(ctxt->err == 0);
28011 }
28012
28013 /**
28014 * xmlSchemaSetValidErrors:
28015 * @ctxt: a schema validation context
28016 * @err: the error function
28017 * @warn: the warning function
28018 * @ctx: the functions context
28019 *
28020 * Set the error and warning callback information
28021 */
28022 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)28023 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
28024 xmlSchemaValidityErrorFunc err,
28025 xmlSchemaValidityWarningFunc warn, void *ctx)
28026 {
28027 if (ctxt == NULL)
28028 return;
28029 ctxt->error = err;
28030 ctxt->warning = warn;
28031 ctxt->errCtxt = ctx;
28032 if (ctxt->pctxt != NULL)
28033 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
28034 }
28035
28036 /**
28037 * xmlSchemaSetValidStructuredErrors:
28038 * @ctxt: a schema validation context
28039 * @serror: the structured error function
28040 * @ctx: the functions context
28041 *
28042 * Set the structured error callback
28043 */
28044 void
xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)28045 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
28046 xmlStructuredErrorFunc serror, void *ctx)
28047 {
28048 if (ctxt == NULL)
28049 return;
28050 ctxt->serror = serror;
28051 ctxt->error = NULL;
28052 ctxt->warning = NULL;
28053 ctxt->errCtxt = ctx;
28054 if (ctxt->pctxt != NULL)
28055 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
28056 }
28057
28058 /**
28059 * xmlSchemaGetValidErrors:
28060 * @ctxt: a XML-Schema validation context
28061 * @err: the error function result
28062 * @warn: the warning function result
28063 * @ctx: the functions context result
28064 *
28065 * Get the error and warning callback information
28066 *
28067 * Returns -1 in case of error and 0 otherwise
28068 */
28069 int
xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)28070 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
28071 xmlSchemaValidityErrorFunc * err,
28072 xmlSchemaValidityWarningFunc * warn, void **ctx)
28073 {
28074 if (ctxt == NULL)
28075 return (-1);
28076 if (err != NULL)
28077 *err = ctxt->error;
28078 if (warn != NULL)
28079 *warn = ctxt->warning;
28080 if (ctx != NULL)
28081 *ctx = ctxt->errCtxt;
28082 return (0);
28083 }
28084
28085
28086 /**
28087 * xmlSchemaSetValidOptions:
28088 * @ctxt: a schema validation context
28089 * @options: a combination of xmlSchemaValidOption
28090 *
28091 * Sets the options to be used during the validation.
28092 *
28093 * Returns 0 in case of success, -1 in case of an
28094 * API error.
28095 */
28096 int
xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,int options)28097 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
28098 int options)
28099
28100 {
28101 int i;
28102
28103 if (ctxt == NULL)
28104 return (-1);
28105 /*
28106 * WARNING: Change the start value if adding to the
28107 * xmlSchemaValidOption.
28108 * TODO: Is there an other, more easy to maintain,
28109 * way?
28110 */
28111 for (i = 1; i < (int) sizeof(int) * 8; i++) {
28112 if (options & 1<<i)
28113 return (-1);
28114 }
28115 ctxt->options = options;
28116 return (0);
28117 }
28118
28119 /**
28120 * xmlSchemaValidCtxtGetOptions:
28121 * @ctxt: a schema validation context
28122 *
28123 * Get the validation context options.
28124 *
28125 * Returns the option combination or -1 on error.
28126 */
28127 int
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)28128 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
28129
28130 {
28131 if (ctxt == NULL)
28132 return (-1);
28133 else
28134 return (ctxt->options);
28135 }
28136
28137 static int
xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)28138 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
28139 {
28140 xmlAttrPtr attr;
28141 int ret = 0;
28142 xmlSchemaNodeInfoPtr ielem = NULL;
28143 xmlNodePtr node, valRoot;
28144 const xmlChar *nsName;
28145
28146 /* DOC VAL TODO: Move this to the start function. */
28147 if (vctxt->validationRoot != NULL)
28148 valRoot = vctxt->validationRoot;
28149 else
28150 valRoot = xmlDocGetRootElement(vctxt->doc);
28151 if (valRoot == NULL) {
28152 /* VAL TODO: Error code? */
28153 VERROR(1, NULL, "The document has no document element");
28154 return (1);
28155 }
28156 vctxt->depth = -1;
28157 vctxt->validationRoot = valRoot;
28158 node = valRoot;
28159 while (node != NULL) {
28160 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
28161 goto next_sibling;
28162 if (node->type == XML_ELEMENT_NODE) {
28163
28164 /*
28165 * Init the node-info.
28166 */
28167 vctxt->depth++;
28168 if (xmlSchemaValidatorPushElem(vctxt) == -1)
28169 goto internal_error;
28170 ielem = vctxt->inode;
28171 ielem->node = node;
28172 ielem->nodeLine = node->line;
28173 ielem->localName = node->name;
28174 if (node->ns != NULL)
28175 ielem->nsName = node->ns->href;
28176 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
28177 /*
28178 * Register attributes.
28179 * DOC VAL TODO: We do not register namespace declaration
28180 * attributes yet.
28181 */
28182 vctxt->nbAttrInfos = 0;
28183 if (node->properties != NULL) {
28184 attr = node->properties;
28185 do {
28186 if (attr->ns != NULL)
28187 nsName = attr->ns->href;
28188 else
28189 nsName = NULL;
28190 ret = xmlSchemaValidatorPushAttribute(vctxt,
28191 (xmlNodePtr) attr,
28192 /*
28193 * Note that we give it the line number of the
28194 * parent element.
28195 */
28196 ielem->nodeLine,
28197 attr->name, nsName, 0,
28198 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
28199 if (ret == -1) {
28200 VERROR_INT("xmlSchemaDocWalk",
28201 "calling xmlSchemaValidatorPushAttribute()");
28202 goto internal_error;
28203 }
28204 attr = attr->next;
28205 } while (attr);
28206 }
28207 /*
28208 * Validate the element.
28209 */
28210 ret = xmlSchemaValidateElem(vctxt);
28211 if (ret != 0) {
28212 if (ret == -1) {
28213 VERROR_INT("xmlSchemaDocWalk",
28214 "calling xmlSchemaValidateElem()");
28215 goto internal_error;
28216 }
28217 /*
28218 * Don't stop validation; just skip the content
28219 * of this element.
28220 */
28221 goto leave_node;
28222 }
28223 if ((vctxt->skipDepth != -1) &&
28224 (vctxt->depth >= vctxt->skipDepth))
28225 goto leave_node;
28226 } else if ((node->type == XML_TEXT_NODE) ||
28227 (node->type == XML_CDATA_SECTION_NODE)) {
28228 /*
28229 * Process character content.
28230 */
28231 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
28232 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
28233 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
28234 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
28235 if (ret < 0) {
28236 VERROR_INT("xmlSchemaVDocWalk",
28237 "calling xmlSchemaVPushText()");
28238 goto internal_error;
28239 }
28240 /*
28241 * DOC VAL TODO: Should we skip further validation of the
28242 * element content here?
28243 */
28244 } else if ((node->type == XML_ENTITY_NODE) ||
28245 (node->type == XML_ENTITY_REF_NODE)) {
28246 /*
28247 * DOC VAL TODO: What to do with entities?
28248 */
28249 VERROR_INT("xmlSchemaVDocWalk",
28250 "there is at least one entity reference in the node-tree "
28251 "currently being validated. Processing of entities with "
28252 "this XML Schema processor is not supported (yet). Please "
28253 "substitute entities before validation.");
28254 goto internal_error;
28255 } else {
28256 goto leave_node;
28257 /*
28258 * DOC VAL TODO: XInclude nodes, etc.
28259 */
28260 }
28261 /*
28262 * Walk the doc.
28263 */
28264 if (node->children != NULL) {
28265 node = node->children;
28266 continue;
28267 }
28268 leave_node:
28269 if (node->type == XML_ELEMENT_NODE) {
28270 /*
28271 * Leaving the scope of an element.
28272 */
28273 if (node != vctxt->inode->node) {
28274 VERROR_INT("xmlSchemaVDocWalk",
28275 "element position mismatch");
28276 goto internal_error;
28277 }
28278 ret = xmlSchemaValidatorPopElem(vctxt);
28279 if (ret != 0) {
28280 if (ret < 0) {
28281 VERROR_INT("xmlSchemaVDocWalk",
28282 "calling xmlSchemaValidatorPopElem()");
28283 goto internal_error;
28284 }
28285 }
28286 if (node == valRoot)
28287 goto exit;
28288 }
28289 next_sibling:
28290 if (node->next != NULL)
28291 node = node->next;
28292 else {
28293 node = node->parent;
28294 goto leave_node;
28295 }
28296 }
28297
28298 exit:
28299 return (ret);
28300 internal_error:
28301 return (-1);
28302 }
28303
28304 static int
xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt)28305 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28306 /*
28307 * Some initialization.
28308 */
28309 vctxt->err = 0;
28310 vctxt->nberrors = 0;
28311 vctxt->depth = -1;
28312 vctxt->skipDepth = -1;
28313 vctxt->hasKeyrefs = 0;
28314 #ifdef ENABLE_IDC_NODE_TABLES_TEST
28315 vctxt->createIDCNodeTables = 1;
28316 #else
28317 vctxt->createIDCNodeTables = 0;
28318 #endif
28319 /*
28320 * Create a schema + parser if necessary.
28321 */
28322 if (vctxt->schema == NULL) {
28323 xmlSchemaParserCtxtPtr pctxt;
28324
28325 vctxt->xsiAssemble = 1;
28326 /*
28327 * If not schema was given then we will create a schema
28328 * dynamically using XSI schema locations.
28329 *
28330 * Create the schema parser context.
28331 */
28332 if ((vctxt->pctxt == NULL) &&
28333 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28334 return (-1);
28335 pctxt = vctxt->pctxt;
28336 pctxt->xsiAssemble = 1;
28337 /*
28338 * Create the schema.
28339 */
28340 vctxt->schema = xmlSchemaNewSchema(pctxt);
28341 if (vctxt->schema == NULL)
28342 return (-1);
28343 /*
28344 * Create the schema construction context.
28345 */
28346 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28347 if (pctxt->constructor == NULL)
28348 return(-1);
28349 pctxt->constructor->mainSchema = vctxt->schema;
28350 /*
28351 * Take ownership of the constructor to be able to free it.
28352 */
28353 pctxt->ownsConstructor = 1;
28354 }
28355 /*
28356 * Augment the IDC definitions for the main schema and all imported ones
28357 * NOTE: main schema if the first in the imported list
28358 */
28359 xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28360 vctxt);
28361
28362 return(0);
28363 }
28364
28365 static void
xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt)28366 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28367 if (vctxt->xsiAssemble) {
28368 if (vctxt->schema != NULL) {
28369 xmlSchemaFree(vctxt->schema);
28370 vctxt->schema = NULL;
28371 }
28372 }
28373 xmlSchemaClearValidCtxt(vctxt);
28374 }
28375
28376 static int
xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)28377 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28378 {
28379 int ret = 0;
28380
28381 if (xmlSchemaPreRun(vctxt) < 0)
28382 return(-1);
28383
28384 if (vctxt->doc != NULL) {
28385 /*
28386 * Tree validation.
28387 */
28388 ret = xmlSchemaVDocWalk(vctxt);
28389 #ifdef LIBXML_READER_ENABLED
28390 } else if (vctxt->reader != NULL) {
28391 /*
28392 * XML Reader validation.
28393 */
28394 #ifdef XML_SCHEMA_READER_ENABLED
28395 ret = xmlSchemaVReaderWalk(vctxt);
28396 #endif
28397 #endif
28398 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28399 /*
28400 * SAX validation.
28401 */
28402 ret = xmlParseDocument(vctxt->parserCtxt);
28403 } else {
28404 VERROR_INT("xmlSchemaVStart",
28405 "no instance to validate");
28406 ret = -1;
28407 }
28408
28409 xmlSchemaPostRun(vctxt);
28410 if (ret == 0)
28411 ret = vctxt->err;
28412 return (ret);
28413 }
28414
28415 /**
28416 * xmlSchemaValidateOneElement:
28417 * @ctxt: a schema validation context
28418 * @elem: an element node
28419 *
28420 * Validate a branch of a tree, starting with the given @elem.
28421 *
28422 * Returns 0 if the element and its subtree is valid, a positive error
28423 * code number otherwise and -1 in case of an internal or API error.
28424 */
28425 int
xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)28426 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28427 {
28428 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28429 return (-1);
28430
28431 if (ctxt->schema == NULL)
28432 return (-1);
28433
28434 ctxt->doc = elem->doc;
28435 ctxt->node = elem;
28436 ctxt->validationRoot = elem;
28437 return(xmlSchemaVStart(ctxt));
28438 }
28439
28440 /**
28441 * xmlSchemaValidateDoc:
28442 * @ctxt: a schema validation context
28443 * @doc: a parsed document tree
28444 *
28445 * Validate a document tree in memory.
28446 *
28447 * Returns 0 if the document is schemas valid, a positive error code
28448 * number otherwise and -1 in case of internal or API error.
28449 */
28450 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)28451 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28452 {
28453 if ((ctxt == NULL) || (doc == NULL))
28454 return (-1);
28455
28456 ctxt->doc = doc;
28457 ctxt->node = xmlDocGetRootElement(doc);
28458 if (ctxt->node == NULL) {
28459 xmlSchemaCustomErr(ACTXT_CAST ctxt,
28460 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28461 (xmlNodePtr) doc, NULL,
28462 "The document has no document element", NULL, NULL);
28463 return (ctxt->err);
28464 }
28465 ctxt->validationRoot = ctxt->node;
28466 return (xmlSchemaVStart(ctxt));
28467 }
28468
28469
28470 /************************************************************************
28471 * *
28472 * Function and data for SAX streaming API *
28473 * *
28474 ************************************************************************/
28475 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28476 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28477
28478 struct _xmlSchemaSplitSAXData {
28479 xmlSAXHandlerPtr user_sax;
28480 void *user_data;
28481 xmlSchemaValidCtxtPtr ctxt;
28482 xmlSAXHandlerPtr schemas_sax;
28483 };
28484
28485 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28486
28487 struct _xmlSchemaSAXPlug {
28488 unsigned int magic;
28489
28490 /* the original callbacks information */
28491 xmlSAXHandlerPtr *user_sax_ptr;
28492 xmlSAXHandlerPtr user_sax;
28493 void **user_data_ptr;
28494 void *user_data;
28495
28496 /* the block plugged back and validation information */
28497 xmlSAXHandler schemas_sax;
28498 xmlSchemaValidCtxtPtr ctxt;
28499 };
28500
28501 /* All those functions just bounces to the user provided SAX handlers */
28502 static void
internalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28503 internalSubsetSplit(void *ctx, const xmlChar *name,
28504 const xmlChar *ExternalID, const xmlChar *SystemID)
28505 {
28506 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28507 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28508 (ctxt->user_sax->internalSubset != NULL))
28509 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28510 SystemID);
28511 }
28512
28513 static int
isStandaloneSplit(void * ctx)28514 isStandaloneSplit(void *ctx)
28515 {
28516 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28517 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28518 (ctxt->user_sax->isStandalone != NULL))
28519 return(ctxt->user_sax->isStandalone(ctxt->user_data));
28520 return(0);
28521 }
28522
28523 static int
hasInternalSubsetSplit(void * ctx)28524 hasInternalSubsetSplit(void *ctx)
28525 {
28526 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28527 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28528 (ctxt->user_sax->hasInternalSubset != NULL))
28529 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28530 return(0);
28531 }
28532
28533 static int
hasExternalSubsetSplit(void * ctx)28534 hasExternalSubsetSplit(void *ctx)
28535 {
28536 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28537 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28538 (ctxt->user_sax->hasExternalSubset != NULL))
28539 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28540 return(0);
28541 }
28542
28543 static void
externalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28544 externalSubsetSplit(void *ctx, const xmlChar *name,
28545 const xmlChar *ExternalID, const xmlChar *SystemID)
28546 {
28547 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28548 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28549 (ctxt->user_sax->externalSubset != NULL))
28550 ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28551 SystemID);
28552 }
28553
28554 static xmlParserInputPtr
resolveEntitySplit(void * ctx,const xmlChar * publicId,const xmlChar * systemId)28555 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28556 {
28557 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28558 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28559 (ctxt->user_sax->resolveEntity != NULL))
28560 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28561 systemId));
28562 return(NULL);
28563 }
28564
28565 static xmlEntityPtr
getEntitySplit(void * ctx,const xmlChar * name)28566 getEntitySplit(void *ctx, const xmlChar *name)
28567 {
28568 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28569 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28570 (ctxt->user_sax->getEntity != NULL))
28571 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28572 return(NULL);
28573 }
28574
28575 static xmlEntityPtr
getParameterEntitySplit(void * ctx,const xmlChar * name)28576 getParameterEntitySplit(void *ctx, const xmlChar *name)
28577 {
28578 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28579 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28580 (ctxt->user_sax->getParameterEntity != NULL))
28581 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28582 return(NULL);
28583 }
28584
28585
28586 static void
entityDeclSplit(void * ctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)28587 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28588 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28589 {
28590 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28591 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28592 (ctxt->user_sax->entityDecl != NULL))
28593 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28594 systemId, content);
28595 }
28596
28597 static void
attributeDeclSplit(void * ctx,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)28598 attributeDeclSplit(void *ctx, const xmlChar * elem,
28599 const xmlChar * name, int type, int def,
28600 const xmlChar * defaultValue, xmlEnumerationPtr tree)
28601 {
28602 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28603 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28604 (ctxt->user_sax->attributeDecl != NULL)) {
28605 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28606 def, defaultValue, tree);
28607 } else {
28608 xmlFreeEnumeration(tree);
28609 }
28610 }
28611
28612 static void
elementDeclSplit(void * ctx,const xmlChar * name,int type,xmlElementContentPtr content)28613 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28614 xmlElementContentPtr content)
28615 {
28616 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28617 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28618 (ctxt->user_sax->elementDecl != NULL))
28619 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28620 }
28621
28622 static void
notationDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)28623 notationDeclSplit(void *ctx, const xmlChar *name,
28624 const xmlChar *publicId, const xmlChar *systemId)
28625 {
28626 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28627 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28628 (ctxt->user_sax->notationDecl != NULL))
28629 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28630 systemId);
28631 }
28632
28633 static void
unparsedEntityDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)28634 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28635 const xmlChar *publicId, const xmlChar *systemId,
28636 const xmlChar *notationName)
28637 {
28638 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28639 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28640 (ctxt->user_sax->unparsedEntityDecl != NULL))
28641 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28642 systemId, notationName);
28643 }
28644
28645 static void
setDocumentLocatorSplit(void * ctx,xmlSAXLocatorPtr loc)28646 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28647 {
28648 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28649 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28650 (ctxt->user_sax->setDocumentLocator != NULL))
28651 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28652 }
28653
28654 static void
startDocumentSplit(void * ctx)28655 startDocumentSplit(void *ctx)
28656 {
28657 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28658 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28659 (ctxt->user_sax->startDocument != NULL))
28660 ctxt->user_sax->startDocument(ctxt->user_data);
28661 }
28662
28663 static void
endDocumentSplit(void * ctx)28664 endDocumentSplit(void *ctx)
28665 {
28666 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28667 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28668 (ctxt->user_sax->endDocument != NULL))
28669 ctxt->user_sax->endDocument(ctxt->user_data);
28670 }
28671
28672 static void
processingInstructionSplit(void * ctx,const xmlChar * target,const xmlChar * data)28673 processingInstructionSplit(void *ctx, const xmlChar *target,
28674 const xmlChar *data)
28675 {
28676 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28677 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28678 (ctxt->user_sax->processingInstruction != NULL))
28679 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28680 }
28681
28682 static void
commentSplit(void * ctx,const xmlChar * value)28683 commentSplit(void *ctx, const xmlChar *value)
28684 {
28685 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28686 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28687 (ctxt->user_sax->comment != NULL))
28688 ctxt->user_sax->comment(ctxt->user_data, value);
28689 }
28690
28691 /*
28692 * Varargs error callbacks to the user application, harder ...
28693 */
28694
28695 static void XMLCDECL
warningSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28696 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28697 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28698 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28699 (ctxt->user_sax->warning != NULL)) {
28700 TODO
28701 }
28702 }
28703 static void XMLCDECL
errorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28704 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28705 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28706 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28707 (ctxt->user_sax->error != NULL)) {
28708 TODO
28709 }
28710 }
28711 static void XMLCDECL
fatalErrorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28712 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28713 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28714 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28715 (ctxt->user_sax->fatalError != NULL)) {
28716 TODO
28717 }
28718 }
28719
28720 /*
28721 * Those are function where both the user handler and the schemas handler
28722 * need to be called.
28723 */
28724 static void
charactersSplit(void * ctx,const xmlChar * ch,int len)28725 charactersSplit(void *ctx, const xmlChar *ch, int len)
28726 {
28727 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28728 if (ctxt == NULL)
28729 return;
28730 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28731 ctxt->user_sax->characters(ctxt->user_data, ch, len);
28732 if (ctxt->ctxt != NULL)
28733 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28734 }
28735
28736 static void
ignorableWhitespaceSplit(void * ctx,const xmlChar * ch,int len)28737 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28738 {
28739 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28740 if (ctxt == NULL)
28741 return;
28742 if ((ctxt->user_sax != NULL) &&
28743 (ctxt->user_sax->ignorableWhitespace != NULL))
28744 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28745 if (ctxt->ctxt != NULL)
28746 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28747 }
28748
28749 static void
cdataBlockSplit(void * ctx,const xmlChar * value,int len)28750 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28751 {
28752 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28753 if (ctxt == NULL)
28754 return;
28755 if ((ctxt->user_sax != NULL) &&
28756 (ctxt->user_sax->cdataBlock != NULL))
28757 ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28758 if (ctxt->ctxt != NULL)
28759 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28760 }
28761
28762 static void
referenceSplit(void * ctx,const xmlChar * name)28763 referenceSplit(void *ctx, const xmlChar *name)
28764 {
28765 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28766 if (ctxt == NULL)
28767 return;
28768 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28769 (ctxt->user_sax->reference != NULL))
28770 ctxt->user_sax->reference(ctxt->user_data, name);
28771 if (ctxt->ctxt != NULL)
28772 xmlSchemaSAXHandleReference(ctxt->user_data, name);
28773 }
28774
28775 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)28776 startElementNsSplit(void *ctx, const xmlChar * localname,
28777 const xmlChar * prefix, const xmlChar * URI,
28778 int nb_namespaces, const xmlChar ** namespaces,
28779 int nb_attributes, int nb_defaulted,
28780 const xmlChar ** attributes) {
28781 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28782 if (ctxt == NULL)
28783 return;
28784 if ((ctxt->user_sax != NULL) &&
28785 (ctxt->user_sax->startElementNs != NULL))
28786 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28787 URI, nb_namespaces, namespaces,
28788 nb_attributes, nb_defaulted,
28789 attributes);
28790 if (ctxt->ctxt != NULL)
28791 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28792 URI, nb_namespaces, namespaces,
28793 nb_attributes, nb_defaulted,
28794 attributes);
28795 }
28796
28797 static void
endElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)28798 endElementNsSplit(void *ctx, const xmlChar * localname,
28799 const xmlChar * prefix, const xmlChar * URI) {
28800 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28801 if (ctxt == NULL)
28802 return;
28803 if ((ctxt->user_sax != NULL) &&
28804 (ctxt->user_sax->endElementNs != NULL))
28805 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28806 if (ctxt->ctxt != NULL)
28807 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28808 }
28809
28810 /**
28811 * xmlSchemaSAXPlug:
28812 * @ctxt: a schema validation context
28813 * @sax: a pointer to the original xmlSAXHandlerPtr
28814 * @user_data: a pointer to the original SAX user data pointer
28815 *
28816 * Plug a SAX based validation layer in a SAX parsing event flow.
28817 * The original @saxptr and @dataptr data are replaced by new pointers
28818 * but the calls to the original will be maintained.
28819 *
28820 * Returns a pointer to a data structure needed to unplug the validation layer
28821 * or NULL in case of errors.
28822 */
28823 xmlSchemaSAXPlugPtr
xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,xmlSAXHandlerPtr * sax,void ** user_data)28824 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28825 xmlSAXHandlerPtr *sax, void **user_data)
28826 {
28827 xmlSchemaSAXPlugPtr ret;
28828 xmlSAXHandlerPtr old_sax;
28829
28830 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28831 return(NULL);
28832
28833 /*
28834 * We only allow to plug into SAX2 event streams
28835 */
28836 old_sax = *sax;
28837 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28838 return(NULL);
28839 if ((old_sax != NULL) &&
28840 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28841 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28842 return(NULL);
28843
28844 /*
28845 * everything seems right allocate the local data needed for that layer
28846 */
28847 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28848 if (ret == NULL) {
28849 return(NULL);
28850 }
28851 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28852 ret->magic = XML_SAX_PLUG_MAGIC;
28853 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28854 ret->ctxt = ctxt;
28855 ret->user_sax_ptr = sax;
28856 ret->user_sax = old_sax;
28857 if (old_sax == NULL) {
28858 /*
28859 * go direct, no need for the split block and functions.
28860 */
28861 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28862 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28863 /*
28864 * Note that we use the same text-function for both, to prevent
28865 * the parser from testing for ignorable whitespace.
28866 */
28867 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28868 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28869
28870 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28871 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28872
28873 ret->user_data = ctxt;
28874 *user_data = ctxt;
28875 } else {
28876 /*
28877 * for each callback unused by Schemas initialize it to the Split
28878 * routine only if non NULL in the user block, this can speed up
28879 * things at the SAX level.
28880 */
28881 if (old_sax->internalSubset != NULL)
28882 ret->schemas_sax.internalSubset = internalSubsetSplit;
28883 if (old_sax->isStandalone != NULL)
28884 ret->schemas_sax.isStandalone = isStandaloneSplit;
28885 if (old_sax->hasInternalSubset != NULL)
28886 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28887 if (old_sax->hasExternalSubset != NULL)
28888 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28889 if (old_sax->resolveEntity != NULL)
28890 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28891 if (old_sax->getEntity != NULL)
28892 ret->schemas_sax.getEntity = getEntitySplit;
28893 if (old_sax->entityDecl != NULL)
28894 ret->schemas_sax.entityDecl = entityDeclSplit;
28895 if (old_sax->notationDecl != NULL)
28896 ret->schemas_sax.notationDecl = notationDeclSplit;
28897 if (old_sax->attributeDecl != NULL)
28898 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28899 if (old_sax->elementDecl != NULL)
28900 ret->schemas_sax.elementDecl = elementDeclSplit;
28901 if (old_sax->unparsedEntityDecl != NULL)
28902 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28903 if (old_sax->setDocumentLocator != NULL)
28904 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28905 if (old_sax->startDocument != NULL)
28906 ret->schemas_sax.startDocument = startDocumentSplit;
28907 if (old_sax->endDocument != NULL)
28908 ret->schemas_sax.endDocument = endDocumentSplit;
28909 if (old_sax->processingInstruction != NULL)
28910 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28911 if (old_sax->comment != NULL)
28912 ret->schemas_sax.comment = commentSplit;
28913 if (old_sax->warning != NULL)
28914 ret->schemas_sax.warning = warningSplit;
28915 if (old_sax->error != NULL)
28916 ret->schemas_sax.error = errorSplit;
28917 if (old_sax->fatalError != NULL)
28918 ret->schemas_sax.fatalError = fatalErrorSplit;
28919 if (old_sax->getParameterEntity != NULL)
28920 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28921 if (old_sax->externalSubset != NULL)
28922 ret->schemas_sax.externalSubset = externalSubsetSplit;
28923
28924 /*
28925 * the 6 schemas callback have to go to the splitter functions
28926 * Note that we use the same text-function for ignorableWhitespace
28927 * if possible, to prevent the parser from testing for ignorable
28928 * whitespace.
28929 */
28930 ret->schemas_sax.characters = charactersSplit;
28931 if ((old_sax->ignorableWhitespace != NULL) &&
28932 (old_sax->ignorableWhitespace != old_sax->characters))
28933 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28934 else
28935 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28936 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28937 ret->schemas_sax.reference = referenceSplit;
28938 ret->schemas_sax.startElementNs = startElementNsSplit;
28939 ret->schemas_sax.endElementNs = endElementNsSplit;
28940
28941 ret->user_data_ptr = user_data;
28942 ret->user_data = *user_data;
28943 *user_data = ret;
28944 }
28945
28946 /*
28947 * plug the pointers back.
28948 */
28949 *sax = &(ret->schemas_sax);
28950 ctxt->sax = *sax;
28951 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28952 xmlSchemaPreRun(ctxt);
28953 return(ret);
28954 }
28955
28956 /**
28957 * xmlSchemaSAXUnplug:
28958 * @plug: a data structure returned by xmlSchemaSAXPlug
28959 *
28960 * Unplug a SAX based validation layer in a SAX parsing event flow.
28961 * The original pointers used in the call are restored.
28962 *
28963 * Returns 0 in case of success and -1 in case of failure.
28964 */
28965 int
xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)28966 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28967 {
28968 xmlSAXHandlerPtr *sax;
28969 void **user_data;
28970
28971 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28972 return(-1);
28973 plug->magic = 0;
28974
28975 xmlSchemaPostRun(plug->ctxt);
28976 /* restore the data */
28977 sax = plug->user_sax_ptr;
28978 *sax = plug->user_sax;
28979 if (plug->user_sax != NULL) {
28980 user_data = plug->user_data_ptr;
28981 *user_data = plug->user_data;
28982 }
28983
28984 /* free and return */
28985 xmlFree(plug);
28986 return(0);
28987 }
28988
28989 /**
28990 * xmlSchemaValidateSetLocator:
28991 * @vctxt: a schema validation context
28992 * @f: the locator function pointer
28993 * @ctxt: the locator context
28994 *
28995 * Allows to set a locator function to the validation context,
28996 * which will be used to provide file and line information since
28997 * those are not provided as part of the SAX validation flow
28998 * Setting @f to NULL disable the locator.
28999 */
29000
29001 void
xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,xmlSchemaValidityLocatorFunc f,void * ctxt)29002 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
29003 xmlSchemaValidityLocatorFunc f,
29004 void *ctxt)
29005 {
29006 if (vctxt == NULL) return;
29007 vctxt->locFunc = f;
29008 vctxt->locCtxt = ctxt;
29009 }
29010
29011 /**
29012 * xmlSchemaValidateStreamLocator:
29013 * @ctx: the xmlTextReaderPtr used
29014 * @file: returned file information
29015 * @line: returned line information
29016 *
29017 * Internal locator function for the readers
29018 *
29019 * Returns 0 in case the Schema validation could be (de)activated and
29020 * -1 in case of error.
29021 */
29022 static int
xmlSchemaValidateStreamLocator(void * ctx,const char ** file,unsigned long * line)29023 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
29024 unsigned long *line) {
29025 xmlParserCtxtPtr ctxt;
29026
29027 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
29028 return(-1);
29029
29030 if (file != NULL)
29031 *file = NULL;
29032 if (line != NULL)
29033 *line = 0;
29034
29035 ctxt = (xmlParserCtxtPtr) ctx;
29036 if (ctxt->input != NULL) {
29037 if (file != NULL)
29038 *file = ctxt->input->filename;
29039 if (line != NULL)
29040 *line = ctxt->input->line;
29041 return(0);
29042 }
29043 return(-1);
29044 }
29045
29046 /**
29047 * xmlSchemaValidateStream:
29048 * @ctxt: a schema validation context
29049 * @input: the input to use for reading the data
29050 * @enc: an optional encoding information
29051 * @sax: a SAX handler for the resulting events
29052 * @user_data: the context to provide to the SAX handler.
29053 *
29054 * Validate an input based on a flow of SAX event from the parser
29055 * and forward the events to the @sax handler with the provided @user_data
29056 * the user provided @sax handler must be a SAX2 one.
29057 *
29058 * Returns 0 if the document is schemas valid, a positive error code
29059 * number otherwise and -1 in case of internal or API error.
29060 */
29061 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,xmlSAXHandlerPtr sax,void * user_data)29062 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
29063 xmlParserInputBufferPtr input, xmlCharEncoding enc,
29064 xmlSAXHandlerPtr sax, void *user_data)
29065 {
29066 xmlSchemaSAXPlugPtr plug = NULL;
29067 xmlSAXHandlerPtr old_sax = NULL;
29068 xmlParserCtxtPtr pctxt = NULL;
29069 xmlParserInputPtr inputStream = NULL;
29070 int ret;
29071
29072 if ((ctxt == NULL) || (input == NULL))
29073 return (-1);
29074
29075 /*
29076 * prepare the parser
29077 */
29078 pctxt = xmlNewParserCtxt();
29079 if (pctxt == NULL)
29080 return (-1);
29081 old_sax = pctxt->sax;
29082 pctxt->sax = sax;
29083 pctxt->userData = user_data;
29084 #if 0
29085 if (options)
29086 xmlCtxtUseOptions(pctxt, options);
29087 #endif
29088 pctxt->linenumbers = 1;
29089 xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
29090
29091 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
29092 if (inputStream == NULL) {
29093 ret = -1;
29094 goto done;
29095 }
29096 inputPush(pctxt, inputStream);
29097 ctxt->parserCtxt = pctxt;
29098 ctxt->input = input;
29099
29100 /*
29101 * Plug the validation and launch the parsing
29102 */
29103 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
29104 if (plug == NULL) {
29105 ret = -1;
29106 goto done;
29107 }
29108 ctxt->input = input;
29109 ctxt->enc = enc;
29110 ctxt->sax = pctxt->sax;
29111 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
29112 ret = xmlSchemaVStart(ctxt);
29113
29114 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
29115 ret = ctxt->parserCtxt->errNo;
29116 if (ret == 0)
29117 ret = 1;
29118 }
29119
29120 done:
29121 ctxt->parserCtxt = NULL;
29122 ctxt->sax = NULL;
29123 ctxt->input = NULL;
29124 if (plug != NULL) {
29125 xmlSchemaSAXUnplug(plug);
29126 }
29127 /* cleanup */
29128 if (pctxt != NULL) {
29129 pctxt->sax = old_sax;
29130 xmlFreeParserCtxt(pctxt);
29131 }
29132 return (ret);
29133 }
29134
29135 /**
29136 * xmlSchemaValidateFile:
29137 * @ctxt: a schema validation context
29138 * @filename: the URI of the instance
29139 * @options: a future set of options, currently unused
29140 *
29141 * Do a schemas validation of the given resource, it will use the
29142 * SAX streamable validation internally.
29143 *
29144 * Returns 0 if the document is valid, a positive error code
29145 * number otherwise and -1 in case of an internal or API error.
29146 */
29147 int
xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,const char * filename,int options ATTRIBUTE_UNUSED)29148 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
29149 const char * filename,
29150 int options ATTRIBUTE_UNUSED)
29151 {
29152 int ret;
29153 xmlParserInputBufferPtr input;
29154
29155 if ((ctxt == NULL) || (filename == NULL))
29156 return (-1);
29157
29158 input = xmlParserInputBufferCreateFilename(filename,
29159 XML_CHAR_ENCODING_NONE);
29160 if (input == NULL)
29161 return (-1);
29162 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
29163 NULL, NULL);
29164 return (ret);
29165 }
29166
29167 /**
29168 * xmlSchemaValidCtxtGetParserCtxt:
29169 * @ctxt: a schema validation context
29170 *
29171 * allow access to the parser context of the schema validation context
29172 *
29173 * Returns the parser context of the schema validation context or NULL
29174 * in case of error.
29175 */
29176 xmlParserCtxtPtr
xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)29177 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
29178 {
29179 if (ctxt == NULL)
29180 return(NULL);
29181 return (ctxt->parserCtxt);
29182 }
29183
29184 #define bottom_xmlschemas
29185 #include "elfgcchack.h"
29186 #endif /* LIBXML_SCHEMAS_ENABLED */
29187