Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/xml2/xmlschemas.c
4389 views
1
/*
2
* schemas.c : implementation of the XML Schema handling and
3
* schema validity checking
4
*
5
* See Copyright for the status of this software.
6
*
7
* Daniel Veillard <[email protected]>
8
*/
9
10
/*
11
* TODO:
12
* - when types are redefined in includes, check that all
13
* types in the redef list are equal
14
* -> need a type equality operation.
15
* - if we don't intend to use the schema for schemas, we
16
* need to validate all schema attributes (ref, type, name)
17
* against their types.
18
* - Eliminate item creation for: ??
19
*
20
* URGENT TODO:
21
* - For xsi-driven schema acquisition, augment the IDCs after every
22
* acquisition episode (xmlSchemaAugmentIDC).
23
*
24
* NOTES:
25
* - Eliminated item creation for: <restriction>, <extension>,
26
* <simpleContent>, <complexContent>, <list>, <union>
27
*
28
* PROBLEMS:
29
* - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30
* IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31
* XPath will have trouble to resolve to this namespace, since not known.
32
*
33
*
34
* CONSTRAINTS:
35
*
36
* Schema Component Constraint:
37
* All Group Limited (cos-all-limited)
38
* Status: complete
39
* (1.2)
40
* In xmlSchemaGroupDefReferenceTermFixup() and
41
* (2)
42
* In xmlSchemaParseModelGroup()
43
* TODO: Actually this should go to component-level checks,
44
* but is done here due to performance. Move it to an other layer
45
* is schema construction via an API is implemented.
46
*/
47
48
/* To avoid EBCDIC trouble when parsing on zOS */
49
#if defined(__MVS__)
50
#pragma convert("ISO8859-1")
51
#endif
52
53
#define IN_LIBXML
54
#include "libxml.h"
55
56
#ifdef LIBXML_SCHEMAS_ENABLED
57
58
#include <string.h>
59
#include <libxml/xmlmemory.h>
60
#include <libxml/parser.h>
61
#include <libxml/parserInternals.h>
62
#include <libxml/hash.h>
63
#include <libxml/uri.h>
64
#include <libxml/xmlschemas.h>
65
#include <libxml/schemasInternals.h>
66
#include <libxml/xmlschemastypes.h>
67
#include <libxml/xmlautomata.h>
68
#include <libxml/xmlregexp.h>
69
#include <libxml/dict.h>
70
#include <libxml/encoding.h>
71
#include <libxml/xmlIO.h>
72
#ifdef LIBXML_PATTERN_ENABLED
73
#include <libxml/pattern.h>
74
#endif
75
#ifdef LIBXML_READER_ENABLED
76
#include <libxml/xmlreader.h>
77
#endif
78
79
#include "private/error.h"
80
#include "private/string.h"
81
82
/* #define WXS_ELEM_DECL_CONS_ENABLED */
83
84
/* #define ENABLE_PARTICLE_RESTRICTION 1 */
85
86
#define ENABLE_REDEFINE
87
88
/* #define ENABLE_NAMED_LOCALS */
89
90
/* #define ENABLE_IDC_NODE_TABLES_TEST */
91
92
#define DUMP_CONTENT_MODEL
93
94
#ifdef LIBXML_READER_ENABLED
95
/* #define XML_SCHEMA_READER_ENABLED */
96
#endif
97
98
#define UNBOUNDED (1 << 30)
99
#define TODO \
100
xmlGenericError(xmlGenericErrorContext, \
101
"Unimplemented block at %s:%d\n", \
102
__FILE__, __LINE__);
103
104
#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
105
106
/*
107
* The XML Schemas namespaces
108
*/
109
static const xmlChar *xmlSchemaNs = (const xmlChar *)
110
"http://www.w3.org/2001/XMLSchema";
111
112
static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
113
"http://www.w3.org/2001/XMLSchema-instance";
114
115
static const xmlChar *xmlNamespaceNs = (const xmlChar *)
116
"http://www.w3.org/2000/xmlns/";
117
118
/*
119
* Come casting macros.
120
*/
121
#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
122
#define PCTXT_CAST (xmlSchemaParserCtxtPtr)
123
#define VCTXT_CAST (xmlSchemaValidCtxtPtr)
124
#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
125
#define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
126
#define WXS_PTC_CAST (xmlSchemaParticlePtr)
127
#define WXS_TYPE_CAST (xmlSchemaTypePtr)
128
#define WXS_ELEM_CAST (xmlSchemaElementPtr)
129
#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
130
#define WXS_ATTR_CAST (xmlSchemaAttributePtr)
131
#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
132
#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
133
#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
134
#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
135
#define WXS_IDC_CAST (xmlSchemaIDCPtr)
136
#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
137
#define WXS_LIST_CAST (xmlSchemaItemListPtr)
138
139
/*
140
* Macros to query common properties of components.
141
*/
142
#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
143
144
#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
145
/*
146
* Macros for element declarations.
147
*/
148
#define WXS_ELEM_TYPEDEF(e) (e)->subtypes
149
150
#define WXS_SUBST_HEAD(item) (item)->refDecl
151
/*
152
* Macros for attribute declarations.
153
*/
154
#define WXS_ATTR_TYPEDEF(a) (a)->subtypes
155
/*
156
* Macros for attribute uses.
157
*/
158
#define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
159
160
#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
161
162
#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
163
164
#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
165
/*
166
* Macros for attribute groups.
167
*/
168
#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
169
#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
170
/*
171
* Macros for particles.
172
*/
173
#define WXS_PARTICLE(p) WXS_PTC_CAST (p)
174
175
#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
176
177
#define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
178
179
#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
180
/*
181
* Macros for model groups definitions.
182
*/
183
#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
184
/*
185
* Macros for model groups.
186
*/
187
#define WXS_IS_MODEL_GROUP(i) \
188
(((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
189
((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
190
((i)->type == XML_SCHEMA_TYPE_ALL))
191
192
#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
193
/*
194
* Macros for schema buckets.
195
*/
196
#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
197
((t) == XML_SCHEMA_SCHEMA_REDEFINE))
198
199
#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
200
((t) == XML_SCHEMA_SCHEMA_IMPORT))
201
202
#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
203
204
#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
205
/*
206
* Macros for complex/simple types.
207
*/
208
#define WXS_IS_ANYTYPE(i) \
209
(( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
210
( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
211
212
#define WXS_IS_COMPLEX(i) \
213
(((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
214
((i)->builtInType == XML_SCHEMAS_ANYTYPE))
215
216
#define WXS_IS_SIMPLE(item) \
217
((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
218
((item->type == XML_SCHEMA_TYPE_BASIC) && \
219
(item->builtInType != XML_SCHEMAS_ANYTYPE)))
220
221
#define WXS_IS_ANY_SIMPLE_TYPE(i) \
222
(((i)->type == XML_SCHEMA_TYPE_BASIC) && \
223
((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
224
225
#define WXS_IS_RESTRICTION(t) \
226
((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
227
228
#define WXS_IS_EXTENSION(t) \
229
((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
230
231
#define WXS_IS_TYPE_NOT_FIXED(i) \
232
(((i)->type != XML_SCHEMA_TYPE_BASIC) && \
233
(((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
234
235
#define WXS_IS_TYPE_NOT_FIXED_1(item) \
236
(((item)->type != XML_SCHEMA_TYPE_BASIC) && \
237
(((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
238
239
#define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
240
241
#define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
242
/*
243
* Macros for exclusively for complex types.
244
*/
245
#define WXS_HAS_COMPLEX_CONTENT(item) \
246
((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
247
(item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
248
(item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
249
250
#define WXS_HAS_SIMPLE_CONTENT(item) \
251
((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
252
(item->contentType == XML_SCHEMA_CONTENT_BASIC))
253
254
#define WXS_HAS_MIXED_CONTENT(item) \
255
(item->contentType == XML_SCHEMA_CONTENT_MIXED)
256
257
#define WXS_EMPTIABLE(t) \
258
(xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
259
260
#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
261
262
#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
263
264
#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
265
/*
266
* Macros for exclusively for simple types.
267
*/
268
#define WXS_LIST_ITEMTYPE(t) (t)->subtypes
269
270
#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
271
272
#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
273
274
#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
275
/*
276
* Misc parser context macros.
277
*/
278
#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
279
280
#define WXS_HAS_BUCKETS(ctx) \
281
( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
282
(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
283
284
#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
285
286
#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
287
288
#define WXS_SCHEMA(ctx) (ctx)->schema
289
290
#define WXS_ADD_LOCAL(ctx, item) \
291
do { \
292
if (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item) < 0) { \
293
xmlFree(item); \
294
item = NULL; \
295
} \
296
} while (0)
297
298
#define WXS_ADD_GLOBAL(ctx, item) \
299
do { \
300
if (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item) < 0) { \
301
xmlFree(item); \
302
item = NULL; \
303
} \
304
} while (0)
305
306
#define WXS_ADD_PENDING(ctx, item) \
307
xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
308
/*
309
* xmlSchemaItemList macros.
310
*/
311
#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
312
/*
313
* Misc macros.
314
*/
315
#define IS_SCHEMA(node, type) \
316
((node != NULL) && (node->ns != NULL) && \
317
(xmlStrEqual(node->name, (const xmlChar *) type)) && \
318
(xmlStrEqual(node->ns->href, xmlSchemaNs)))
319
320
#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
321
322
/*
323
* Since we put the default/fixed values into the dict, we can
324
* use pointer comparison for those values.
325
* REMOVED: (xmlStrEqual((v1), (v2)))
326
*/
327
#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
328
329
#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
330
331
#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
332
333
#define HFAILURE if (res == -1) goto exit_failure;
334
335
#define HERROR if (res != 0) goto exit_error;
336
337
#define HSTOP(ctx) if ((ctx)->stop) goto exit;
338
/*
339
* Some flags used for various schema constraints.
340
*/
341
#define SUBSET_RESTRICTION 1<<0
342
#define SUBSET_EXTENSION 1<<1
343
#define SUBSET_SUBSTITUTION 1<<2
344
#define SUBSET_LIST 1<<3
345
#define SUBSET_UNION 1<<4
346
347
typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
348
typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
349
350
typedef struct _xmlSchemaItemList xmlSchemaItemList;
351
typedef xmlSchemaItemList *xmlSchemaItemListPtr;
352
struct _xmlSchemaItemList {
353
void **items; /* used for dynamic addition of schemata */
354
int nbItems; /* used for dynamic addition of schemata */
355
int sizeItems; /* used for dynamic addition of schemata */
356
};
357
358
#define XML_SCHEMA_CTXT_PARSER 1
359
#define XML_SCHEMA_CTXT_VALIDATOR 2
360
361
typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
362
typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
363
struct _xmlSchemaAbstractCtxt {
364
int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
365
void *dummy; /* Fix alignment issues */
366
};
367
368
typedef struct _xmlSchemaBucket xmlSchemaBucket;
369
typedef xmlSchemaBucket *xmlSchemaBucketPtr;
370
371
#define XML_SCHEMA_SCHEMA_MAIN 0
372
#define XML_SCHEMA_SCHEMA_IMPORT 1
373
#define XML_SCHEMA_SCHEMA_INCLUDE 2
374
#define XML_SCHEMA_SCHEMA_REDEFINE 3
375
376
/**
377
* xmlSchemaSchemaRelation:
378
*
379
* Used to create a graph of schema relationships.
380
*/
381
typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
382
typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
383
struct _xmlSchemaSchemaRelation {
384
xmlSchemaSchemaRelationPtr next;
385
int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
386
const xmlChar *importNamespace;
387
xmlSchemaBucketPtr bucket;
388
};
389
390
#define XML_SCHEMA_BUCKET_MARKED 1<<0
391
#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
392
393
struct _xmlSchemaBucket {
394
int type;
395
int flags;
396
const xmlChar *schemaLocation;
397
const xmlChar *origTargetNamespace;
398
const xmlChar *targetNamespace;
399
xmlDocPtr doc;
400
xmlSchemaSchemaRelationPtr relations;
401
int located;
402
int parsed;
403
int imported;
404
int preserveDoc;
405
xmlSchemaItemListPtr globals; /* Global components. */
406
xmlSchemaItemListPtr locals; /* Local components. */
407
};
408
409
/**
410
* xmlSchemaImport:
411
* (extends xmlSchemaBucket)
412
*
413
* Reflects a schema. Holds some information
414
* about the schema and its toplevel components. Duplicate
415
* toplevel components are not checked at this level.
416
*/
417
typedef struct _xmlSchemaImport xmlSchemaImport;
418
typedef xmlSchemaImport *xmlSchemaImportPtr;
419
struct _xmlSchemaImport {
420
int type; /* Main OR import OR include. */
421
int flags;
422
const xmlChar *schemaLocation; /* The URI of the schema document. */
423
/* For chameleon includes, @origTargetNamespace will be NULL */
424
const xmlChar *origTargetNamespace;
425
/*
426
* For chameleon includes, @targetNamespace will be the
427
* targetNamespace of the including schema.
428
*/
429
const xmlChar *targetNamespace;
430
xmlDocPtr doc; /* The schema node-tree. */
431
/* @relations will hold any included/imported/redefined schemas. */
432
xmlSchemaSchemaRelationPtr relations;
433
int located;
434
int parsed;
435
int imported;
436
int preserveDoc;
437
xmlSchemaItemListPtr globals;
438
xmlSchemaItemListPtr locals;
439
/* The imported schema. */
440
xmlSchemaPtr schema;
441
};
442
443
/*
444
* (extends xmlSchemaBucket)
445
*/
446
typedef struct _xmlSchemaInclude xmlSchemaInclude;
447
typedef xmlSchemaInclude *xmlSchemaIncludePtr;
448
struct _xmlSchemaInclude {
449
int type;
450
int flags;
451
const xmlChar *schemaLocation;
452
const xmlChar *origTargetNamespace;
453
const xmlChar *targetNamespace;
454
xmlDocPtr doc;
455
xmlSchemaSchemaRelationPtr relations;
456
int located;
457
int parsed;
458
int imported;
459
int preserveDoc;
460
xmlSchemaItemListPtr globals; /* Global components. */
461
xmlSchemaItemListPtr locals; /* Local components. */
462
463
/* The owning main or import schema bucket. */
464
xmlSchemaImportPtr ownerImport;
465
};
466
467
/**
468
* xmlSchemaBasicItem:
469
*
470
* The abstract base type for schema components.
471
*/
472
typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
473
typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
474
struct _xmlSchemaBasicItem {
475
xmlSchemaTypeType type;
476
void *dummy; /* Fix alignment issues */
477
};
478
479
/**
480
* xmlSchemaAnnotItem:
481
*
482
* The abstract base type for annotated schema components.
483
* (Extends xmlSchemaBasicItem)
484
*/
485
typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
486
typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
487
struct _xmlSchemaAnnotItem {
488
xmlSchemaTypeType type;
489
xmlSchemaAnnotPtr annot;
490
};
491
492
/**
493
* xmlSchemaTreeItem:
494
*
495
* The abstract base type for tree-like structured schema components.
496
* (Extends xmlSchemaAnnotItem)
497
*/
498
typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
499
typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
500
struct _xmlSchemaTreeItem {
501
xmlSchemaTypeType type;
502
xmlSchemaAnnotPtr annot;
503
xmlSchemaTreeItemPtr next;
504
xmlSchemaTreeItemPtr children;
505
};
506
507
508
#define XML_SCHEMA_ATTR_USE_FIXED 1<<0
509
/**
510
* xmlSchemaAttributeUsePtr:
511
*
512
* The abstract base type for tree-like structured schema components.
513
* (Extends xmlSchemaTreeItem)
514
*/
515
typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
516
typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
517
struct _xmlSchemaAttributeUse {
518
xmlSchemaTypeType type;
519
xmlSchemaAnnotPtr annot;
520
xmlSchemaAttributeUsePtr next; /* The next attr. use. */
521
/*
522
* The attr. decl. OR a QName-ref. to an attr. decl. OR
523
* a QName-ref. to an attribute group definition.
524
*/
525
xmlSchemaAttributePtr attrDecl;
526
527
int flags;
528
xmlNodePtr node;
529
int occurs; /* required, optional */
530
const xmlChar * defValue;
531
xmlSchemaValPtr defVal;
532
};
533
534
/**
535
* xmlSchemaAttributeUseProhibPtr:
536
*
537
* A helper component to reflect attribute prohibitions.
538
* (Extends xmlSchemaBasicItem)
539
*/
540
typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
541
typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
542
struct _xmlSchemaAttributeUseProhib {
543
xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
544
xmlNodePtr node;
545
const xmlChar *name;
546
const xmlChar *targetNamespace;
547
int isRef;
548
};
549
550
/**
551
* xmlSchemaRedef:
552
*/
553
typedef struct _xmlSchemaRedef xmlSchemaRedef;
554
typedef xmlSchemaRedef *xmlSchemaRedefPtr;
555
struct _xmlSchemaRedef {
556
xmlSchemaRedefPtr next;
557
xmlSchemaBasicItemPtr item; /* The redefining component. */
558
xmlSchemaBasicItemPtr reference; /* The referencing component. */
559
xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
560
const xmlChar *refName; /* The name of the to-be-redefined component. */
561
const xmlChar *refTargetNs; /* The target namespace of the
562
to-be-redefined comp. */
563
xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
564
};
565
566
/**
567
* xmlSchemaConstructionCtxt:
568
*/
569
typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
570
typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
571
struct _xmlSchemaConstructionCtxt {
572
xmlSchemaPtr mainSchema; /* The main schema. */
573
xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
574
xmlDictPtr dict;
575
xmlSchemaItemListPtr buckets; /* List of schema buckets. */
576
/* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
577
xmlSchemaBucketPtr bucket; /* The current schema bucket */
578
xmlSchemaItemListPtr pending; /* All Components of all schemas that
579
need to be fixed. */
580
xmlHashTablePtr substGroups;
581
xmlSchemaRedefPtr redefs;
582
xmlSchemaRedefPtr lastRedef;
583
};
584
585
#define XML_SCHEMAS_PARSE_ERROR 1
586
#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
587
588
struct _xmlSchemaParserCtxt {
589
int type;
590
void *errCtxt; /* user specific error context */
591
xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
592
xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
593
int err;
594
int nberrors;
595
xmlStructuredErrorFunc serror;
596
597
xmlSchemaConstructionCtxtPtr constructor;
598
int ownsConstructor; /* TODO: Move this to parser *flags*. */
599
600
/* xmlSchemaPtr topschema; */
601
/* xmlHashTablePtr namespaces; */
602
603
xmlSchemaPtr schema; /* The main schema in use */
604
int counter;
605
606
const xmlChar *URL;
607
xmlDocPtr doc;
608
int preserve; /* Whether the doc should be freed */
609
610
const char *buffer;
611
int size;
612
613
/*
614
* Used to build complex element content models
615
*/
616
xmlAutomataPtr am;
617
xmlAutomataStatePtr start;
618
xmlAutomataStatePtr end;
619
xmlAutomataStatePtr state;
620
621
xmlDictPtr dict; /* dictionary for interned string names */
622
xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
623
int options;
624
xmlSchemaValidCtxtPtr vctxt;
625
int isS4S;
626
int isRedefine;
627
int xsiAssemble;
628
int stop; /* If the parser should stop; i.e. a critical error. */
629
const xmlChar *targetNamespace;
630
xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
631
632
xmlSchemaRedefPtr redef; /* Used for redefinitions. */
633
int redefCounter; /* Used for redefinitions. */
634
xmlSchemaItemListPtr attrProhibs;
635
};
636
637
/**
638
* xmlSchemaQNameRef:
639
*
640
* A component reference item (not a schema component)
641
* (Extends xmlSchemaBasicItem)
642
*/
643
typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
644
typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
645
struct _xmlSchemaQNameRef {
646
xmlSchemaTypeType type;
647
xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
648
xmlSchemaTypeType itemType;
649
const xmlChar *name;
650
const xmlChar *targetNamespace;
651
xmlNodePtr node;
652
};
653
654
/**
655
* xmlSchemaParticle:
656
*
657
* A particle component.
658
* (Extends xmlSchemaTreeItem)
659
*/
660
typedef struct _xmlSchemaParticle xmlSchemaParticle;
661
typedef xmlSchemaParticle *xmlSchemaParticlePtr;
662
struct _xmlSchemaParticle {
663
xmlSchemaTypeType type;
664
xmlSchemaAnnotPtr annot;
665
xmlSchemaTreeItemPtr next; /* next particle */
666
xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
667
a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
668
etc.) */
669
int minOccurs;
670
int maxOccurs;
671
xmlNodePtr node;
672
};
673
674
/**
675
* xmlSchemaModelGroup:
676
*
677
* A model group component.
678
* (Extends xmlSchemaTreeItem)
679
*/
680
typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
681
typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
682
struct _xmlSchemaModelGroup {
683
xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
684
xmlSchemaAnnotPtr annot;
685
xmlSchemaTreeItemPtr next; /* not used */
686
xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
687
xmlNodePtr node;
688
};
689
690
#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
691
#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
692
/**
693
* xmlSchemaModelGroupDef:
694
*
695
* A model group definition component.
696
* (Extends xmlSchemaTreeItem)
697
*/
698
typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
699
typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
700
struct _xmlSchemaModelGroupDef {
701
xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
702
xmlSchemaAnnotPtr annot;
703
xmlSchemaTreeItemPtr next; /* not used */
704
xmlSchemaTreeItemPtr children; /* the "model group" */
705
const xmlChar *name;
706
const xmlChar *targetNamespace;
707
xmlNodePtr node;
708
int flags;
709
};
710
711
typedef struct _xmlSchemaIDC xmlSchemaIDC;
712
typedef xmlSchemaIDC *xmlSchemaIDCPtr;
713
714
/**
715
* xmlSchemaIDCSelect:
716
*
717
* The identity-constraint "field" and "selector" item, holding the
718
* XPath expression.
719
*/
720
typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
721
typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
722
struct _xmlSchemaIDCSelect {
723
xmlSchemaIDCSelectPtr next;
724
xmlSchemaIDCPtr idc;
725
int index; /* an index position if significant for IDC key-sequences */
726
const xmlChar *xpath; /* the XPath expression */
727
void *xpathComp; /* the compiled XPath expression */
728
};
729
730
/**
731
* xmlSchemaIDC:
732
*
733
* The identity-constraint definition component.
734
* (Extends xmlSchemaAnnotItem)
735
*/
736
737
struct _xmlSchemaIDC {
738
xmlSchemaTypeType type;
739
xmlSchemaAnnotPtr annot;
740
xmlSchemaIDCPtr next;
741
xmlNodePtr node;
742
const xmlChar *name;
743
const xmlChar *targetNamespace;
744
xmlSchemaIDCSelectPtr selector;
745
xmlSchemaIDCSelectPtr fields;
746
int nbFields;
747
xmlSchemaQNameRefPtr ref;
748
};
749
750
/**
751
* xmlSchemaIDCAug:
752
*
753
* The augmented IDC information used for validation.
754
*/
755
typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
756
typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
757
struct _xmlSchemaIDCAug {
758
xmlSchemaIDCAugPtr next; /* next in a list */
759
xmlSchemaIDCPtr def; /* the IDC definition */
760
int keyrefDepth; /* the lowest tree level to which IDC
761
tables need to be bubbled upwards */
762
};
763
764
/**
765
* xmlSchemaPSVIIDCKeySequence:
766
*
767
* The key sequence of a node table item.
768
*/
769
typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
770
typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
771
struct _xmlSchemaPSVIIDCKey {
772
xmlSchemaTypePtr type;
773
xmlSchemaValPtr val;
774
};
775
776
/**
777
* xmlSchemaPSVIIDCNode:
778
*
779
* The node table item of a node table.
780
*/
781
typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
782
typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
783
struct _xmlSchemaPSVIIDCNode {
784
xmlNodePtr node;
785
xmlSchemaPSVIIDCKeyPtr *keys;
786
int nodeLine;
787
int nodeQNameID;
788
789
};
790
791
/**
792
* xmlSchemaPSVIIDCBinding:
793
*
794
* The identity-constraint binding item of the [identity-constraint table].
795
*/
796
typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
797
typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
798
struct _xmlSchemaPSVIIDCBinding {
799
xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
800
xmlSchemaIDCPtr definition; /* the IDC definition */
801
xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
802
int nbNodes; /* number of entries in the node table */
803
int sizeNodes; /* size of the node table */
804
xmlSchemaItemListPtr dupls;
805
};
806
807
808
#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
809
#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
810
811
#define XPATH_STATE_OBJ_MATCHES -2
812
#define XPATH_STATE_OBJ_BLOCKED -3
813
814
typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
815
typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
816
817
/**
818
* xmlSchemaIDCStateObj:
819
*
820
* The state object used to evaluate XPath expressions.
821
*/
822
typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
823
typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
824
struct _xmlSchemaIDCStateObj {
825
int type;
826
xmlSchemaIDCStateObjPtr next; /* next if in a list */
827
int depth; /* depth of creation */
828
int *history; /* list of (depth, state-id) tuples */
829
int nbHistory;
830
int sizeHistory;
831
xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
832
matcher */
833
xmlSchemaIDCSelectPtr sel;
834
void *xpathCtxt;
835
};
836
837
#define IDC_MATCHER 0
838
839
/**
840
* xmlSchemaIDCMatcher:
841
*
842
* Used to evaluate IDC selectors (and fields).
843
*/
844
struct _xmlSchemaIDCMatcher {
845
int type;
846
int depth; /* the tree depth at creation time */
847
xmlSchemaIDCMatcherPtr next; /* next in the list */
848
xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
849
xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
850
int idcType;
851
xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
852
elements */
853
int sizeKeySeqs;
854
xmlSchemaItemListPtr targets; /* list of target-node
855
(xmlSchemaPSVIIDCNodePtr) entries */
856
xmlHashTablePtr htab;
857
};
858
859
/*
860
* Element info flags.
861
*/
862
#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
863
#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
864
#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
865
#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
866
867
#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
868
#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
869
#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
870
871
#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
872
#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
873
#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
874
#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
875
876
/**
877
* xmlSchemaNodeInfo:
878
*
879
* Holds information of an element node.
880
*/
881
struct _xmlSchemaNodeInfo {
882
int nodeType;
883
xmlNodePtr node;
884
int nodeLine;
885
const xmlChar *localName;
886
const xmlChar *nsName;
887
const xmlChar *value;
888
xmlSchemaValPtr val; /* the pre-computed value if any */
889
xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
890
891
int flags; /* combination of node info flags */
892
893
int valNeeded;
894
int normVal;
895
896
xmlSchemaElementPtr decl; /* the element/attribute declaration */
897
int depth;
898
xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
899
for the scope element*/
900
xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
901
element */
902
xmlRegExecCtxtPtr regexCtxt;
903
904
const xmlChar **nsBindings; /* Namespace bindings on this element */
905
int nbNsBindings;
906
int sizeNsBindings;
907
908
int hasKeyrefs;
909
int appliedXPath; /* Indicates that an XPath has been applied. */
910
};
911
912
#define XML_SCHEMAS_ATTR_UNKNOWN 1
913
#define XML_SCHEMAS_ATTR_ASSESSED 2
914
#define XML_SCHEMAS_ATTR_PROHIBITED 3
915
#define XML_SCHEMAS_ATTR_ERR_MISSING 4
916
#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
917
#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
918
#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
919
#define XML_SCHEMAS_ATTR_DEFAULT 8
920
#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
921
#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
922
#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
923
#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
924
#define XML_SCHEMAS_ATTR_WILD_SKIP 13
925
#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
926
#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
927
#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
928
#define XML_SCHEMAS_ATTR_META 17
929
/*
930
* @metaType values of xmlSchemaAttrInfo.
931
*/
932
#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
933
#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
934
#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
935
#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
936
#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
937
938
typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
939
typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
940
struct _xmlSchemaAttrInfo {
941
int nodeType;
942
xmlNodePtr node;
943
int nodeLine;
944
const xmlChar *localName;
945
const xmlChar *nsName;
946
const xmlChar *value;
947
xmlSchemaValPtr val; /* the pre-computed value if any */
948
xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
949
int flags; /* combination of node info flags */
950
951
xmlSchemaAttributePtr decl; /* the attribute declaration */
952
xmlSchemaAttributeUsePtr use; /* the attribute use */
953
int state;
954
int metaType;
955
const xmlChar *vcValue; /* the value constraint value */
956
xmlSchemaNodeInfoPtr parent;
957
};
958
959
960
#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
961
/**
962
* xmlSchemaValidCtxt:
963
*
964
* A Schemas validation context
965
*/
966
struct _xmlSchemaValidCtxt {
967
int type;
968
void *errCtxt; /* user specific data block */
969
xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
970
xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
971
xmlStructuredErrorFunc serror;
972
973
xmlSchemaPtr schema; /* The schema in use */
974
xmlDocPtr doc;
975
xmlParserInputBufferPtr input;
976
xmlCharEncoding enc;
977
xmlSAXHandlerPtr sax;
978
xmlParserCtxtPtr parserCtxt;
979
void *user_data; /* TODO: What is this for? */
980
char *filename;
981
982
int err;
983
int nberrors;
984
985
xmlNodePtr node;
986
xmlNodePtr cur;
987
/* xmlSchemaTypePtr type; */
988
989
xmlRegExecCtxtPtr regexp;
990
xmlSchemaValPtr value;
991
992
int valueWS;
993
int options;
994
xmlNodePtr validationRoot;
995
xmlSchemaParserCtxtPtr pctxt;
996
int xsiAssemble;
997
998
int depth;
999
xmlSchemaNodeInfoPtr *elemInfos; /* array of element information */
1000
int sizeElemInfos;
1001
xmlSchemaNodeInfoPtr inode; /* the current element information */
1002
1003
xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC information */
1004
1005
xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1006
xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1007
xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1008
1009
xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1010
int nbIdcNodes;
1011
int sizeIdcNodes;
1012
1013
xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1014
int nbIdcKeys;
1015
int sizeIdcKeys;
1016
1017
int flags;
1018
1019
xmlDictPtr dict;
1020
1021
#ifdef LIBXML_READER_ENABLED
1022
xmlTextReaderPtr reader;
1023
#endif
1024
1025
xmlSchemaAttrInfoPtr *attrInfos;
1026
int nbAttrInfos;
1027
int sizeAttrInfos;
1028
1029
int skipDepth;
1030
xmlSchemaItemListPtr nodeQNames;
1031
int hasKeyrefs;
1032
int createIDCNodeTables;
1033
int psviExposeIDCNodeTables;
1034
1035
/* Locator for error reporting in streaming mode */
1036
xmlSchemaValidityLocatorFunc locFunc;
1037
void *locCtxt;
1038
};
1039
1040
/**
1041
* xmlSchemaSubstGroup:
1042
*
1043
*
1044
*/
1045
typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1046
typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1047
struct _xmlSchemaSubstGroup {
1048
xmlSchemaElementPtr head;
1049
xmlSchemaItemListPtr members;
1050
};
1051
1052
/**
1053
* xmlIDCHashEntry:
1054
*
1055
* an entry in hash tables to quickly look up keys/uniques
1056
*/
1057
typedef struct _xmlIDCHashEntry xmlIDCHashEntry;
1058
typedef xmlIDCHashEntry *xmlIDCHashEntryPtr;
1059
struct _xmlIDCHashEntry {
1060
xmlIDCHashEntryPtr next; /* next item with same hash */
1061
int index; /* index into associated item list */
1062
};
1063
1064
/************************************************************************
1065
* *
1066
* Some predeclarations *
1067
* *
1068
************************************************************************/
1069
1070
static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1071
xmlSchemaPtr schema,
1072
xmlNodePtr node);
1073
static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1074
xmlSchemaPtr schema,
1075
xmlNodePtr node);
1076
static int
1077
xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1078
xmlSchemaAbstractCtxtPtr ctxt);
1079
static const xmlChar *
1080
xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1081
static int
1082
xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1083
xmlNodePtr node);
1084
static int
1085
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1086
xmlSchemaParserCtxtPtr ctxt);
1087
static void
1088
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1089
static xmlSchemaWhitespaceValueType
1090
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1091
static xmlSchemaTreeItemPtr
1092
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1093
xmlNodePtr node, xmlSchemaTypeType type,
1094
int withParticle);
1095
static const xmlChar *
1096
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1097
static xmlSchemaTypeLinkPtr
1098
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1099
static void
1100
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1101
const char *funcName,
1102
const char *message) LIBXML_ATTR_FORMAT(3,0);
1103
static int
1104
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1105
xmlSchemaTypePtr type,
1106
xmlSchemaTypePtr baseType,
1107
int subset);
1108
static void
1109
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1110
xmlSchemaParserCtxtPtr ctxt);
1111
static void
1112
xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1113
static xmlSchemaQNameRefPtr
1114
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1115
xmlSchemaPtr schema,
1116
xmlNodePtr node);
1117
1118
/************************************************************************
1119
* *
1120
* Helper functions *
1121
* *
1122
************************************************************************/
1123
1124
/**
1125
* xmlSchemaItemTypeToStr:
1126
* @type: the type of the schema item
1127
*
1128
* Returns the component name of a schema item.
1129
*/
1130
static const xmlChar *
1131
xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1132
{
1133
switch (type) {
1134
case XML_SCHEMA_TYPE_BASIC:
1135
return(BAD_CAST "simple type definition");
1136
case XML_SCHEMA_TYPE_SIMPLE:
1137
return(BAD_CAST "simple type definition");
1138
case XML_SCHEMA_TYPE_COMPLEX:
1139
return(BAD_CAST "complex type definition");
1140
case XML_SCHEMA_TYPE_ELEMENT:
1141
return(BAD_CAST "element declaration");
1142
case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1143
return(BAD_CAST "attribute use");
1144
case XML_SCHEMA_TYPE_ATTRIBUTE:
1145
return(BAD_CAST "attribute declaration");
1146
case XML_SCHEMA_TYPE_GROUP:
1147
return(BAD_CAST "model group definition");
1148
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1149
return(BAD_CAST "attribute group definition");
1150
case XML_SCHEMA_TYPE_NOTATION:
1151
return(BAD_CAST "notation declaration");
1152
case XML_SCHEMA_TYPE_SEQUENCE:
1153
return(BAD_CAST "model group (sequence)");
1154
case XML_SCHEMA_TYPE_CHOICE:
1155
return(BAD_CAST "model group (choice)");
1156
case XML_SCHEMA_TYPE_ALL:
1157
return(BAD_CAST "model group (all)");
1158
case XML_SCHEMA_TYPE_PARTICLE:
1159
return(BAD_CAST "particle");
1160
case XML_SCHEMA_TYPE_IDC_UNIQUE:
1161
return(BAD_CAST "unique identity-constraint");
1162
/* return(BAD_CAST "IDC (unique)"); */
1163
case XML_SCHEMA_TYPE_IDC_KEY:
1164
return(BAD_CAST "key identity-constraint");
1165
/* return(BAD_CAST "IDC (key)"); */
1166
case XML_SCHEMA_TYPE_IDC_KEYREF:
1167
return(BAD_CAST "keyref identity-constraint");
1168
/* return(BAD_CAST "IDC (keyref)"); */
1169
case XML_SCHEMA_TYPE_ANY:
1170
return(BAD_CAST "wildcard (any)");
1171
case XML_SCHEMA_EXTRA_QNAMEREF:
1172
return(BAD_CAST "[helper component] QName reference");
1173
case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1174
return(BAD_CAST "[helper component] attribute use prohibition");
1175
default:
1176
return(BAD_CAST "Not a schema component");
1177
}
1178
}
1179
1180
/**
1181
* xmlSchemaGetComponentTypeStr:
1182
* @type: the type of the schema item
1183
*
1184
* Returns the component name of a schema item.
1185
*/
1186
static const xmlChar *
1187
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1188
{
1189
switch (item->type) {
1190
case XML_SCHEMA_TYPE_BASIC:
1191
if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1192
return(BAD_CAST "complex type definition");
1193
else
1194
return(BAD_CAST "simple type definition");
1195
default:
1196
return(xmlSchemaItemTypeToStr(item->type));
1197
}
1198
}
1199
1200
/**
1201
* xmlSchemaGetComponentNode:
1202
* @item: a schema component
1203
*
1204
* Returns node associated with the schema component.
1205
* NOTE that such a node need not be available; plus, a component's
1206
* node need not to reflect the component directly, since there is no
1207
* one-to-one relationship between the XML Schema representation and
1208
* the component representation.
1209
*/
1210
static xmlNodePtr
1211
xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1212
{
1213
switch (item->type) {
1214
case XML_SCHEMA_TYPE_ELEMENT:
1215
return (((xmlSchemaElementPtr) item)->node);
1216
case XML_SCHEMA_TYPE_ATTRIBUTE:
1217
return (((xmlSchemaAttributePtr) item)->node);
1218
case XML_SCHEMA_TYPE_COMPLEX:
1219
case XML_SCHEMA_TYPE_SIMPLE:
1220
return (((xmlSchemaTypePtr) item)->node);
1221
case XML_SCHEMA_TYPE_ANY:
1222
case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1223
return (((xmlSchemaWildcardPtr) item)->node);
1224
case XML_SCHEMA_TYPE_PARTICLE:
1225
return (((xmlSchemaParticlePtr) item)->node);
1226
case XML_SCHEMA_TYPE_SEQUENCE:
1227
case XML_SCHEMA_TYPE_CHOICE:
1228
case XML_SCHEMA_TYPE_ALL:
1229
return (((xmlSchemaModelGroupPtr) item)->node);
1230
case XML_SCHEMA_TYPE_GROUP:
1231
return (((xmlSchemaModelGroupDefPtr) item)->node);
1232
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1233
return (((xmlSchemaAttributeGroupPtr) item)->node);
1234
case XML_SCHEMA_TYPE_IDC_UNIQUE:
1235
case XML_SCHEMA_TYPE_IDC_KEY:
1236
case XML_SCHEMA_TYPE_IDC_KEYREF:
1237
return (((xmlSchemaIDCPtr) item)->node);
1238
case XML_SCHEMA_EXTRA_QNAMEREF:
1239
return(((xmlSchemaQNameRefPtr) item)->node);
1240
/* TODO: What to do with NOTATIONs?
1241
case XML_SCHEMA_TYPE_NOTATION:
1242
return (((xmlSchemaNotationPtr) item)->node);
1243
*/
1244
case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1245
return (((xmlSchemaAttributeUsePtr) item)->node);
1246
default:
1247
return (NULL);
1248
}
1249
}
1250
1251
#if 0
1252
/**
1253
* xmlSchemaGetNextComponent:
1254
* @item: a schema component
1255
*
1256
* Returns the next sibling of the schema component.
1257
*/
1258
static xmlSchemaBasicItemPtr
1259
xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1260
{
1261
switch (item->type) {
1262
case XML_SCHEMA_TYPE_ELEMENT:
1263
return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1264
case XML_SCHEMA_TYPE_ATTRIBUTE:
1265
return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1266
case XML_SCHEMA_TYPE_COMPLEX:
1267
case XML_SCHEMA_TYPE_SIMPLE:
1268
return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1269
case XML_SCHEMA_TYPE_ANY:
1270
case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1271
return (NULL);
1272
case XML_SCHEMA_TYPE_PARTICLE:
1273
return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1274
case XML_SCHEMA_TYPE_SEQUENCE:
1275
case XML_SCHEMA_TYPE_CHOICE:
1276
case XML_SCHEMA_TYPE_ALL:
1277
return (NULL);
1278
case XML_SCHEMA_TYPE_GROUP:
1279
return (NULL);
1280
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1281
return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1282
case XML_SCHEMA_TYPE_IDC_UNIQUE:
1283
case XML_SCHEMA_TYPE_IDC_KEY:
1284
case XML_SCHEMA_TYPE_IDC_KEYREF:
1285
return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1286
default:
1287
return (NULL);
1288
}
1289
}
1290
#endif
1291
1292
1293
/**
1294
* xmlSchemaFormatQName:
1295
* @buf: the string buffer
1296
* @namespaceName: the namespace name
1297
* @localName: the local name
1298
*
1299
* Returns the given QName in the format "{namespaceName}localName" or
1300
* just "localName" if @namespaceName is NULL.
1301
*
1302
* Returns the localName if @namespaceName is NULL, a formatted
1303
* string otherwise.
1304
*/
1305
static const xmlChar*
1306
xmlSchemaFormatQName(xmlChar **buf,
1307
const xmlChar *namespaceName,
1308
const xmlChar *localName)
1309
{
1310
FREE_AND_NULL(*buf)
1311
if (namespaceName != NULL) {
1312
*buf = xmlStrdup(BAD_CAST "{");
1313
*buf = xmlStrcat(*buf, namespaceName);
1314
*buf = xmlStrcat(*buf, BAD_CAST "}");
1315
}
1316
if (localName != NULL) {
1317
if (namespaceName == NULL)
1318
return(localName);
1319
*buf = xmlStrcat(*buf, localName);
1320
} else {
1321
*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1322
}
1323
return ((const xmlChar *) *buf);
1324
}
1325
1326
static const xmlChar*
1327
xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1328
{
1329
if (ns != NULL)
1330
return (xmlSchemaFormatQName(buf, ns->href, localName));
1331
else
1332
return (xmlSchemaFormatQName(buf, NULL, localName));
1333
}
1334
1335
static const xmlChar *
1336
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1337
{
1338
if (item == NULL) {
1339
return (NULL);
1340
}
1341
switch (item->type) {
1342
case XML_SCHEMA_TYPE_ELEMENT:
1343
return (((xmlSchemaElementPtr) item)->name);
1344
case XML_SCHEMA_TYPE_ATTRIBUTE:
1345
return (((xmlSchemaAttributePtr) item)->name);
1346
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1347
return (((xmlSchemaAttributeGroupPtr) item)->name);
1348
case XML_SCHEMA_TYPE_BASIC:
1349
case XML_SCHEMA_TYPE_SIMPLE:
1350
case XML_SCHEMA_TYPE_COMPLEX:
1351
return (((xmlSchemaTypePtr) item)->name);
1352
case XML_SCHEMA_TYPE_GROUP:
1353
return (((xmlSchemaModelGroupDefPtr) item)->name);
1354
case XML_SCHEMA_TYPE_IDC_KEY:
1355
case XML_SCHEMA_TYPE_IDC_UNIQUE:
1356
case XML_SCHEMA_TYPE_IDC_KEYREF:
1357
return (((xmlSchemaIDCPtr) item)->name);
1358
case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1359
if (WXS_ATTRUSE_DECL(item) != NULL) {
1360
return(xmlSchemaGetComponentName(
1361
WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1362
} else
1363
return(NULL);
1364
case XML_SCHEMA_EXTRA_QNAMEREF:
1365
return (((xmlSchemaQNameRefPtr) item)->name);
1366
case XML_SCHEMA_TYPE_NOTATION:
1367
return (((xmlSchemaNotationPtr) item)->name);
1368
default:
1369
/*
1370
* Other components cannot have names.
1371
*/
1372
break;
1373
}
1374
return (NULL);
1375
}
1376
1377
#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1378
#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1379
/*
1380
static const xmlChar *
1381
xmlSchemaGetQNameRefName(void *ref)
1382
{
1383
return(((xmlSchemaQNameRefPtr) ref)->name);
1384
}
1385
1386
static const xmlChar *
1387
xmlSchemaGetQNameRefTargetNs(void *ref)
1388
{
1389
return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1390
}
1391
*/
1392
1393
static const xmlChar *
1394
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1395
{
1396
if (item == NULL) {
1397
return (NULL);
1398
}
1399
switch (item->type) {
1400
case XML_SCHEMA_TYPE_ELEMENT:
1401
return (((xmlSchemaElementPtr) item)->targetNamespace);
1402
case XML_SCHEMA_TYPE_ATTRIBUTE:
1403
return (((xmlSchemaAttributePtr) item)->targetNamespace);
1404
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1405
return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1406
case XML_SCHEMA_TYPE_BASIC:
1407
return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1408
case XML_SCHEMA_TYPE_SIMPLE:
1409
case XML_SCHEMA_TYPE_COMPLEX:
1410
return (((xmlSchemaTypePtr) item)->targetNamespace);
1411
case XML_SCHEMA_TYPE_GROUP:
1412
return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1413
case XML_SCHEMA_TYPE_IDC_KEY:
1414
case XML_SCHEMA_TYPE_IDC_UNIQUE:
1415
case XML_SCHEMA_TYPE_IDC_KEYREF:
1416
return (((xmlSchemaIDCPtr) item)->targetNamespace);
1417
case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1418
if (WXS_ATTRUSE_DECL(item) != NULL) {
1419
return(xmlSchemaGetComponentTargetNs(
1420
WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1421
}
1422
/* TODO: Will returning NULL break something? */
1423
break;
1424
case XML_SCHEMA_EXTRA_QNAMEREF:
1425
return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1426
case XML_SCHEMA_TYPE_NOTATION:
1427
return (((xmlSchemaNotationPtr) item)->targetNamespace);
1428
default:
1429
/*
1430
* Other components cannot have names.
1431
*/
1432
break;
1433
}
1434
return (NULL);
1435
}
1436
1437
static const xmlChar*
1438
xmlSchemaGetComponentQName(xmlChar **buf,
1439
void *item)
1440
{
1441
return (xmlSchemaFormatQName(buf,
1442
xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1443
xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1444
}
1445
1446
static const xmlChar*
1447
xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1448
{
1449
xmlChar *str = NULL;
1450
1451
*buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1452
*buf = xmlStrcat(*buf, BAD_CAST " '");
1453
*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1454
(xmlSchemaBasicItemPtr) item));
1455
*buf = xmlStrcat(*buf, BAD_CAST "'");
1456
FREE_AND_NULL(str);
1457
return(*buf);
1458
}
1459
1460
static const xmlChar*
1461
xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1462
{
1463
return(xmlSchemaGetComponentDesignation(buf, idc));
1464
}
1465
1466
/**
1467
* xmlSchemaWildcardPCToString:
1468
* @pc: the type of processContents
1469
*
1470
* Returns a string representation of the type of
1471
* processContents.
1472
*/
1473
static const xmlChar *
1474
xmlSchemaWildcardPCToString(int pc)
1475
{
1476
switch (pc) {
1477
case XML_SCHEMAS_ANY_SKIP:
1478
return (BAD_CAST "skip");
1479
case XML_SCHEMAS_ANY_LAX:
1480
return (BAD_CAST "lax");
1481
case XML_SCHEMAS_ANY_STRICT:
1482
return (BAD_CAST "strict");
1483
default:
1484
return (BAD_CAST "invalid process contents");
1485
}
1486
}
1487
1488
/**
1489
* xmlSchemaGetCanonValueWhtspExt:
1490
* @val: the precomputed value
1491
* @retValue: the returned value
1492
* @ws: the whitespace type of the value
1493
* @for_hash: non-zero if this is supposed to generate a string for hashing
1494
*
1495
* Get a the canonical representation of the value.
1496
* The caller has to free the returned retValue.
1497
*
1498
* Returns 0 if the value could be built and -1 in case of
1499
* API errors or if the value type is not supported yet.
1500
*/
1501
static int
1502
xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
1503
xmlSchemaWhitespaceValueType ws,
1504
xmlChar **retValue,
1505
int for_hash)
1506
{
1507
int list;
1508
xmlSchemaValType valType;
1509
const xmlChar *value, *value2 = NULL;
1510
1511
1512
if ((retValue == NULL) || (val == NULL))
1513
return (-1);
1514
list = xmlSchemaValueGetNext(val) ? 1 : 0;
1515
*retValue = NULL;
1516
do {
1517
value = NULL;
1518
valType = xmlSchemaGetValType(val);
1519
switch (valType) {
1520
case XML_SCHEMAS_STRING:
1521
case XML_SCHEMAS_NORMSTRING:
1522
case XML_SCHEMAS_ANYSIMPLETYPE:
1523
value = xmlSchemaValueGetAsString(val);
1524
if (value != NULL) {
1525
if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1526
value2 = xmlSchemaCollapseString(value);
1527
else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1528
value2 = xmlSchemaWhiteSpaceReplace(value);
1529
if (value2 != NULL)
1530
value = value2;
1531
}
1532
break;
1533
default:
1534
if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1535
if (value2 != NULL)
1536
xmlFree((xmlChar *) value2);
1537
goto internal_error;
1538
}
1539
if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
1540
/* We can mostly use the canonical value for hashing,
1541
except in the case of decimal. There the canonical
1542
representation requires a trailing '.0' even for
1543
non-fractional numbers, but for the derived integer
1544
types it forbids any decimal point. Nevertheless they
1545
compare equal if the value is equal. We need to generate
1546
the same hash value for this to work, and it's easiest
1547
to just cut off the useless '.0' suffix for the
1548
decimal type. */
1549
int len = xmlStrlen(value2);
1550
if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
1551
((xmlChar*)value2)[len-2] = 0;
1552
}
1553
value = value2;
1554
}
1555
if (*retValue == NULL)
1556
if (value == NULL) {
1557
if (! list)
1558
*retValue = xmlStrdup(BAD_CAST "");
1559
} else
1560
*retValue = xmlStrdup(value);
1561
else if (value != NULL) {
1562
/* List. */
1563
*retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1564
*retValue = xmlStrcat((xmlChar *) *retValue, value);
1565
}
1566
FREE_AND_NULL(value2)
1567
val = xmlSchemaValueGetNext(val);
1568
} while (val != NULL);
1569
1570
return (0);
1571
internal_error:
1572
if (*retValue != NULL)
1573
xmlFree((xmlChar *) (*retValue));
1574
if (value2 != NULL)
1575
xmlFree((xmlChar *) value2);
1576
return (-1);
1577
}
1578
1579
static int
1580
xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1581
xmlSchemaWhitespaceValueType ws,
1582
xmlChar **retValue)
1583
{
1584
return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
1585
}
1586
1587
static int
1588
xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
1589
xmlChar **retValue)
1590
{
1591
return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
1592
retValue, 1);
1593
}
1594
1595
/**
1596
* xmlSchemaFormatItemForReport:
1597
* @buf: the string buffer
1598
* @itemDes: the designation of the item
1599
* @itemName: the name of the item
1600
* @item: the item as an object
1601
* @itemNode: the node of the item
1602
* @local: the local name
1603
* @parsing: if the function is used during the parse
1604
*
1605
* Returns a representation of the given item used
1606
* for error reports.
1607
*
1608
* The following order is used to build the resulting
1609
* designation if the arguments are not NULL:
1610
* 1a. If itemDes not NULL -> itemDes
1611
* 1b. If (itemDes not NULL) and (itemName not NULL)
1612
* -> itemDes + itemName
1613
* 2. If the preceding was NULL and (item not NULL) -> item
1614
* 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1615
*
1616
* If the itemNode is an attribute node, the name of the attribute
1617
* will be appended to the result.
1618
*
1619
* Returns the formatted string and sets @buf to the resulting value.
1620
*/
1621
static xmlChar*
1622
xmlSchemaFormatItemForReport(xmlChar **buf,
1623
const xmlChar *itemDes,
1624
xmlSchemaBasicItemPtr item,
1625
xmlNodePtr itemNode)
1626
{
1627
xmlChar *str = NULL;
1628
int named = 1;
1629
1630
if (*buf != NULL) {
1631
xmlFree(*buf);
1632
*buf = NULL;
1633
}
1634
1635
if (itemDes != NULL) {
1636
*buf = xmlStrdup(itemDes);
1637
} else if (item != NULL) {
1638
switch (item->type) {
1639
case XML_SCHEMA_TYPE_BASIC: {
1640
xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1641
1642
if (WXS_IS_ATOMIC(type))
1643
*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1644
else if (WXS_IS_LIST(type))
1645
*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1646
else if (WXS_IS_UNION(type))
1647
*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1648
else
1649
*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1650
*buf = xmlStrcat(*buf, type->name);
1651
*buf = xmlStrcat(*buf, BAD_CAST "'");
1652
}
1653
break;
1654
case XML_SCHEMA_TYPE_SIMPLE: {
1655
xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1656
1657
if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1658
*buf = xmlStrdup(BAD_CAST"");
1659
} else {
1660
*buf = xmlStrdup(BAD_CAST "local ");
1661
}
1662
if (WXS_IS_ATOMIC(type))
1663
*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1664
else if (WXS_IS_LIST(type))
1665
*buf = xmlStrcat(*buf, BAD_CAST "list type");
1666
else if (WXS_IS_UNION(type))
1667
*buf = xmlStrcat(*buf, BAD_CAST "union type");
1668
else
1669
*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1670
if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1671
*buf = xmlStrcat(*buf, BAD_CAST " '");
1672
*buf = xmlStrcat(*buf, type->name);
1673
*buf = xmlStrcat(*buf, BAD_CAST "'");
1674
}
1675
}
1676
break;
1677
case XML_SCHEMA_TYPE_COMPLEX: {
1678
xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1679
1680
if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1681
*buf = xmlStrdup(BAD_CAST "");
1682
else
1683
*buf = xmlStrdup(BAD_CAST "local ");
1684
*buf = xmlStrcat(*buf, BAD_CAST "complex type");
1685
if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1686
*buf = xmlStrcat(*buf, BAD_CAST " '");
1687
*buf = xmlStrcat(*buf, type->name);
1688
*buf = xmlStrcat(*buf, BAD_CAST "'");
1689
}
1690
}
1691
break;
1692
case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1693
xmlSchemaAttributeUsePtr ause;
1694
1695
ause = WXS_ATTR_USE_CAST item;
1696
*buf = xmlStrdup(BAD_CAST "attribute use ");
1697
if (WXS_ATTRUSE_DECL(ause) != NULL) {
1698
*buf = xmlStrcat(*buf, BAD_CAST "'");
1699
*buf = xmlStrcat(*buf,
1700
xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1701
FREE_AND_NULL(str)
1702
*buf = xmlStrcat(*buf, BAD_CAST "'");
1703
} else {
1704
*buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1705
}
1706
}
1707
break;
1708
case XML_SCHEMA_TYPE_ATTRIBUTE: {
1709
xmlSchemaAttributePtr attr;
1710
1711
attr = (xmlSchemaAttributePtr) item;
1712
*buf = xmlStrdup(BAD_CAST "attribute decl.");
1713
*buf = xmlStrcat(*buf, BAD_CAST " '");
1714
*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1715
attr->targetNamespace, attr->name));
1716
FREE_AND_NULL(str)
1717
*buf = xmlStrcat(*buf, BAD_CAST "'");
1718
}
1719
break;
1720
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1721
xmlSchemaGetComponentDesignation(buf, item);
1722
break;
1723
case XML_SCHEMA_TYPE_ELEMENT: {
1724
xmlSchemaElementPtr elem;
1725
1726
elem = (xmlSchemaElementPtr) item;
1727
*buf = xmlStrdup(BAD_CAST "element decl.");
1728
*buf = xmlStrcat(*buf, BAD_CAST " '");
1729
*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1730
elem->targetNamespace, elem->name));
1731
*buf = xmlStrcat(*buf, BAD_CAST "'");
1732
}
1733
break;
1734
case XML_SCHEMA_TYPE_IDC_UNIQUE:
1735
case XML_SCHEMA_TYPE_IDC_KEY:
1736
case XML_SCHEMA_TYPE_IDC_KEYREF:
1737
if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1738
*buf = xmlStrdup(BAD_CAST "unique '");
1739
else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1740
*buf = xmlStrdup(BAD_CAST "key '");
1741
else
1742
*buf = xmlStrdup(BAD_CAST "keyRef '");
1743
*buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1744
*buf = xmlStrcat(*buf, BAD_CAST "'");
1745
break;
1746
case XML_SCHEMA_TYPE_ANY:
1747
case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1748
*buf = xmlStrdup(xmlSchemaWildcardPCToString(
1749
((xmlSchemaWildcardPtr) item)->processContents));
1750
*buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1751
break;
1752
case XML_SCHEMA_FACET_MININCLUSIVE:
1753
case XML_SCHEMA_FACET_MINEXCLUSIVE:
1754
case XML_SCHEMA_FACET_MAXINCLUSIVE:
1755
case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1756
case XML_SCHEMA_FACET_TOTALDIGITS:
1757
case XML_SCHEMA_FACET_FRACTIONDIGITS:
1758
case XML_SCHEMA_FACET_PATTERN:
1759
case XML_SCHEMA_FACET_ENUMERATION:
1760
case XML_SCHEMA_FACET_WHITESPACE:
1761
case XML_SCHEMA_FACET_LENGTH:
1762
case XML_SCHEMA_FACET_MAXLENGTH:
1763
case XML_SCHEMA_FACET_MINLENGTH:
1764
*buf = xmlStrdup(BAD_CAST "facet '");
1765
*buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1766
*buf = xmlStrcat(*buf, BAD_CAST "'");
1767
break;
1768
case XML_SCHEMA_TYPE_GROUP: {
1769
*buf = xmlStrdup(BAD_CAST "model group def.");
1770
*buf = xmlStrcat(*buf, BAD_CAST " '");
1771
*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1772
*buf = xmlStrcat(*buf, BAD_CAST "'");
1773
FREE_AND_NULL(str)
1774
}
1775
break;
1776
case XML_SCHEMA_TYPE_SEQUENCE:
1777
case XML_SCHEMA_TYPE_CHOICE:
1778
case XML_SCHEMA_TYPE_ALL:
1779
case XML_SCHEMA_TYPE_PARTICLE:
1780
*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1781
break;
1782
case XML_SCHEMA_TYPE_NOTATION: {
1783
*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1784
*buf = xmlStrcat(*buf, BAD_CAST " '");
1785
*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1786
*buf = xmlStrcat(*buf, BAD_CAST "'");
1787
FREE_AND_NULL(str);
1788
}
1789
/* Falls through. */
1790
default:
1791
named = 0;
1792
}
1793
} else
1794
named = 0;
1795
1796
if ((named == 0) && (itemNode != NULL)) {
1797
xmlNodePtr elem;
1798
1799
if (itemNode->type == XML_ATTRIBUTE_NODE)
1800
elem = itemNode->parent;
1801
else
1802
elem = itemNode;
1803
*buf = xmlStrdup(BAD_CAST "Element '");
1804
if (elem->ns != NULL) {
1805
*buf = xmlStrcat(*buf,
1806
xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1807
FREE_AND_NULL(str)
1808
} else
1809
*buf = xmlStrcat(*buf, elem->name);
1810
*buf = xmlStrcat(*buf, BAD_CAST "'");
1811
1812
}
1813
if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1814
*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1815
if (itemNode->ns != NULL) {
1816
*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1817
itemNode->ns->href, itemNode->name));
1818
FREE_AND_NULL(str)
1819
} else
1820
*buf = xmlStrcat(*buf, itemNode->name);
1821
*buf = xmlStrcat(*buf, BAD_CAST "'");
1822
}
1823
FREE_AND_NULL(str)
1824
1825
return (xmlEscapeFormatString(buf));
1826
}
1827
1828
/**
1829
* xmlSchemaFormatFacetEnumSet:
1830
* @buf: the string buffer
1831
* @type: the type holding the enumeration facets
1832
*
1833
* Builds a string consisting of all enumeration elements.
1834
*
1835
* Returns a string of all enumeration elements.
1836
*/
1837
static const xmlChar *
1838
xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1839
xmlChar **buf, xmlSchemaTypePtr type)
1840
{
1841
xmlSchemaFacetPtr facet;
1842
xmlSchemaWhitespaceValueType ws;
1843
xmlChar *value = NULL;
1844
int res, found = 0;
1845
1846
if (*buf != NULL)
1847
xmlFree(*buf);
1848
*buf = NULL;
1849
1850
do {
1851
/*
1852
* Use the whitespace type of the base type.
1853
*/
1854
ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1855
for (facet = type->facets; facet != NULL; facet = facet->next) {
1856
if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1857
continue;
1858
found = 1;
1859
res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1860
ws, &value);
1861
if (res == -1) {
1862
xmlSchemaInternalErr(actxt,
1863
"xmlSchemaFormatFacetEnumSet",
1864
"compute the canonical lexical representation");
1865
if (*buf != NULL)
1866
xmlFree(*buf);
1867
*buf = NULL;
1868
return (NULL);
1869
}
1870
if (*buf == NULL)
1871
*buf = xmlStrdup(BAD_CAST "'");
1872
else
1873
*buf = xmlStrcat(*buf, BAD_CAST ", '");
1874
*buf = xmlStrcat(*buf, BAD_CAST value);
1875
*buf = xmlStrcat(*buf, BAD_CAST "'");
1876
if (value != NULL) {
1877
xmlFree((xmlChar *)value);
1878
value = NULL;
1879
}
1880
}
1881
/*
1882
* The enumeration facet of a type restricts the enumeration
1883
* facet of the ancestor type; i.e., such restricted enumerations
1884
* do not belong to the set of the given type. Thus we break
1885
* on the first found enumeration.
1886
*/
1887
if (found)
1888
break;
1889
type = type->baseType;
1890
} while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1891
1892
return ((const xmlChar *) *buf);
1893
}
1894
1895
/************************************************************************
1896
* *
1897
* Error functions *
1898
* *
1899
************************************************************************/
1900
1901
#if 0
1902
static void
1903
xmlSchemaErrMemory(const char *msg)
1904
{
1905
__xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1906
msg);
1907
}
1908
#endif
1909
1910
static void
1911
xmlSchemaPSimpleErr(const char *msg)
1912
{
1913
__xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1914
msg);
1915
}
1916
1917
/**
1918
* xmlSchemaPErrMemory:
1919
* @node: a context node
1920
* @extra: extra information
1921
*
1922
* Handle an out of memory condition
1923
*/
1924
static void
1925
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1926
const char *extra, xmlNodePtr node)
1927
{
1928
if (ctxt != NULL)
1929
ctxt->nberrors++;
1930
__xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1931
extra);
1932
}
1933
1934
/**
1935
* xmlSchemaPErr:
1936
* @ctxt: the parsing context
1937
* @node: the context node
1938
* @error: the error code
1939
* @msg: the error message
1940
* @str1: extra data
1941
* @str2: extra data
1942
*
1943
* Handle a parser error
1944
*/
1945
static void LIBXML_ATTR_FORMAT(4,0)
1946
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1947
const char *msg, const xmlChar * str1, const xmlChar * str2)
1948
{
1949
xmlGenericErrorFunc channel = NULL;
1950
xmlStructuredErrorFunc schannel = NULL;
1951
void *data = NULL;
1952
1953
if (ctxt != NULL) {
1954
ctxt->nberrors++;
1955
ctxt->err = error;
1956
channel = ctxt->error;
1957
data = ctxt->errCtxt;
1958
schannel = ctxt->serror;
1959
}
1960
__xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1961
error, XML_ERR_ERROR, NULL, 0,
1962
(const char *) str1, (const char *) str2, NULL, 0, 0,
1963
msg, str1, str2);
1964
}
1965
1966
/**
1967
* xmlSchemaPErr2:
1968
* @ctxt: the parsing context
1969
* @node: the context node
1970
* @node: the current child
1971
* @error: the error code
1972
* @msg: the error message
1973
* @str1: extra data
1974
* @str2: extra data
1975
*
1976
* Handle a parser error
1977
*/
1978
static void LIBXML_ATTR_FORMAT(5,0)
1979
xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1980
xmlNodePtr child, int error,
1981
const char *msg, const xmlChar * str1, const xmlChar * str2)
1982
{
1983
if (child != NULL)
1984
xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1985
else
1986
xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1987
}
1988
1989
1990
/**
1991
* xmlSchemaPErrExt:
1992
* @ctxt: the parsing context
1993
* @node: the context node
1994
* @error: the error code
1995
* @strData1: extra data
1996
* @strData2: extra data
1997
* @strData3: extra data
1998
* @msg: the message
1999
* @str1: extra parameter for the message display
2000
* @str2: extra parameter for the message display
2001
* @str3: extra parameter for the message display
2002
* @str4: extra parameter for the message display
2003
* @str5: extra parameter for the message display
2004
*
2005
* Handle a parser error
2006
*/
2007
static void LIBXML_ATTR_FORMAT(7,0)
2008
xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
2009
const xmlChar * strData1, const xmlChar * strData2,
2010
const xmlChar * strData3, const char *msg, const xmlChar * str1,
2011
const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
2012
const xmlChar * str5)
2013
{
2014
2015
xmlGenericErrorFunc channel = NULL;
2016
xmlStructuredErrorFunc schannel = NULL;
2017
void *data = NULL;
2018
2019
if (ctxt != NULL) {
2020
ctxt->nberrors++;
2021
ctxt->err = error;
2022
channel = ctxt->error;
2023
data = ctxt->errCtxt;
2024
schannel = ctxt->serror;
2025
}
2026
__xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
2027
error, XML_ERR_ERROR, NULL, 0,
2028
(const char *) strData1, (const char *) strData2,
2029
(const char *) strData3, 0, 0, msg, str1, str2,
2030
str3, str4, str5);
2031
}
2032
2033
/************************************************************************
2034
* *
2035
* Allround error functions *
2036
* *
2037
************************************************************************/
2038
2039
/**
2040
* xmlSchemaVTypeErrMemory:
2041
* @node: a context node
2042
* @extra: extra information
2043
*
2044
* Handle an out of memory condition
2045
*/
2046
static void
2047
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2048
const char *extra, xmlNodePtr node)
2049
{
2050
if (ctxt != NULL) {
2051
ctxt->nberrors++;
2052
ctxt->err = XML_SCHEMAV_INTERNAL;
2053
}
2054
__xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2055
extra);
2056
}
2057
2058
static void LIBXML_ATTR_FORMAT(2,0)
2059
xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2060
const char *msg, const xmlChar *str)
2061
{
2062
__xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2063
msg, (const char *) str);
2064
}
2065
2066
#define WXS_ERROR_TYPE_ERROR 1
2067
#define WXS_ERROR_TYPE_WARNING 2
2068
/**
2069
* xmlSchemaErr4Line:
2070
* @ctxt: the validation context
2071
* @errorLevel: the error level
2072
* @error: the error code
2073
* @node: the context node
2074
* @line: the line number
2075
* @msg: the error message
2076
* @str1: extra data
2077
* @str2: extra data
2078
* @str3: extra data
2079
* @str4: extra data
2080
*
2081
* Handle a validation error
2082
*/
2083
static void LIBXML_ATTR_FORMAT(6,0)
2084
xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2085
xmlErrorLevel errorLevel,
2086
int error, xmlNodePtr node, int line, const char *msg,
2087
const xmlChar *str1, const xmlChar *str2,
2088
const xmlChar *str3, const xmlChar *str4)
2089
{
2090
xmlStructuredErrorFunc schannel = NULL;
2091
xmlGenericErrorFunc channel = NULL;
2092
void *data = NULL;
2093
2094
if (ctxt != NULL) {
2095
if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2096
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2097
const char *file = NULL;
2098
int col = 0;
2099
if (errorLevel != XML_ERR_WARNING) {
2100
vctxt->nberrors++;
2101
vctxt->err = error;
2102
channel = vctxt->error;
2103
} else {
2104
channel = vctxt->warning;
2105
}
2106
schannel = vctxt->serror;
2107
data = vctxt->errCtxt;
2108
2109
/*
2110
* Error node. If we specify a line number, then
2111
* do not channel any node to the error function.
2112
*/
2113
if (line == 0) {
2114
if ((node == NULL) &&
2115
(vctxt->depth >= 0) &&
2116
(vctxt->inode != NULL)) {
2117
node = vctxt->inode->node;
2118
}
2119
/*
2120
* Get filename and line if no node-tree.
2121
*/
2122
if ((node == NULL) &&
2123
(vctxt->parserCtxt != NULL) &&
2124
(vctxt->parserCtxt->input != NULL)) {
2125
file = vctxt->parserCtxt->input->filename;
2126
if (vctxt->inode != NULL) {
2127
line = vctxt->inode->nodeLine;
2128
col = 0;
2129
} else {
2130
/* This is inaccurate. */
2131
line = vctxt->parserCtxt->input->line;
2132
col = vctxt->parserCtxt->input->col;
2133
}
2134
}
2135
} else {
2136
/*
2137
* Override the given node's (if any) position
2138
* and channel only the given line number.
2139
*/
2140
node = NULL;
2141
/*
2142
* Get filename.
2143
*/
2144
if (vctxt->doc != NULL)
2145
file = (const char *) vctxt->doc->URL;
2146
else if ((vctxt->parserCtxt != NULL) &&
2147
(vctxt->parserCtxt->input != NULL))
2148
file = vctxt->parserCtxt->input->filename;
2149
}
2150
if (vctxt->locFunc != NULL) {
2151
if ((file == NULL) || (line == 0)) {
2152
unsigned long l;
2153
const char *f;
2154
vctxt->locFunc(vctxt->locCtxt, &f, &l);
2155
if (file == NULL)
2156
file = f;
2157
if (line == 0)
2158
line = (int) l;
2159
}
2160
}
2161
if ((file == NULL) && (vctxt->filename != NULL))
2162
file = vctxt->filename;
2163
2164
__xmlRaiseError(schannel, channel, data, ctxt,
2165
node, XML_FROM_SCHEMASV,
2166
error, errorLevel, file, line,
2167
(const char *) str1, (const char *) str2,
2168
(const char *) str3, 0, col, msg, str1, str2, str3, str4);
2169
2170
} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2171
xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2172
if (errorLevel != XML_ERR_WARNING) {
2173
pctxt->nberrors++;
2174
pctxt->err = error;
2175
channel = pctxt->error;
2176
} else {
2177
channel = pctxt->warning;
2178
}
2179
schannel = pctxt->serror;
2180
data = pctxt->errCtxt;
2181
__xmlRaiseError(schannel, channel, data, ctxt,
2182
node, XML_FROM_SCHEMASP, error,
2183
errorLevel, NULL, 0,
2184
(const char *) str1, (const char *) str2,
2185
(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2186
} else {
2187
TODO
2188
}
2189
}
2190
}
2191
2192
/**
2193
* xmlSchemaErr3:
2194
* @ctxt: the validation context
2195
* @node: the context node
2196
* @error: the error code
2197
* @msg: the error message
2198
* @str1: extra data
2199
* @str2: extra data
2200
* @str3: extra data
2201
*
2202
* Handle a validation error
2203
*/
2204
static void LIBXML_ATTR_FORMAT(4,0)
2205
xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2206
int error, xmlNodePtr node, const char *msg,
2207
const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2208
{
2209
xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2210
msg, str1, str2, str3, NULL);
2211
}
2212
2213
static void LIBXML_ATTR_FORMAT(4,0)
2214
xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2215
int error, xmlNodePtr node, const char *msg,
2216
const xmlChar *str1, const xmlChar *str2,
2217
const xmlChar *str3, const xmlChar *str4)
2218
{
2219
xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2220
msg, str1, str2, str3, str4);
2221
}
2222
2223
static void LIBXML_ATTR_FORMAT(4,0)
2224
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2225
int error, xmlNodePtr node, const char *msg,
2226
const xmlChar *str1, const xmlChar *str2)
2227
{
2228
xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2229
}
2230
2231
static xmlChar *
2232
xmlSchemaFormatNodeForError(xmlChar ** msg,
2233
xmlSchemaAbstractCtxtPtr actxt,
2234
xmlNodePtr node)
2235
{
2236
xmlChar *str = NULL;
2237
2238
*msg = NULL;
2239
if ((node != NULL) &&
2240
(node->type != XML_ELEMENT_NODE) &&
2241
(node->type != XML_ATTRIBUTE_NODE))
2242
{
2243
/*
2244
* Don't try to format other nodes than element and
2245
* attribute nodes.
2246
* Play safe and return an empty string.
2247
*/
2248
*msg = xmlStrdup(BAD_CAST "");
2249
return(*msg);
2250
}
2251
if (node != NULL) {
2252
/*
2253
* Work on tree nodes.
2254
*/
2255
if (node->type == XML_ATTRIBUTE_NODE) {
2256
xmlNodePtr elem = node->parent;
2257
2258
*msg = xmlStrdup(BAD_CAST "Element '");
2259
if (elem->ns != NULL)
2260
*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2261
elem->ns->href, elem->name));
2262
else
2263
*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2264
NULL, elem->name));
2265
FREE_AND_NULL(str);
2266
*msg = xmlStrcat(*msg, BAD_CAST "', ");
2267
*msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2268
} else {
2269
*msg = xmlStrdup(BAD_CAST "Element '");
2270
}
2271
if (node->ns != NULL)
2272
*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2273
node->ns->href, node->name));
2274
else
2275
*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2276
NULL, node->name));
2277
FREE_AND_NULL(str);
2278
*msg = xmlStrcat(*msg, BAD_CAST "': ");
2279
} else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2280
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2281
/*
2282
* Work on node infos.
2283
*/
2284
if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2285
xmlSchemaNodeInfoPtr ielem =
2286
vctxt->elemInfos[vctxt->depth];
2287
2288
*msg = xmlStrdup(BAD_CAST "Element '");
2289
*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2290
ielem->nsName, ielem->localName));
2291
FREE_AND_NULL(str);
2292
*msg = xmlStrcat(*msg, BAD_CAST "', ");
2293
*msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2294
} else {
2295
*msg = xmlStrdup(BAD_CAST "Element '");
2296
}
2297
*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2298
vctxt->inode->nsName, vctxt->inode->localName));
2299
FREE_AND_NULL(str);
2300
*msg = xmlStrcat(*msg, BAD_CAST "': ");
2301
} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2302
/*
2303
* Hmm, no node while parsing?
2304
* Return an empty string, in case NULL will break something.
2305
*/
2306
*msg = xmlStrdup(BAD_CAST "");
2307
} else {
2308
TODO
2309
return (NULL);
2310
}
2311
2312
/*
2313
* xmlSchemaFormatItemForReport() also returns an escaped format
2314
* string, so do this before calling it below (in the future).
2315
*/
2316
xmlEscapeFormatString(msg);
2317
2318
/*
2319
* VAL TODO: The output of the given schema component is currently
2320
* disabled.
2321
*/
2322
#if 0
2323
if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2324
*msg = xmlStrcat(*msg, BAD_CAST " [");
2325
*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2326
NULL, type, NULL, 0));
2327
FREE_AND_NULL(str)
2328
*msg = xmlStrcat(*msg, BAD_CAST "]");
2329
}
2330
#endif
2331
return (*msg);
2332
}
2333
2334
static void LIBXML_ATTR_FORMAT(3,0)
2335
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2336
const char *funcName,
2337
const char *message,
2338
const xmlChar *str1,
2339
const xmlChar *str2)
2340
{
2341
xmlChar *msg = NULL;
2342
2343
if (actxt == NULL)
2344
return;
2345
msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2346
msg = xmlStrcat(msg, BAD_CAST message);
2347
msg = xmlStrcat(msg, BAD_CAST ".\n");
2348
2349
if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2350
xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2351
(const char *) msg, (const xmlChar *) funcName, str1, str2);
2352
else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2353
xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2354
(const char *) msg, (const xmlChar *) funcName, str1, str2);
2355
2356
FREE_AND_NULL(msg)
2357
}
2358
2359
static void LIBXML_ATTR_FORMAT(3,0)
2360
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2361
const char *funcName,
2362
const char *message)
2363
{
2364
xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2365
}
2366
2367
#if 0
2368
static void LIBXML_ATTR_FORMAT(3,0)
2369
xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2370
const char *funcName,
2371
const char *message,
2372
const xmlChar *str1,
2373
const xmlChar *str2)
2374
{
2375
xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2376
str1, str2);
2377
}
2378
#endif
2379
2380
static void LIBXML_ATTR_FORMAT(5,0)
2381
xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2382
xmlParserErrors error,
2383
xmlNodePtr node,
2384
xmlSchemaBasicItemPtr item,
2385
const char *message,
2386
const xmlChar *str1, const xmlChar *str2,
2387
const xmlChar *str3, const xmlChar *str4)
2388
{
2389
xmlChar *msg = NULL;
2390
2391
if ((node == NULL) && (item != NULL) &&
2392
(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2393
node = WXS_ITEM_NODE(item);
2394
xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2395
msg = xmlStrcat(msg, BAD_CAST ": ");
2396
} else
2397
xmlSchemaFormatNodeForError(&msg, actxt, node);
2398
msg = xmlStrcat(msg, (const xmlChar *) message);
2399
msg = xmlStrcat(msg, BAD_CAST ".\n");
2400
xmlSchemaErr4(actxt, error, node,
2401
(const char *) msg, str1, str2, str3, str4);
2402
FREE_AND_NULL(msg)
2403
}
2404
2405
static void LIBXML_ATTR_FORMAT(5,0)
2406
xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2407
xmlParserErrors error,
2408
xmlNodePtr node,
2409
xmlSchemaBasicItemPtr item,
2410
const char *message,
2411
const xmlChar *str1,
2412
const xmlChar *str2)
2413
{
2414
xmlSchemaCustomErr4(actxt, error, node, item,
2415
message, str1, str2, NULL, NULL);
2416
}
2417
2418
2419
2420
static void LIBXML_ATTR_FORMAT(5,0)
2421
xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2422
xmlParserErrors error,
2423
xmlNodePtr node,
2424
xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2425
const char *message,
2426
const xmlChar *str1,
2427
const xmlChar *str2,
2428
const xmlChar *str3)
2429
{
2430
xmlChar *msg = NULL;
2431
2432
xmlSchemaFormatNodeForError(&msg, actxt, node);
2433
msg = xmlStrcat(msg, (const xmlChar *) message);
2434
msg = xmlStrcat(msg, BAD_CAST ".\n");
2435
2436
/* URGENT TODO: Set the error code to something sane. */
2437
xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2438
(const char *) msg, str1, str2, str3, NULL);
2439
2440
FREE_AND_NULL(msg)
2441
}
2442
2443
2444
2445
static void LIBXML_ATTR_FORMAT(5,0)
2446
xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2447
xmlParserErrors error,
2448
xmlSchemaPSVIIDCNodePtr idcNode,
2449
xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2450
const char *message,
2451
const xmlChar *str1,
2452
const xmlChar *str2)
2453
{
2454
xmlChar *msg = NULL, *qname = NULL;
2455
2456
msg = xmlStrdup(BAD_CAST "Element '%s': ");
2457
msg = xmlStrcat(msg, (const xmlChar *) message);
2458
msg = xmlStrcat(msg, BAD_CAST ".\n");
2459
xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2460
error, NULL, idcNode->nodeLine, (const char *) msg,
2461
xmlSchemaFormatQName(&qname,
2462
vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2463
vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2464
str1, str2, NULL);
2465
FREE_AND_NULL(qname);
2466
FREE_AND_NULL(msg);
2467
}
2468
2469
static int
2470
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2471
xmlNodePtr node)
2472
{
2473
if (node != NULL)
2474
return (node->type);
2475
if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2476
(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2477
return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2478
return (-1);
2479
}
2480
2481
static int
2482
xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2483
{
2484
switch (item->type) {
2485
case XML_SCHEMA_TYPE_COMPLEX:
2486
case XML_SCHEMA_TYPE_SIMPLE:
2487
if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2488
return(1);
2489
break;
2490
case XML_SCHEMA_TYPE_GROUP:
2491
return (1);
2492
case XML_SCHEMA_TYPE_ELEMENT:
2493
if ( ((xmlSchemaElementPtr) item)->flags &
2494
XML_SCHEMAS_ELEM_GLOBAL)
2495
return(1);
2496
break;
2497
case XML_SCHEMA_TYPE_ATTRIBUTE:
2498
if ( ((xmlSchemaAttributePtr) item)->flags &
2499
XML_SCHEMAS_ATTR_GLOBAL)
2500
return(1);
2501
break;
2502
/* Note that attribute groups are always global. */
2503
default:
2504
return(1);
2505
}
2506
return (0);
2507
}
2508
2509
static void
2510
xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2511
xmlParserErrors error,
2512
xmlNodePtr node,
2513
const xmlChar *value,
2514
xmlSchemaTypePtr type,
2515
int displayValue)
2516
{
2517
xmlChar *msg = NULL;
2518
2519
xmlSchemaFormatNodeForError(&msg, actxt, node);
2520
2521
if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2522
XML_ATTRIBUTE_NODE))
2523
msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2524
else
2525
msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2526
"value of ");
2527
2528
if (! xmlSchemaIsGlobalItem(type))
2529
msg = xmlStrcat(msg, BAD_CAST "the local ");
2530
else
2531
msg = xmlStrcat(msg, BAD_CAST "the ");
2532
2533
if (WXS_IS_ATOMIC(type))
2534
msg = xmlStrcat(msg, BAD_CAST "atomic type");
2535
else if (WXS_IS_LIST(type))
2536
msg = xmlStrcat(msg, BAD_CAST "list type");
2537
else if (WXS_IS_UNION(type))
2538
msg = xmlStrcat(msg, BAD_CAST "union type");
2539
2540
if (xmlSchemaIsGlobalItem(type)) {
2541
xmlChar *str = NULL;
2542
msg = xmlStrcat(msg, BAD_CAST " '");
2543
if (type->builtInType != 0) {
2544
msg = xmlStrcat(msg, BAD_CAST "xs:");
2545
str = xmlStrdup(type->name);
2546
} else {
2547
const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2548
if (!str)
2549
str = xmlStrdup(qName);
2550
}
2551
msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2552
msg = xmlStrcat(msg, BAD_CAST "'");
2553
FREE_AND_NULL(str);
2554
}
2555
msg = xmlStrcat(msg, BAD_CAST ".\n");
2556
if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2557
XML_ATTRIBUTE_NODE))
2558
xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2559
else
2560
xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2561
FREE_AND_NULL(msg)
2562
}
2563
2564
static const xmlChar *
2565
xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2566
xmlSchemaNodeInfoPtr ni,
2567
xmlNodePtr node)
2568
{
2569
if (node != NULL) {
2570
if (node->ns != NULL)
2571
return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2572
else
2573
return (xmlSchemaFormatQName(str, NULL, node->name));
2574
} else if (ni != NULL)
2575
return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2576
return (NULL);
2577
}
2578
2579
static void
2580
xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2581
xmlParserErrors error,
2582
xmlSchemaAttrInfoPtr ni,
2583
xmlNodePtr node)
2584
{
2585
xmlChar *msg = NULL, *str = NULL;
2586
2587
xmlSchemaFormatNodeForError(&msg, actxt, node);
2588
msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2589
xmlSchemaErr(actxt, error, node, (const char *) msg,
2590
xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2591
NULL);
2592
FREE_AND_NULL(str)
2593
FREE_AND_NULL(msg)
2594
}
2595
2596
static void LIBXML_ATTR_FORMAT(5,0)
2597
xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2598
xmlParserErrors error,
2599
xmlNodePtr node,
2600
xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2601
const char *message,
2602
int nbval,
2603
int nbneg,
2604
xmlChar **values)
2605
{
2606
xmlChar *str = NULL, *msg = NULL;
2607
xmlChar *localName, *nsName;
2608
const xmlChar *cur, *end;
2609
int i;
2610
2611
xmlSchemaFormatNodeForError(&msg, actxt, node);
2612
msg = xmlStrcat(msg, (const xmlChar *) message);
2613
msg = xmlStrcat(msg, BAD_CAST ".");
2614
/*
2615
* Note that is does not make sense to report that we have a
2616
* wildcard here, since the wildcard might be unfolded into
2617
* multiple transitions.
2618
*/
2619
if (nbval + nbneg > 0) {
2620
if (nbval + nbneg > 1) {
2621
str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2622
} else
2623
str = xmlStrdup(BAD_CAST " Expected is ( ");
2624
nsName = NULL;
2625
2626
for (i = 0; i < nbval + nbneg; i++) {
2627
cur = values[i];
2628
if (cur == NULL)
2629
continue;
2630
if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2631
(cur[3] == ' ')) {
2632
cur += 4;
2633
str = xmlStrcat(str, BAD_CAST "##other");
2634
}
2635
/*
2636
* Get the local name.
2637
*/
2638
localName = NULL;
2639
2640
end = cur;
2641
if (*end == '*') {
2642
localName = xmlStrdup(BAD_CAST "*");
2643
end++;
2644
} else {
2645
while ((*end != 0) && (*end != '|'))
2646
end++;
2647
localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2648
}
2649
if (*end != 0) {
2650
end++;
2651
/*
2652
* Skip "*|*" if they come with negated expressions, since
2653
* they represent the same negated wildcard.
2654
*/
2655
if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2656
/*
2657
* Get the namespace name.
2658
*/
2659
cur = end;
2660
if (*end == '*') {
2661
nsName = xmlStrdup(BAD_CAST "{*}");
2662
} else {
2663
while (*end != 0)
2664
end++;
2665
2666
if (i >= nbval)
2667
nsName = xmlStrdup(BAD_CAST "{##other:");
2668
else
2669
nsName = xmlStrdup(BAD_CAST "{");
2670
2671
nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2672
nsName = xmlStrcat(nsName, BAD_CAST "}");
2673
}
2674
str = xmlStrcat(str, BAD_CAST nsName);
2675
FREE_AND_NULL(nsName)
2676
} else {
2677
FREE_AND_NULL(localName);
2678
continue;
2679
}
2680
}
2681
str = xmlStrcat(str, BAD_CAST localName);
2682
FREE_AND_NULL(localName);
2683
2684
if (i < nbval + nbneg -1)
2685
str = xmlStrcat(str, BAD_CAST ", ");
2686
}
2687
str = xmlStrcat(str, BAD_CAST " ).\n");
2688
msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2689
FREE_AND_NULL(str)
2690
} else
2691
msg = xmlStrcat(msg, BAD_CAST "\n");
2692
xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2693
xmlFree(msg);
2694
}
2695
2696
static void LIBXML_ATTR_FORMAT(8,0)
2697
xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2698
xmlParserErrors error,
2699
xmlNodePtr node,
2700
const xmlChar *value,
2701
unsigned long length,
2702
xmlSchemaTypePtr type,
2703
xmlSchemaFacetPtr facet,
2704
const char *message,
2705
const xmlChar *str1,
2706
const xmlChar *str2)
2707
{
2708
xmlChar *str = NULL, *msg = NULL;
2709
xmlSchemaTypeType facetType;
2710
int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2711
2712
xmlSchemaFormatNodeForError(&msg, actxt, node);
2713
if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2714
facetType = XML_SCHEMA_FACET_ENUMERATION;
2715
/*
2716
* If enumerations are validated, one must not expect the
2717
* facet to be given.
2718
*/
2719
} else
2720
facetType = facet->type;
2721
msg = xmlStrcat(msg, BAD_CAST "[");
2722
msg = xmlStrcat(msg, BAD_CAST "facet '");
2723
msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2724
msg = xmlStrcat(msg, BAD_CAST "'] ");
2725
if (message == NULL) {
2726
/*
2727
* Use a default message.
2728
*/
2729
if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2730
(facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2731
(facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2732
2733
char len[25], actLen[25];
2734
2735
/* FIXME, TODO: What is the max expected string length of the
2736
* this value?
2737
*/
2738
if (nodeType == XML_ATTRIBUTE_NODE)
2739
msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2740
else
2741
msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2742
2743
snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2744
snprintf(actLen, 24, "%lu", length);
2745
2746
if (facetType == XML_SCHEMA_FACET_LENGTH)
2747
msg = xmlStrcat(msg,
2748
BAD_CAST "this differs from the allowed length of '%s'.\n");
2749
else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2750
msg = xmlStrcat(msg,
2751
BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2752
else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2753
msg = xmlStrcat(msg,
2754
BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2755
2756
if (nodeType == XML_ATTRIBUTE_NODE)
2757
xmlSchemaErr3(actxt, error, node, (const char *) msg,
2758
value, (const xmlChar *) actLen, (const xmlChar *) len);
2759
else
2760
xmlSchemaErr(actxt, error, node, (const char *) msg,
2761
(const xmlChar *) actLen, (const xmlChar *) len);
2762
2763
} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2764
msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2765
"of the set {%s}.\n");
2766
xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2767
xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2768
} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2769
msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2770
"by the pattern '%s'.\n");
2771
xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2772
facet->value);
2773
} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2774
msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2775
"minimum value allowed ('%s').\n");
2776
xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2777
facet->value);
2778
} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2779
msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2780
"maximum value allowed ('%s').\n");
2781
xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2782
facet->value);
2783
} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2784
msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2785
"'%s'.\n");
2786
xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2787
facet->value);
2788
} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2789
msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2790
"'%s'.\n");
2791
xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2792
facet->value);
2793
} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2794
msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2795
"digits than are allowed ('%s').\n");
2796
xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2797
facet->value);
2798
} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2799
msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2800
"digits than are allowed ('%s').\n");
2801
xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2802
facet->value);
2803
} else if (nodeType == XML_ATTRIBUTE_NODE) {
2804
msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2805
xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2806
} else {
2807
msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2808
xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2809
}
2810
} else {
2811
msg = xmlStrcat(msg, (const xmlChar *) message);
2812
msg = xmlStrcat(msg, BAD_CAST ".\n");
2813
xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2814
}
2815
FREE_AND_NULL(str)
2816
xmlFree(msg);
2817
}
2818
2819
#define VERROR(err, type, msg) \
2820
xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2821
2822
#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2823
2824
#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2825
#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2826
2827
#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2828
2829
2830
/**
2831
* xmlSchemaPMissingAttrErr:
2832
* @ctxt: the schema validation context
2833
* @ownerItem: the owner as a schema object
2834
* @ownerElem: the owner as an element node
2835
* @node: the parent element node of the missing attribute node
2836
* @type: the corresponding type of the attribute node
2837
*
2838
* Reports an illegal attribute.
2839
*/
2840
static void
2841
xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2842
xmlParserErrors error,
2843
xmlSchemaBasicItemPtr ownerItem,
2844
xmlNodePtr ownerElem,
2845
const char *name,
2846
const char *message)
2847
{
2848
xmlChar *des = NULL;
2849
2850
xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2851
2852
if (message != NULL)
2853
xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2854
else
2855
xmlSchemaPErr(ctxt, ownerElem, error,
2856
"%s: The attribute '%s' is required but missing.\n",
2857
BAD_CAST des, BAD_CAST name);
2858
FREE_AND_NULL(des);
2859
}
2860
2861
2862
/**
2863
* xmlSchemaPResCompAttrErr:
2864
* @ctxt: the schema validation context
2865
* @error: the error code
2866
* @ownerItem: the owner as a schema object
2867
* @ownerElem: the owner as an element node
2868
* @name: the name of the attribute holding the QName
2869
* @refName: the referenced local name
2870
* @refURI: the referenced namespace URI
2871
* @message: optional message
2872
*
2873
* Used to report QName attribute values that failed to resolve
2874
* to schema components.
2875
*/
2876
static void
2877
xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2878
xmlParserErrors error,
2879
xmlSchemaBasicItemPtr ownerItem,
2880
xmlNodePtr ownerElem,
2881
const char *name,
2882
const xmlChar *refName,
2883
const xmlChar *refURI,
2884
xmlSchemaTypeType refType,
2885
const char *refTypeStr)
2886
{
2887
xmlChar *des = NULL, *strA = NULL;
2888
2889
xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2890
if (refTypeStr == NULL)
2891
refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2892
xmlSchemaPErrExt(ctxt, ownerElem, error,
2893
NULL, NULL, NULL,
2894
"%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2895
"%s.\n", BAD_CAST des, BAD_CAST name,
2896
xmlSchemaFormatQName(&strA, refURI, refName),
2897
BAD_CAST refTypeStr, NULL);
2898
FREE_AND_NULL(des)
2899
FREE_AND_NULL(strA)
2900
}
2901
2902
/**
2903
* xmlSchemaPCustomAttrErr:
2904
* @ctxt: the schema parser context
2905
* @error: the error code
2906
* @ownerDes: the designation of the owner
2907
* @ownerItem: the owner as a schema object
2908
* @attr: the illegal attribute node
2909
*
2910
* Reports an illegal attribute during the parse.
2911
*/
2912
static void
2913
xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2914
xmlParserErrors error,
2915
xmlChar **ownerDes,
2916
xmlSchemaBasicItemPtr ownerItem,
2917
xmlAttrPtr attr,
2918
const char *msg)
2919
{
2920
xmlChar *des = NULL;
2921
2922
if (ownerDes == NULL)
2923
xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2924
else if (*ownerDes == NULL) {
2925
xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2926
des = *ownerDes;
2927
} else
2928
des = *ownerDes;
2929
if (attr == NULL) {
2930
xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2931
"%s, attribute '%s': %s.\n",
2932
BAD_CAST des, (const xmlChar *) "Unknown",
2933
(const xmlChar *) msg, NULL, NULL);
2934
} else {
2935
xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2936
"%s, attribute '%s': %s.\n",
2937
BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2938
}
2939
if (ownerDes == NULL)
2940
FREE_AND_NULL(des);
2941
}
2942
2943
/**
2944
* xmlSchemaPIllegalAttrErr:
2945
* @ctxt: the schema parser context
2946
* @error: the error code
2947
* @ownerItem: the attribute's owner item
2948
* @attr: the illegal attribute node
2949
*
2950
* Reports an illegal attribute during the parse.
2951
*/
2952
static void
2953
xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2954
xmlParserErrors error,
2955
xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2956
xmlAttrPtr attr)
2957
{
2958
xmlChar *strA = NULL, *strB = NULL;
2959
2960
xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2961
xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2962
"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2963
xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2964
NULL, NULL);
2965
FREE_AND_NULL(strA);
2966
FREE_AND_NULL(strB);
2967
}
2968
2969
/**
2970
* xmlSchemaPCustomErr:
2971
* @ctxt: the schema parser context
2972
* @error: the error code
2973
* @itemDes: the designation of the schema item
2974
* @item: the schema item
2975
* @itemElem: the node of the schema item
2976
* @message: the error message
2977
* @str1: an optional param for the error message
2978
* @str2: an optional param for the error message
2979
* @str3: an optional param for the error message
2980
*
2981
* Reports an error during parsing.
2982
*/
2983
static void LIBXML_ATTR_FORMAT(5,0)
2984
xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2985
xmlParserErrors error,
2986
xmlSchemaBasicItemPtr item,
2987
xmlNodePtr itemElem,
2988
const char *message,
2989
const xmlChar *str1,
2990
const xmlChar *str2,
2991
const xmlChar *str3)
2992
{
2993
xmlChar *des = NULL, *msg = NULL;
2994
2995
xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2996
msg = xmlStrdup(BAD_CAST "%s: ");
2997
msg = xmlStrcat(msg, (const xmlChar *) message);
2998
msg = xmlStrcat(msg, BAD_CAST ".\n");
2999
if ((itemElem == NULL) && (item != NULL))
3000
itemElem = WXS_ITEM_NODE(item);
3001
xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
3002
(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
3003
FREE_AND_NULL(des);
3004
FREE_AND_NULL(msg);
3005
}
3006
3007
/**
3008
* xmlSchemaPCustomErr:
3009
* @ctxt: the schema parser context
3010
* @error: the error code
3011
* @itemDes: the designation of the schema item
3012
* @item: the schema item
3013
* @itemElem: the node of the schema item
3014
* @message: the error message
3015
* @str1: the optional param for the error message
3016
*
3017
* Reports an error during parsing.
3018
*/
3019
static void LIBXML_ATTR_FORMAT(5,0)
3020
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
3021
xmlParserErrors error,
3022
xmlSchemaBasicItemPtr item,
3023
xmlNodePtr itemElem,
3024
const char *message,
3025
const xmlChar *str1)
3026
{
3027
xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
3028
str1, NULL, NULL);
3029
}
3030
3031
/**
3032
* xmlSchemaPAttrUseErr:
3033
* @ctxt: the schema parser context
3034
* @error: the error code
3035
* @itemDes: the designation of the schema type
3036
* @item: the schema type
3037
* @itemElem: the node of the schema type
3038
* @attr: the invalid schema attribute
3039
* @message: the error message
3040
* @str1: the optional param for the error message
3041
*
3042
* Reports an attribute use error during parsing.
3043
*/
3044
static void LIBXML_ATTR_FORMAT(6,0)
3045
xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3046
xmlParserErrors error,
3047
xmlNodePtr node,
3048
xmlSchemaBasicItemPtr ownerItem,
3049
const xmlSchemaAttributeUsePtr attruse,
3050
const char *message,
3051
const xmlChar *str1, const xmlChar *str2,
3052
const xmlChar *str3,const xmlChar *str4)
3053
{
3054
xmlChar *str = NULL, *msg = NULL;
3055
3056
xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3057
msg = xmlStrcat(msg, BAD_CAST ", ");
3058
msg = xmlStrcat(msg,
3059
BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3060
WXS_BASIC_CAST attruse, NULL));
3061
FREE_AND_NULL(str);
3062
msg = xmlStrcat(msg, BAD_CAST ": ");
3063
msg = xmlStrcat(msg, (const xmlChar *) message);
3064
msg = xmlStrcat(msg, BAD_CAST ".\n");
3065
xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3066
(const char *) msg, str1, str2, str3, str4);
3067
xmlFree(msg);
3068
}
3069
3070
/**
3071
* xmlSchemaPIllegalFacetAtomicErr:
3072
* @ctxt: the schema parser context
3073
* @error: the error code
3074
* @type: the schema type
3075
* @baseType: the base type of type
3076
* @facet: the illegal facet
3077
*
3078
* Reports an illegal facet for atomic simple types.
3079
*/
3080
static void
3081
xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3082
xmlParserErrors error,
3083
xmlSchemaTypePtr type,
3084
xmlSchemaTypePtr baseType,
3085
xmlSchemaFacetPtr facet)
3086
{
3087
xmlChar *des = NULL, *strT = NULL;
3088
3089
xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3090
xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3091
"%s: The facet '%s' is not allowed on types derived from the "
3092
"type %s.\n",
3093
BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3094
xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3095
NULL, NULL);
3096
FREE_AND_NULL(des);
3097
FREE_AND_NULL(strT);
3098
}
3099
3100
/**
3101
* xmlSchemaPIllegalFacetListUnionErr:
3102
* @ctxt: the schema parser context
3103
* @error: the error code
3104
* @itemDes: the designation of the schema item involved
3105
* @item: the schema item involved
3106
* @facet: the illegal facet
3107
*
3108
* Reports an illegal facet for <list> and <union>.
3109
*/
3110
static void
3111
xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3112
xmlParserErrors error,
3113
xmlSchemaTypePtr type,
3114
xmlSchemaFacetPtr facet)
3115
{
3116
xmlChar *des = NULL;
3117
3118
xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3119
type->node);
3120
xmlSchemaPErr(ctxt, type->node, error,
3121
"%s: The facet '%s' is not allowed.\n",
3122
BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3123
FREE_AND_NULL(des);
3124
}
3125
3126
/**
3127
* xmlSchemaPMutualExclAttrErr:
3128
* @ctxt: the schema validation context
3129
* @error: the error code
3130
* @elemDes: the designation of the parent element node
3131
* @attr: the bad attribute node
3132
* @type: the corresponding type of the attribute node
3133
*
3134
* Reports an illegal attribute.
3135
*/
3136
static void
3137
xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3138
xmlParserErrors error,
3139
xmlSchemaBasicItemPtr ownerItem,
3140
xmlAttrPtr attr,
3141
const char *name1,
3142
const char *name2)
3143
{
3144
xmlChar *des = NULL;
3145
3146
xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3147
xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3148
"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3149
BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3150
FREE_AND_NULL(des);
3151
}
3152
3153
/**
3154
* xmlSchemaPSimpleTypeErr:
3155
* @ctxt: the schema validation context
3156
* @error: the error code
3157
* @type: the type specifier
3158
* @ownerItem: the schema object if existent
3159
* @node: the validated node
3160
* @value: the validated value
3161
*
3162
* Reports a simple type validation error.
3163
* TODO: Should this report the value of an element as well?
3164
*/
3165
static void LIBXML_ATTR_FORMAT(8,0)
3166
xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3167
xmlParserErrors error,
3168
xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3169
xmlNodePtr node,
3170
xmlSchemaTypePtr type,
3171
const char *expected,
3172
const xmlChar *value,
3173
const char *message,
3174
const xmlChar *str1,
3175
const xmlChar *str2)
3176
{
3177
xmlChar *msg = NULL;
3178
3179
xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3180
if (message == NULL) {
3181
/*
3182
* Use default messages.
3183
*/
3184
if (type != NULL) {
3185
if (node->type == XML_ATTRIBUTE_NODE)
3186
msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3187
else
3188
msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3189
"valid value of ");
3190
if (! xmlSchemaIsGlobalItem(type))
3191
msg = xmlStrcat(msg, BAD_CAST "the local ");
3192
else
3193
msg = xmlStrcat(msg, BAD_CAST "the ");
3194
3195
if (WXS_IS_ATOMIC(type))
3196
msg = xmlStrcat(msg, BAD_CAST "atomic type");
3197
else if (WXS_IS_LIST(type))
3198
msg = xmlStrcat(msg, BAD_CAST "list type");
3199
else if (WXS_IS_UNION(type))
3200
msg = xmlStrcat(msg, BAD_CAST "union type");
3201
3202
if (xmlSchemaIsGlobalItem(type)) {
3203
xmlChar *str = NULL;
3204
msg = xmlStrcat(msg, BAD_CAST " '");
3205
if (type->builtInType != 0) {
3206
msg = xmlStrcat(msg, BAD_CAST "xs:");
3207
str = xmlStrdup(type->name);
3208
} else {
3209
const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3210
if (!str)
3211
str = xmlStrdup(qName);
3212
}
3213
msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3214
msg = xmlStrcat(msg, BAD_CAST "'.");
3215
FREE_AND_NULL(str);
3216
}
3217
} else {
3218
if (node->type == XML_ATTRIBUTE_NODE)
3219
msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3220
else
3221
msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3222
"valid.");
3223
}
3224
if (expected) {
3225
xmlChar *expectedEscaped = xmlCharStrdup(expected);
3226
msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3227
msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3228
FREE_AND_NULL(expectedEscaped);
3229
msg = xmlStrcat(msg, BAD_CAST "'.\n");
3230
} else
3231
msg = xmlStrcat(msg, BAD_CAST "\n");
3232
if (node->type == XML_ATTRIBUTE_NODE)
3233
xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3234
else
3235
xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3236
} else {
3237
msg = xmlStrcat(msg, BAD_CAST message);
3238
msg = xmlStrcat(msg, BAD_CAST ".\n");
3239
xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3240
(const char*) msg, str1, str2, NULL, NULL, NULL);
3241
}
3242
/* Cleanup. */
3243
FREE_AND_NULL(msg)
3244
}
3245
3246
/**
3247
* xmlSchemaPContentErr:
3248
* @ctxt: the schema parser context
3249
* @error: the error code
3250
* @ownerItem: the owner item of the holder of the content
3251
* @ownerElem: the node of the holder of the content
3252
* @child: the invalid child node
3253
* @message: the optional error message
3254
* @content: the optional string describing the correct content
3255
*
3256
* Reports an error concerning the content of a schema element.
3257
*/
3258
static void
3259
xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3260
xmlParserErrors error,
3261
xmlSchemaBasicItemPtr ownerItem,
3262
xmlNodePtr ownerElem,
3263
xmlNodePtr child,
3264
const char *message,
3265
const char *content)
3266
{
3267
xmlChar *des = NULL;
3268
3269
xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3270
if (message != NULL)
3271
xmlSchemaPErr2(ctxt, ownerElem, child, error,
3272
"%s: %s.\n",
3273
BAD_CAST des, BAD_CAST message);
3274
else {
3275
if (content != NULL) {
3276
xmlSchemaPErr2(ctxt, ownerElem, child, error,
3277
"%s: The content is not valid. Expected is %s.\n",
3278
BAD_CAST des, BAD_CAST content);
3279
} else {
3280
xmlSchemaPErr2(ctxt, ownerElem, child, error,
3281
"%s: The content is not valid.\n",
3282
BAD_CAST des, NULL);
3283
}
3284
}
3285
FREE_AND_NULL(des)
3286
}
3287
3288
/************************************************************************
3289
* *
3290
* Streamable error functions *
3291
* *
3292
************************************************************************/
3293
3294
3295
3296
3297
/************************************************************************
3298
* *
3299
* Validation helper functions *
3300
* *
3301
************************************************************************/
3302
3303
3304
/************************************************************************
3305
* *
3306
* Allocation functions *
3307
* *
3308
************************************************************************/
3309
3310
/**
3311
* xmlSchemaNewSchemaForParserCtxt:
3312
* @ctxt: a schema validation context
3313
*
3314
* Allocate a new Schema structure.
3315
*
3316
* Returns the newly allocated structure or NULL in case or error
3317
*/
3318
static xmlSchemaPtr
3319
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3320
{
3321
xmlSchemaPtr ret;
3322
3323
ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3324
if (ret == NULL) {
3325
xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3326
return (NULL);
3327
}
3328
memset(ret, 0, sizeof(xmlSchema));
3329
ret->dict = ctxt->dict;
3330
xmlDictReference(ret->dict);
3331
3332
return (ret);
3333
}
3334
3335
/**
3336
* xmlSchemaNewFacet:
3337
*
3338
* Allocate a new Facet structure.
3339
*
3340
* Returns the newly allocated structure or NULL in case or error
3341
*/
3342
xmlSchemaFacetPtr
3343
xmlSchemaNewFacet(void)
3344
{
3345
xmlSchemaFacetPtr ret;
3346
3347
ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3348
if (ret == NULL) {
3349
return (NULL);
3350
}
3351
memset(ret, 0, sizeof(xmlSchemaFacet));
3352
3353
return (ret);
3354
}
3355
3356
/**
3357
* xmlSchemaNewAnnot:
3358
* @ctxt: a schema validation context
3359
* @node: a node
3360
*
3361
* Allocate a new annotation structure.
3362
*
3363
* Returns the newly allocated structure or NULL in case or error
3364
*/
3365
static xmlSchemaAnnotPtr
3366
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3367
{
3368
xmlSchemaAnnotPtr ret;
3369
3370
ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3371
if (ret == NULL) {
3372
xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3373
return (NULL);
3374
}
3375
memset(ret, 0, sizeof(xmlSchemaAnnot));
3376
ret->content = node;
3377
return (ret);
3378
}
3379
3380
static xmlSchemaItemListPtr
3381
xmlSchemaItemListCreate(void)
3382
{
3383
xmlSchemaItemListPtr ret;
3384
3385
ret = xmlMalloc(sizeof(xmlSchemaItemList));
3386
if (ret == NULL) {
3387
xmlSchemaPErrMemory(NULL,
3388
"allocating an item list structure", NULL);
3389
return (NULL);
3390
}
3391
memset(ret, 0, sizeof(xmlSchemaItemList));
3392
return (ret);
3393
}
3394
3395
static void
3396
xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3397
{
3398
if (list->items != NULL) {
3399
xmlFree(list->items);
3400
list->items = NULL;
3401
}
3402
list->nbItems = 0;
3403
list->sizeItems = 0;
3404
}
3405
3406
static int
3407
xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3408
{
3409
if (list->sizeItems <= list->nbItems) {
3410
void **tmp;
3411
size_t newSize = list->sizeItems == 0 ? 20 : list->sizeItems * 2;
3412
3413
tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *));
3414
if (tmp == NULL) {
3415
xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3416
return(-1);
3417
}
3418
list->items = tmp;
3419
list->sizeItems = newSize;
3420
}
3421
list->items[list->nbItems++] = item;
3422
return(0);
3423
}
3424
3425
static int
3426
xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3427
int initialSize,
3428
void *item)
3429
{
3430
if (list->items == NULL) {
3431
if (initialSize <= 0)
3432
initialSize = 1;
3433
list->items = (void **) xmlMalloc(
3434
initialSize * sizeof(void *));
3435
if (list->items == NULL) {
3436
xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3437
return(-1);
3438
}
3439
list->sizeItems = initialSize;
3440
} else if (list->sizeItems <= list->nbItems) {
3441
void **tmp;
3442
3443
list->sizeItems *= 2;
3444
tmp = (void **) xmlRealloc(list->items,
3445
list->sizeItems * sizeof(void *));
3446
if (tmp == NULL) {
3447
xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3448
list->sizeItems /= 2;
3449
return(-1);
3450
}
3451
list->items = tmp;
3452
}
3453
list->items[list->nbItems++] = item;
3454
return(0);
3455
}
3456
3457
static int
3458
xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3459
{
3460
if (list->sizeItems <= list->nbItems) {
3461
void **tmp;
3462
size_t newSize = list->sizeItems == 0 ? 20 : list->sizeItems * 2;
3463
3464
tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *));
3465
if (tmp == NULL) {
3466
xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3467
return(-1);
3468
}
3469
list->items = tmp;
3470
list->sizeItems = newSize;
3471
}
3472
/*
3473
* Just append if the index is greater/equal than the item count.
3474
*/
3475
if (idx >= list->nbItems) {
3476
list->items[list->nbItems++] = item;
3477
} else {
3478
int i;
3479
for (i = list->nbItems; i > idx; i--)
3480
list->items[i] = list->items[i-1];
3481
list->items[idx] = item;
3482
list->nbItems++;
3483
}
3484
return(0);
3485
}
3486
3487
#if 0 /* enable if ever needed */
3488
static int
3489
xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3490
int initialSize,
3491
void *item,
3492
int idx)
3493
{
3494
if (list->items == NULL) {
3495
if (initialSize <= 0)
3496
initialSize = 1;
3497
list->items = (void **) xmlMalloc(
3498
initialSize * sizeof(void *));
3499
if (list->items == NULL) {
3500
xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3501
return(-1);
3502
}
3503
list->sizeItems = initialSize;
3504
} else if (list->sizeItems <= list->nbItems) {
3505
list->sizeItems *= 2;
3506
list->items = (void **) xmlRealloc(list->items,
3507
list->sizeItems * sizeof(void *));
3508
if (list->items == NULL) {
3509
xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3510
list->sizeItems = 0;
3511
return(-1);
3512
}
3513
}
3514
/*
3515
* Just append if the index is greater/equal than the item count.
3516
*/
3517
if (idx >= list->nbItems) {
3518
list->items[list->nbItems++] = item;
3519
} else {
3520
int i;
3521
for (i = list->nbItems; i > idx; i--)
3522
list->items[i] = list->items[i-1];
3523
list->items[idx] = item;
3524
list->nbItems++;
3525
}
3526
return(0);
3527
}
3528
#endif
3529
3530
static int
3531
xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3532
{
3533
int i;
3534
if ((list->items == NULL) || (idx >= list->nbItems)) {
3535
xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3536
"index error.\n");
3537
return(-1);
3538
}
3539
3540
if (list->nbItems == 1) {
3541
/* TODO: Really free the list? */
3542
xmlFree(list->items);
3543
list->items = NULL;
3544
list->nbItems = 0;
3545
list->sizeItems = 0;
3546
} else if (list->nbItems -1 == idx) {
3547
list->nbItems--;
3548
} else {
3549
for (i = idx; i < list->nbItems -1; i++)
3550
list->items[i] = list->items[i+1];
3551
list->nbItems--;
3552
}
3553
return(0);
3554
}
3555
3556
/**
3557
* xmlSchemaItemListFree:
3558
* @annot: a schema type structure
3559
*
3560
* Deallocate a annotation structure
3561
*/
3562
static void
3563
xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3564
{
3565
if (list == NULL)
3566
return;
3567
if (list->items != NULL)
3568
xmlFree(list->items);
3569
xmlFree(list);
3570
}
3571
3572
static void
3573
xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3574
{
3575
if (bucket == NULL)
3576
return;
3577
if (bucket->globals != NULL) {
3578
xmlSchemaComponentListFree(bucket->globals);
3579
xmlSchemaItemListFree(bucket->globals);
3580
}
3581
if (bucket->locals != NULL) {
3582
xmlSchemaComponentListFree(bucket->locals);
3583
xmlSchemaItemListFree(bucket->locals);
3584
}
3585
if (bucket->relations != NULL) {
3586
xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3587
do {
3588
prev = cur;
3589
cur = cur->next;
3590
xmlFree(prev);
3591
} while (cur != NULL);
3592
}
3593
if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3594
xmlFreeDoc(bucket->doc);
3595
}
3596
if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3597
if (WXS_IMPBUCKET(bucket)->schema != NULL)
3598
xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3599
}
3600
xmlFree(bucket);
3601
}
3602
3603
static void
3604
xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3605
{
3606
xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3607
}
3608
3609
static xmlSchemaBucketPtr
3610
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3611
int type, const xmlChar *targetNamespace)
3612
{
3613
xmlSchemaBucketPtr ret;
3614
int size;
3615
xmlSchemaPtr mainSchema;
3616
3617
if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3618
PERROR_INT("xmlSchemaBucketCreate",
3619
"no main schema on constructor");
3620
return(NULL);
3621
}
3622
mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3623
/* Create the schema bucket. */
3624
if (WXS_IS_BUCKET_INCREDEF(type))
3625
size = sizeof(xmlSchemaInclude);
3626
else
3627
size = sizeof(xmlSchemaImport);
3628
ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3629
if (ret == NULL) {
3630
xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3631
return(NULL);
3632
}
3633
memset(ret, 0, size);
3634
ret->targetNamespace = targetNamespace;
3635
ret->type = type;
3636
ret->globals = xmlSchemaItemListCreate();
3637
if (ret->globals == NULL) {
3638
xmlSchemaBucketFree(ret);
3639
return(NULL);
3640
}
3641
ret->locals = xmlSchemaItemListCreate();
3642
if (ret->locals == NULL) {
3643
xmlSchemaBucketFree(ret);
3644
return(NULL);
3645
}
3646
/*
3647
* The following will assure that only the first bucket is marked as
3648
* XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3649
* For each following import buckets an xmlSchema will be created.
3650
* An xmlSchema will be created for every distinct targetNamespace.
3651
* We assign the targetNamespace to the schemata here.
3652
*/
3653
if (! WXS_HAS_BUCKETS(pctxt)) {
3654
if (WXS_IS_BUCKET_INCREDEF(type)) {
3655
PERROR_INT("xmlSchemaBucketCreate",
3656
"first bucket but it's an include or redefine");
3657
xmlSchemaBucketFree(ret);
3658
return(NULL);
3659
}
3660
/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3661
ret->type = XML_SCHEMA_SCHEMA_MAIN;
3662
/* Point to the *main* schema. */
3663
WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3664
WXS_IMPBUCKET(ret)->schema = mainSchema;
3665
/*
3666
* Ensure that the main schema gets a targetNamespace.
3667
*/
3668
mainSchema->targetNamespace = targetNamespace;
3669
} else {
3670
if (type == XML_SCHEMA_SCHEMA_MAIN) {
3671
PERROR_INT("xmlSchemaBucketCreate",
3672
"main bucket but it's not the first one");
3673
xmlSchemaBucketFree(ret);
3674
return(NULL);
3675
} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3676
/*
3677
* Create a schema for imports and assign the
3678
* targetNamespace.
3679
*/
3680
WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3681
if (WXS_IMPBUCKET(ret)->schema == NULL) {
3682
xmlSchemaBucketFree(ret);
3683
return(NULL);
3684
}
3685
WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3686
}
3687
}
3688
if (WXS_IS_BUCKET_IMPMAIN(type)) {
3689
int res;
3690
/*
3691
* Imports go into the "schemasImports" slot of the main *schema*.
3692
* Note that we create an import entry for the main schema as well; i.e.,
3693
* even if there's only one schema, we'll get an import.
3694
*/
3695
if (mainSchema->schemasImports == NULL) {
3696
mainSchema->schemasImports = xmlHashCreateDict(5,
3697
WXS_CONSTRUCTOR(pctxt)->dict);
3698
if (mainSchema->schemasImports == NULL) {
3699
xmlSchemaBucketFree(ret);
3700
return(NULL);
3701
}
3702
}
3703
if (targetNamespace == NULL)
3704
res = xmlHashAddEntry(mainSchema->schemasImports,
3705
XML_SCHEMAS_NO_NAMESPACE, ret);
3706
else
3707
res = xmlHashAddEntry(mainSchema->schemasImports,
3708
targetNamespace, ret);
3709
if (res != 0) {
3710
PERROR_INT("xmlSchemaBucketCreate",
3711
"failed to add the schema bucket to the hash");
3712
xmlSchemaBucketFree(ret);
3713
return(NULL);
3714
}
3715
} else {
3716
/* Set the @ownerImport of an include bucket. */
3717
if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3718
WXS_INCBUCKET(ret)->ownerImport =
3719
WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3720
else
3721
WXS_INCBUCKET(ret)->ownerImport =
3722
WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3723
3724
/* Includes got into the "includes" slot of the *main* schema. */
3725
if (mainSchema->includes == NULL) {
3726
mainSchema->includes = xmlSchemaItemListCreate();
3727
if (mainSchema->includes == NULL) {
3728
xmlSchemaBucketFree(ret);
3729
return(NULL);
3730
}
3731
}
3732
if (xmlSchemaItemListAdd(mainSchema->includes, ret) < 0) {
3733
xmlSchemaBucketFree(ret);
3734
return(NULL);
3735
}
3736
}
3737
/*
3738
* Add to list of all buckets; this is used for lookup
3739
* during schema construction time only.
3740
*/
3741
if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3742
return(NULL);
3743
return(ret);
3744
}
3745
3746
static int
3747
xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3748
{
3749
if (*list == NULL) {
3750
*list = xmlSchemaItemListCreate();
3751
if (*list == NULL)
3752
return(-1);
3753
}
3754
return(xmlSchemaItemListAddSize(*list, initialSize, item));
3755
}
3756
3757
/**
3758
* xmlSchemaFreeAnnot:
3759
* @annot: a schema type structure
3760
*
3761
* Deallocate a annotation structure
3762
*/
3763
static void
3764
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3765
{
3766
if (annot == NULL)
3767
return;
3768
if (annot->next == NULL) {
3769
xmlFree(annot);
3770
} else {
3771
xmlSchemaAnnotPtr prev;
3772
3773
do {
3774
prev = annot;
3775
annot = annot->next;
3776
xmlFree(prev);
3777
} while (annot != NULL);
3778
}
3779
}
3780
3781
/**
3782
* xmlSchemaFreeNotation:
3783
* @schema: a schema notation structure
3784
*
3785
* Deallocate a Schema Notation structure.
3786
*/
3787
static void
3788
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3789
{
3790
if (nota == NULL)
3791
return;
3792
if (nota->annot != NULL)
3793
xmlSchemaFreeAnnot(nota->annot);
3794
xmlFree(nota);
3795
}
3796
3797
/**
3798
* xmlSchemaFreeAttribute:
3799
* @attr: an attribute declaration
3800
*
3801
* Deallocates an attribute declaration structure.
3802
*/
3803
static void
3804
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3805
{
3806
if (attr == NULL)
3807
return;
3808
if (attr->annot != NULL)
3809
xmlSchemaFreeAnnot(attr->annot);
3810
if (attr->defVal != NULL)
3811
xmlSchemaFreeValue(attr->defVal);
3812
xmlFree(attr);
3813
}
3814
3815
/**
3816
* xmlSchemaFreeAttributeUse:
3817
* @use: an attribute use
3818
*
3819
* Deallocates an attribute use structure.
3820
*/
3821
static void
3822
xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3823
{
3824
if (use == NULL)
3825
return;
3826
if (use->annot != NULL)
3827
xmlSchemaFreeAnnot(use->annot);
3828
if (use->defVal != NULL)
3829
xmlSchemaFreeValue(use->defVal);
3830
xmlFree(use);
3831
}
3832
3833
/**
3834
* xmlSchemaFreeAttributeUseProhib:
3835
* @prohib: an attribute use prohibition
3836
*
3837
* Deallocates an attribute use structure.
3838
*/
3839
static void
3840
xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3841
{
3842
if (prohib == NULL)
3843
return;
3844
xmlFree(prohib);
3845
}
3846
3847
/**
3848
* xmlSchemaFreeWildcardNsSet:
3849
* set: a schema wildcard namespace
3850
*
3851
* Deallocates a list of wildcard constraint structures.
3852
*/
3853
static void
3854
xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3855
{
3856
xmlSchemaWildcardNsPtr next;
3857
3858
while (set != NULL) {
3859
next = set->next;
3860
xmlFree(set);
3861
set = next;
3862
}
3863
}
3864
3865
/**
3866
* xmlSchemaFreeWildcard:
3867
* @wildcard: a wildcard structure
3868
*
3869
* Deallocates a wildcard structure.
3870
*/
3871
void
3872
xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3873
{
3874
if (wildcard == NULL)
3875
return;
3876
if (wildcard->annot != NULL)
3877
xmlSchemaFreeAnnot(wildcard->annot);
3878
if (wildcard->nsSet != NULL)
3879
xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3880
if (wildcard->negNsSet != NULL)
3881
xmlFree(wildcard->negNsSet);
3882
xmlFree(wildcard);
3883
}
3884
3885
/**
3886
* xmlSchemaFreeAttributeGroup:
3887
* @schema: a schema attribute group structure
3888
*
3889
* Deallocate a Schema Attribute Group structure.
3890
*/
3891
static void
3892
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3893
{
3894
if (attrGr == NULL)
3895
return;
3896
if (attrGr->annot != NULL)
3897
xmlSchemaFreeAnnot(attrGr->annot);
3898
if (attrGr->attrUses != NULL)
3899
xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3900
xmlFree(attrGr);
3901
}
3902
3903
/**
3904
* xmlSchemaFreeQNameRef:
3905
* @item: a QName reference structure
3906
*
3907
* Deallocatea a QName reference structure.
3908
*/
3909
static void
3910
xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3911
{
3912
xmlFree(item);
3913
}
3914
3915
/**
3916
* xmlSchemaFreeTypeLinkList:
3917
* @alink: a type link
3918
*
3919
* Deallocate a list of types.
3920
*/
3921
static void
3922
xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3923
{
3924
xmlSchemaTypeLinkPtr next;
3925
3926
while (link != NULL) {
3927
next = link->next;
3928
xmlFree(link);
3929
link = next;
3930
}
3931
}
3932
3933
static void
3934
xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3935
{
3936
xmlSchemaIDCStateObjPtr next;
3937
while (sto != NULL) {
3938
next = sto->next;
3939
if (sto->history != NULL)
3940
xmlFree(sto->history);
3941
if (sto->xpathCtxt != NULL)
3942
xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3943
xmlFree(sto);
3944
sto = next;
3945
}
3946
}
3947
3948
/**
3949
* xmlSchemaFreeIDC:
3950
* @idc: a identity-constraint definition
3951
*
3952
* Deallocates an identity-constraint definition.
3953
*/
3954
static void
3955
xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3956
{
3957
xmlSchemaIDCSelectPtr cur, prev;
3958
3959
if (idcDef == NULL)
3960
return;
3961
if (idcDef->annot != NULL)
3962
xmlSchemaFreeAnnot(idcDef->annot);
3963
/* Selector */
3964
if (idcDef->selector != NULL) {
3965
if (idcDef->selector->xpathComp != NULL)
3966
xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3967
xmlFree(idcDef->selector);
3968
}
3969
/* Fields */
3970
if (idcDef->fields != NULL) {
3971
cur = idcDef->fields;
3972
do {
3973
prev = cur;
3974
cur = cur->next;
3975
if (prev->xpathComp != NULL)
3976
xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3977
xmlFree(prev);
3978
} while (cur != NULL);
3979
}
3980
xmlFree(idcDef);
3981
}
3982
3983
/**
3984
* xmlSchemaFreeElement:
3985
* @schema: a schema element structure
3986
*
3987
* Deallocate a Schema Element structure.
3988
*/
3989
static void
3990
xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3991
{
3992
if (elem == NULL)
3993
return;
3994
if (elem->annot != NULL)
3995
xmlSchemaFreeAnnot(elem->annot);
3996
if (elem->contModel != NULL)
3997
xmlRegFreeRegexp(elem->contModel);
3998
if (elem->defVal != NULL)
3999
xmlSchemaFreeValue(elem->defVal);
4000
xmlFree(elem);
4001
}
4002
4003
/**
4004
* xmlSchemaFreeFacet:
4005
* @facet: a schema facet structure
4006
*
4007
* Deallocate a Schema Facet structure.
4008
*/
4009
void
4010
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
4011
{
4012
if (facet == NULL)
4013
return;
4014
if (facet->val != NULL)
4015
xmlSchemaFreeValue(facet->val);
4016
if (facet->regexp != NULL)
4017
xmlRegFreeRegexp(facet->regexp);
4018
if (facet->annot != NULL)
4019
xmlSchemaFreeAnnot(facet->annot);
4020
xmlFree(facet);
4021
}
4022
4023
/**
4024
* xmlSchemaFreeType:
4025
* @type: a schema type structure
4026
*
4027
* Deallocate a Schema Type structure.
4028
*/
4029
void
4030
xmlSchemaFreeType(xmlSchemaTypePtr type)
4031
{
4032
if (type == NULL)
4033
return;
4034
if (type->annot != NULL)
4035
xmlSchemaFreeAnnot(type->annot);
4036
if (type->facets != NULL) {
4037
xmlSchemaFacetPtr facet, next;
4038
4039
facet = type->facets;
4040
while (facet != NULL) {
4041
next = facet->next;
4042
xmlSchemaFreeFacet(facet);
4043
facet = next;
4044
}
4045
}
4046
if (type->attrUses != NULL)
4047
xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4048
if (type->memberTypes != NULL)
4049
xmlSchemaFreeTypeLinkList(type->memberTypes);
4050
if (type->facetSet != NULL) {
4051
xmlSchemaFacetLinkPtr next, link;
4052
4053
link = type->facetSet;
4054
do {
4055
next = link->next;
4056
xmlFree(link);
4057
link = next;
4058
} while (link != NULL);
4059
}
4060
if (type->contModel != NULL)
4061
xmlRegFreeRegexp(type->contModel);
4062
xmlFree(type);
4063
}
4064
4065
/**
4066
* xmlSchemaFreeModelGroupDef:
4067
* @item: a schema model group definition
4068
*
4069
* Deallocates a schema model group definition.
4070
*/
4071
static void
4072
xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4073
{
4074
if (item->annot != NULL)
4075
xmlSchemaFreeAnnot(item->annot);
4076
xmlFree(item);
4077
}
4078
4079
/**
4080
* xmlSchemaFreeModelGroup:
4081
* @item: a schema model group
4082
*
4083
* Deallocates a schema model group structure.
4084
*/
4085
static void
4086
xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4087
{
4088
if (item->annot != NULL)
4089
xmlSchemaFreeAnnot(item->annot);
4090
xmlFree(item);
4091
}
4092
4093
static void
4094
xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4095
{
4096
if ((list == NULL) || (list->nbItems == 0))
4097
return;
4098
{
4099
xmlSchemaTreeItemPtr item;
4100
xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4101
int i;
4102
4103
for (i = 0; i < list->nbItems; i++) {
4104
item = items[i];
4105
if (item == NULL)
4106
continue;
4107
switch (item->type) {
4108
case XML_SCHEMA_TYPE_SIMPLE:
4109
case XML_SCHEMA_TYPE_COMPLEX:
4110
xmlSchemaFreeType((xmlSchemaTypePtr) item);
4111
break;
4112
case XML_SCHEMA_TYPE_ATTRIBUTE:
4113
xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4114
break;
4115
case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4116
xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4117
break;
4118
case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4119
xmlSchemaFreeAttributeUseProhib(
4120
(xmlSchemaAttributeUseProhibPtr) item);
4121
break;
4122
case XML_SCHEMA_TYPE_ELEMENT:
4123
xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4124
break;
4125
case XML_SCHEMA_TYPE_PARTICLE:
4126
if (item->annot != NULL)
4127
xmlSchemaFreeAnnot(item->annot);
4128
xmlFree(item);
4129
break;
4130
case XML_SCHEMA_TYPE_SEQUENCE:
4131
case XML_SCHEMA_TYPE_CHOICE:
4132
case XML_SCHEMA_TYPE_ALL:
4133
xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4134
break;
4135
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4136
xmlSchemaFreeAttributeGroup(
4137
(xmlSchemaAttributeGroupPtr) item);
4138
break;
4139
case XML_SCHEMA_TYPE_GROUP:
4140
xmlSchemaFreeModelGroupDef(
4141
(xmlSchemaModelGroupDefPtr) item);
4142
break;
4143
case XML_SCHEMA_TYPE_ANY:
4144
case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4145
xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4146
break;
4147
case XML_SCHEMA_TYPE_IDC_KEY:
4148
case XML_SCHEMA_TYPE_IDC_UNIQUE:
4149
case XML_SCHEMA_TYPE_IDC_KEYREF:
4150
xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4151
break;
4152
case XML_SCHEMA_TYPE_NOTATION:
4153
xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4154
break;
4155
case XML_SCHEMA_EXTRA_QNAMEREF:
4156
xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4157
break;
4158
default: {
4159
/* TODO: This should never be hit. */
4160
xmlSchemaPSimpleInternalErr(NULL,
4161
"Internal error: xmlSchemaComponentListFree, "
4162
"unexpected component type '%s'\n",
4163
(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4164
}
4165
break;
4166
}
4167
}
4168
list->nbItems = 0;
4169
}
4170
}
4171
4172
/**
4173
* xmlSchemaFree:
4174
* @schema: a schema structure
4175
*
4176
* Deallocate a Schema structure.
4177
*/
4178
void
4179
xmlSchemaFree(xmlSchemaPtr schema)
4180
{
4181
if (schema == NULL)
4182
return;
4183
/* @volatiles is not used anymore :-/ */
4184
if (schema->volatiles != NULL)
4185
TODO
4186
/*
4187
* Note that those slots are not responsible for freeing
4188
* schema components anymore; this will now be done by
4189
* the schema buckets.
4190
*/
4191
if (schema->notaDecl != NULL)
4192
xmlHashFree(schema->notaDecl, NULL);
4193
if (schema->attrDecl != NULL)
4194
xmlHashFree(schema->attrDecl, NULL);
4195
if (schema->attrgrpDecl != NULL)
4196
xmlHashFree(schema->attrgrpDecl, NULL);
4197
if (schema->elemDecl != NULL)
4198
xmlHashFree(schema->elemDecl, NULL);
4199
if (schema->typeDecl != NULL)
4200
xmlHashFree(schema->typeDecl, NULL);
4201
if (schema->groupDecl != NULL)
4202
xmlHashFree(schema->groupDecl, NULL);
4203
if (schema->idcDef != NULL)
4204
xmlHashFree(schema->idcDef, NULL);
4205
4206
if (schema->schemasImports != NULL)
4207
xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4208
if (schema->includes != NULL) {
4209
xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4210
int i;
4211
for (i = 0; i < list->nbItems; i++) {
4212
xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4213
}
4214
xmlSchemaItemListFree(list);
4215
}
4216
if (schema->annot != NULL)
4217
xmlSchemaFreeAnnot(schema->annot);
4218
/* Never free the doc here, since this will be done by the buckets. */
4219
4220
xmlDictFree(schema->dict);
4221
xmlFree(schema);
4222
}
4223
4224
/************************************************************************
4225
* *
4226
* Debug functions *
4227
* *
4228
************************************************************************/
4229
4230
#ifdef LIBXML_OUTPUT_ENABLED
4231
4232
static void
4233
xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4234
4235
/**
4236
* xmlSchemaElementDump:
4237
* @elem: an element
4238
* @output: the file output
4239
*
4240
* Dump the element
4241
*/
4242
static void
4243
xmlSchemaElementDump(void *payload, void *data,
4244
const xmlChar * name ATTRIBUTE_UNUSED,
4245
const xmlChar * namespace ATTRIBUTE_UNUSED,
4246
const xmlChar * context ATTRIBUTE_UNUSED)
4247
{
4248
xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4249
FILE *output = (FILE *) data;
4250
if (elem == NULL)
4251
return;
4252
4253
4254
fprintf(output, "Element");
4255
if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4256
fprintf(output, " (global)");
4257
fprintf(output, ": '%s' ", elem->name);
4258
if (namespace != NULL)
4259
fprintf(output, "ns '%s'", namespace);
4260
fprintf(output, "\n");
4261
#if 0
4262
if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4263
fprintf(output, " min %d ", elem->minOccurs);
4264
if (elem->maxOccurs >= UNBOUNDED)
4265
fprintf(output, "max: unbounded\n");
4266
else if (elem->maxOccurs != 1)
4267
fprintf(output, "max: %d\n", elem->maxOccurs);
4268
else
4269
fprintf(output, "\n");
4270
}
4271
#endif
4272
/*
4273
* Misc other properties.
4274
*/
4275
if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4276
(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4277
(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4278
(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4279
fprintf(output, " props: ");
4280
if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4281
fprintf(output, "[fixed] ");
4282
if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4283
fprintf(output, "[default] ");
4284
if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4285
fprintf(output, "[abstract] ");
4286
if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4287
fprintf(output, "[nillable] ");
4288
fprintf(output, "\n");
4289
}
4290
/*
4291
* Default/fixed value.
4292
*/
4293
if (elem->value != NULL)
4294
fprintf(output, " value: '%s'\n", elem->value);
4295
/*
4296
* Type.
4297
*/
4298
if (elem->namedType != NULL) {
4299
fprintf(output, " type: '%s' ", elem->namedType);
4300
if (elem->namedTypeNs != NULL)
4301
fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4302
else
4303
fprintf(output, "\n");
4304
} else if (elem->subtypes != NULL) {
4305
/*
4306
* Dump local types.
4307
*/
4308
xmlSchemaTypeDump(elem->subtypes, output);
4309
}
4310
/*
4311
* Substitution group.
4312
*/
4313
if (elem->substGroup != NULL) {
4314
fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
4315
if (elem->substGroupNs != NULL)
4316
fprintf(output, "ns '%s'\n", elem->substGroupNs);
4317
else
4318
fprintf(output, "\n");
4319
}
4320
}
4321
4322
/**
4323
* xmlSchemaAnnotDump:
4324
* @output: the file output
4325
* @annot: a annotation
4326
*
4327
* Dump the annotation
4328
*/
4329
static void
4330
xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4331
{
4332
xmlChar *content;
4333
4334
if (annot == NULL)
4335
return;
4336
4337
content = xmlNodeGetContent(annot->content);
4338
if (content != NULL) {
4339
fprintf(output, " Annot: %s\n", content);
4340
xmlFree(content);
4341
} else
4342
fprintf(output, " Annot: empty\n");
4343
}
4344
4345
/**
4346
* xmlSchemaContentModelDump:
4347
* @particle: the schema particle
4348
* @output: the file output
4349
* @depth: the depth used for indentation
4350
*
4351
* Dump a SchemaType structure
4352
*/
4353
static void
4354
xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4355
{
4356
xmlChar *str = NULL;
4357
xmlSchemaTreeItemPtr term;
4358
char shift[100];
4359
int i;
4360
4361
if (particle == NULL)
4362
return;
4363
for (i = 0;((i < depth) && (i < 25));i++)
4364
shift[2 * i] = shift[2 * i + 1] = ' ';
4365
shift[2 * i] = shift[2 * i + 1] = 0;
4366
fprintf(output, "%s", shift);
4367
if (particle->children == NULL) {
4368
fprintf(output, "MISSING particle term\n");
4369
return;
4370
}
4371
term = particle->children;
4372
if (term == NULL) {
4373
fprintf(output, "(NULL)");
4374
} else {
4375
switch (term->type) {
4376
case XML_SCHEMA_TYPE_ELEMENT:
4377
fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4378
((xmlSchemaElementPtr)term)->targetNamespace,
4379
((xmlSchemaElementPtr)term)->name));
4380
FREE_AND_NULL(str);
4381
break;
4382
case XML_SCHEMA_TYPE_SEQUENCE:
4383
fprintf(output, "SEQUENCE");
4384
break;
4385
case XML_SCHEMA_TYPE_CHOICE:
4386
fprintf(output, "CHOICE");
4387
break;
4388
case XML_SCHEMA_TYPE_ALL:
4389
fprintf(output, "ALL");
4390
break;
4391
case XML_SCHEMA_TYPE_ANY:
4392
fprintf(output, "ANY");
4393
break;
4394
default:
4395
fprintf(output, "UNKNOWN\n");
4396
return;
4397
}
4398
}
4399
if (particle->minOccurs != 1)
4400
fprintf(output, " min: %d", particle->minOccurs);
4401
if (particle->maxOccurs >= UNBOUNDED)
4402
fprintf(output, " max: unbounded");
4403
else if (particle->maxOccurs != 1)
4404
fprintf(output, " max: %d", particle->maxOccurs);
4405
fprintf(output, "\n");
4406
if (term &&
4407
((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4408
(term->type == XML_SCHEMA_TYPE_CHOICE) ||
4409
(term->type == XML_SCHEMA_TYPE_ALL)) &&
4410
(term->children != NULL)) {
4411
xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4412
output, depth +1);
4413
}
4414
if (particle->next != NULL)
4415
xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4416
output, depth);
4417
}
4418
4419
/**
4420
* xmlSchemaAttrUsesDump:
4421
* @uses: attribute uses list
4422
* @output: the file output
4423
*
4424
* Dumps a list of attribute use components.
4425
*/
4426
static void
4427
xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4428
{
4429
xmlSchemaAttributeUsePtr use;
4430
xmlSchemaAttributeUseProhibPtr prohib;
4431
xmlSchemaQNameRefPtr ref;
4432
const xmlChar *name, *tns;
4433
xmlChar *str = NULL;
4434
int i;
4435
4436
if ((uses == NULL) || (uses->nbItems == 0))
4437
return;
4438
4439
fprintf(output, " attributes:\n");
4440
for (i = 0; i < uses->nbItems; i++) {
4441
use = uses->items[i];
4442
if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4443
fprintf(output, " [prohibition] ");
4444
prohib = (xmlSchemaAttributeUseProhibPtr) use;
4445
name = prohib->name;
4446
tns = prohib->targetNamespace;
4447
} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4448
fprintf(output, " [reference] ");
4449
ref = (xmlSchemaQNameRefPtr) use;
4450
name = ref->name;
4451
tns = ref->targetNamespace;
4452
} else {
4453
fprintf(output, " [use] ");
4454
name = WXS_ATTRUSE_DECL_NAME(use);
4455
tns = WXS_ATTRUSE_DECL_TNS(use);
4456
}
4457
fprintf(output, "'%s'\n",
4458
(const char *) xmlSchemaFormatQName(&str, tns, name));
4459
FREE_AND_NULL(str);
4460
}
4461
}
4462
4463
/**
4464
* xmlSchemaTypeDump:
4465
* @output: the file output
4466
* @type: a type structure
4467
*
4468
* Dump a SchemaType structure
4469
*/
4470
static void
4471
xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4472
{
4473
if (type == NULL) {
4474
fprintf(output, "Type: NULL\n");
4475
return;
4476
}
4477
fprintf(output, "Type: ");
4478
if (type->name != NULL)
4479
fprintf(output, "'%s' ", type->name);
4480
else
4481
fprintf(output, "(no name) ");
4482
if (type->targetNamespace != NULL)
4483
fprintf(output, "ns '%s' ", type->targetNamespace);
4484
switch (type->type) {
4485
case XML_SCHEMA_TYPE_BASIC:
4486
fprintf(output, "[basic] ");
4487
break;
4488
case XML_SCHEMA_TYPE_SIMPLE:
4489
fprintf(output, "[simple] ");
4490
break;
4491
case XML_SCHEMA_TYPE_COMPLEX:
4492
fprintf(output, "[complex] ");
4493
break;
4494
case XML_SCHEMA_TYPE_SEQUENCE:
4495
fprintf(output, "[sequence] ");
4496
break;
4497
case XML_SCHEMA_TYPE_CHOICE:
4498
fprintf(output, "[choice] ");
4499
break;
4500
case XML_SCHEMA_TYPE_ALL:
4501
fprintf(output, "[all] ");
4502
break;
4503
case XML_SCHEMA_TYPE_UR:
4504
fprintf(output, "[ur] ");
4505
break;
4506
case XML_SCHEMA_TYPE_RESTRICTION:
4507
fprintf(output, "[restriction] ");
4508
break;
4509
case XML_SCHEMA_TYPE_EXTENSION:
4510
fprintf(output, "[extension] ");
4511
break;
4512
default:
4513
fprintf(output, "[unknown type %d] ", type->type);
4514
break;
4515
}
4516
fprintf(output, "content: ");
4517
switch (type->contentType) {
4518
case XML_SCHEMA_CONTENT_UNKNOWN:
4519
fprintf(output, "[unknown] ");
4520
break;
4521
case XML_SCHEMA_CONTENT_EMPTY:
4522
fprintf(output, "[empty] ");
4523
break;
4524
case XML_SCHEMA_CONTENT_ELEMENTS:
4525
fprintf(output, "[element] ");
4526
break;
4527
case XML_SCHEMA_CONTENT_MIXED:
4528
fprintf(output, "[mixed] ");
4529
break;
4530
case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4531
/* not used. */
4532
break;
4533
case XML_SCHEMA_CONTENT_BASIC:
4534
fprintf(output, "[basic] ");
4535
break;
4536
case XML_SCHEMA_CONTENT_SIMPLE:
4537
fprintf(output, "[simple] ");
4538
break;
4539
case XML_SCHEMA_CONTENT_ANY:
4540
fprintf(output, "[any] ");
4541
break;
4542
}
4543
fprintf(output, "\n");
4544
if (type->base != NULL) {
4545
fprintf(output, " base type: '%s'", type->base);
4546
if (type->baseNs != NULL)
4547
fprintf(output, " ns '%s'\n", type->baseNs);
4548
else
4549
fprintf(output, "\n");
4550
}
4551
if (type->attrUses != NULL)
4552
xmlSchemaAttrUsesDump(type->attrUses, output);
4553
if (type->annot != NULL)
4554
xmlSchemaAnnotDump(output, type->annot);
4555
#ifdef DUMP_CONTENT_MODEL
4556
if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4557
(type->subtypes != NULL)) {
4558
xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4559
output, 1);
4560
}
4561
#endif
4562
}
4563
4564
static void
4565
xmlSchemaTypeDumpEntry(void *type, void *output,
4566
const xmlChar *name ATTRIBUTE_UNUSED)
4567
{
4568
xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4569
}
4570
4571
/**
4572
* xmlSchemaDump:
4573
* @output: the file output
4574
* @schema: a schema structure
4575
*
4576
* Dump a Schema structure.
4577
*/
4578
void
4579
xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4580
{
4581
if (output == NULL)
4582
return;
4583
if (schema == NULL) {
4584
fprintf(output, "Schemas: NULL\n");
4585
return;
4586
}
4587
fprintf(output, "Schemas: ");
4588
if (schema->name != NULL)
4589
fprintf(output, "%s, ", schema->name);
4590
else
4591
fprintf(output, "no name, ");
4592
if (schema->targetNamespace != NULL)
4593
fprintf(output, "%s", (const char *) schema->targetNamespace);
4594
else
4595
fprintf(output, "no target namespace");
4596
fprintf(output, "\n");
4597
if (schema->annot != NULL)
4598
xmlSchemaAnnotDump(output, schema->annot);
4599
xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4600
xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4601
}
4602
4603
#endif /* LIBXML_OUTPUT_ENABLED */
4604
4605
/************************************************************************
4606
* *
4607
* Utilities *
4608
* *
4609
************************************************************************/
4610
4611
/**
4612
* xmlSchemaGetPropNode:
4613
* @node: the element node
4614
* @name: the name of the attribute
4615
*
4616
* Seeks an attribute with a name of @name in
4617
* no namespace.
4618
*
4619
* Returns the attribute or NULL if not present.
4620
*/
4621
static xmlAttrPtr
4622
xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4623
{
4624
xmlAttrPtr prop;
4625
4626
if ((node == NULL) || (name == NULL))
4627
return(NULL);
4628
prop = node->properties;
4629
while (prop != NULL) {
4630
if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4631
return(prop);
4632
prop = prop->next;
4633
}
4634
return (NULL);
4635
}
4636
4637
/**
4638
* xmlSchemaGetPropNodeNs:
4639
* @node: the element node
4640
* @uri: the uri
4641
* @name: the name of the attribute
4642
*
4643
* Seeks an attribute with a local name of @name and
4644
* a namespace URI of @uri.
4645
*
4646
* Returns the attribute or NULL if not present.
4647
*/
4648
static xmlAttrPtr
4649
xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4650
{
4651
xmlAttrPtr prop;
4652
4653
if ((node == NULL) || (name == NULL))
4654
return(NULL);
4655
prop = node->properties;
4656
while (prop != NULL) {
4657
if ((prop->ns != NULL) &&
4658
xmlStrEqual(prop->name, BAD_CAST name) &&
4659
xmlStrEqual(prop->ns->href, BAD_CAST uri))
4660
return(prop);
4661
prop = prop->next;
4662
}
4663
return (NULL);
4664
}
4665
4666
static const xmlChar *
4667
xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4668
{
4669
xmlChar *val;
4670
const xmlChar *ret;
4671
4672
val = xmlNodeGetContent(node);
4673
if (val == NULL)
4674
val = xmlStrdup((xmlChar *)"");
4675
ret = xmlDictLookup(ctxt->dict, val, -1);
4676
xmlFree(val);
4677
if (ret == NULL)
4678
xmlSchemaPErrMemory(ctxt, "getting node content", node);
4679
return(ret);
4680
}
4681
4682
static const xmlChar *
4683
xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4684
{
4685
return((const xmlChar*) xmlNodeGetContent(node));
4686
}
4687
4688
/**
4689
* xmlSchemaGetProp:
4690
* @ctxt: the parser context
4691
* @node: the node
4692
* @name: the property name
4693
*
4694
* Read a attribute value and internalize the string
4695
*
4696
* Returns the string or NULL if not present.
4697
*/
4698
static const xmlChar *
4699
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4700
const char *name)
4701
{
4702
xmlChar *val;
4703
const xmlChar *ret;
4704
4705
val = xmlGetNoNsProp(node, BAD_CAST name);
4706
if (val == NULL)
4707
return(NULL);
4708
ret = xmlDictLookup(ctxt->dict, val, -1);
4709
xmlFree(val);
4710
return(ret);
4711
}
4712
4713
/************************************************************************
4714
* *
4715
* Parsing functions *
4716
* *
4717
************************************************************************/
4718
4719
#define WXS_FIND_GLOBAL_ITEM(slot) \
4720
if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4721
ret = xmlHashLookup(schema->slot, name); \
4722
if (ret != NULL) goto exit; \
4723
} \
4724
if (xmlHashSize(schema->schemasImports) > 1) { \
4725
xmlSchemaImportPtr import; \
4726
if (nsName == NULL) \
4727
import = xmlHashLookup(schema->schemasImports, \
4728
XML_SCHEMAS_NO_NAMESPACE); \
4729
else \
4730
import = xmlHashLookup(schema->schemasImports, nsName); \
4731
if (import == NULL) \
4732
goto exit; \
4733
ret = xmlHashLookup(import->schema->slot, name); \
4734
}
4735
4736
/**
4737
* xmlSchemaGetElem:
4738
* @schema: the schema context
4739
* @name: the element name
4740
* @ns: the element namespace
4741
*
4742
* Lookup a global element declaration in the schema.
4743
*
4744
* Returns the element declaration or NULL if not found.
4745
*/
4746
static xmlSchemaElementPtr
4747
xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4748
const xmlChar * nsName)
4749
{
4750
xmlSchemaElementPtr ret = NULL;
4751
4752
if ((name == NULL) || (schema == NULL))
4753
return(NULL);
4754
if (schema != NULL) {
4755
WXS_FIND_GLOBAL_ITEM(elemDecl)
4756
}
4757
exit:
4758
return (ret);
4759
}
4760
4761
/**
4762
* xmlSchemaGetType:
4763
* @schema: the main schema
4764
* @name: the type's name
4765
* nsName: the type's namespace
4766
*
4767
* Lookup a type in the schemas or the predefined types
4768
*
4769
* Returns the group definition or NULL if not found.
4770
*/
4771
static xmlSchemaTypePtr
4772
xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4773
const xmlChar * nsName)
4774
{
4775
xmlSchemaTypePtr ret = NULL;
4776
4777
if (name == NULL)
4778
return (NULL);
4779
/* First try the built-in types. */
4780
if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4781
ret = xmlSchemaGetPredefinedType(name, nsName);
4782
if (ret != NULL)
4783
goto exit;
4784
/*
4785
* Note that we try the parsed schemas as well here
4786
* since one might have parsed the S4S, which contain more
4787
* than the built-in types.
4788
* TODO: Can we optimize this?
4789
*/
4790
}
4791
if (schema != NULL) {
4792
WXS_FIND_GLOBAL_ITEM(typeDecl)
4793
}
4794
exit:
4795
4796
return (ret);
4797
}
4798
4799
/**
4800
* xmlSchemaGetAttributeDecl:
4801
* @schema: the context of the schema
4802
* @name: the name of the attribute
4803
* @ns: the target namespace of the attribute
4804
*
4805
* Lookup a an attribute in the schema or imported schemas
4806
*
4807
* Returns the attribute declaration or NULL if not found.
4808
*/
4809
static xmlSchemaAttributePtr
4810
xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4811
const xmlChar * nsName)
4812
{
4813
xmlSchemaAttributePtr ret = NULL;
4814
4815
if ((name == NULL) || (schema == NULL))
4816
return (NULL);
4817
if (schema != NULL) {
4818
WXS_FIND_GLOBAL_ITEM(attrDecl)
4819
}
4820
exit:
4821
return (ret);
4822
}
4823
4824
/**
4825
* xmlSchemaGetAttributeGroup:
4826
* @schema: the context of the schema
4827
* @name: the name of the attribute group
4828
* @ns: the target namespace of the attribute group
4829
*
4830
* Lookup a an attribute group in the schema or imported schemas
4831
*
4832
* Returns the attribute group definition or NULL if not found.
4833
*/
4834
static xmlSchemaAttributeGroupPtr
4835
xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4836
const xmlChar * nsName)
4837
{
4838
xmlSchemaAttributeGroupPtr ret = NULL;
4839
4840
if ((name == NULL) || (schema == NULL))
4841
return (NULL);
4842
if (schema != NULL) {
4843
WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4844
}
4845
exit:
4846
/* TODO:
4847
if ((ret != NULL) && (ret->redef != NULL)) {
4848
* Return the last redefinition. *
4849
ret = ret->redef;
4850
}
4851
*/
4852
return (ret);
4853
}
4854
4855
/**
4856
* xmlSchemaGetGroup:
4857
* @schema: the context of the schema
4858
* @name: the name of the group
4859
* @ns: the target namespace of the group
4860
*
4861
* Lookup a group in the schema or imported schemas
4862
*
4863
* Returns the group definition or NULL if not found.
4864
*/
4865
static xmlSchemaModelGroupDefPtr
4866
xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4867
const xmlChar * nsName)
4868
{
4869
xmlSchemaModelGroupDefPtr ret = NULL;
4870
4871
if ((name == NULL) || (schema == NULL))
4872
return (NULL);
4873
if (schema != NULL) {
4874
WXS_FIND_GLOBAL_ITEM(groupDecl)
4875
}
4876
exit:
4877
4878
return (ret);
4879
}
4880
4881
static xmlSchemaNotationPtr
4882
xmlSchemaGetNotation(xmlSchemaPtr schema,
4883
const xmlChar *name,
4884
const xmlChar *nsName)
4885
{
4886
xmlSchemaNotationPtr ret = NULL;
4887
4888
if ((name == NULL) || (schema == NULL))
4889
return (NULL);
4890
if (schema != NULL) {
4891
WXS_FIND_GLOBAL_ITEM(notaDecl)
4892
}
4893
exit:
4894
return (ret);
4895
}
4896
4897
static xmlSchemaIDCPtr
4898
xmlSchemaGetIDC(xmlSchemaPtr schema,
4899
const xmlChar *name,
4900
const xmlChar *nsName)
4901
{
4902
xmlSchemaIDCPtr ret = NULL;
4903
4904
if ((name == NULL) || (schema == NULL))
4905
return (NULL);
4906
if (schema != NULL) {
4907
WXS_FIND_GLOBAL_ITEM(idcDef)
4908
}
4909
exit:
4910
return (ret);
4911
}
4912
4913
/**
4914
* xmlSchemaGetNamedComponent:
4915
* @schema: the schema
4916
* @name: the name of the group
4917
* @ns: the target namespace of the group
4918
*
4919
* Lookup a group in the schema or imported schemas
4920
*
4921
* Returns the group definition or NULL if not found.
4922
*/
4923
static xmlSchemaBasicItemPtr
4924
xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4925
xmlSchemaTypeType itemType,
4926
const xmlChar *name,
4927
const xmlChar *targetNs)
4928
{
4929
switch (itemType) {
4930
case XML_SCHEMA_TYPE_GROUP:
4931
return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4932
name, targetNs));
4933
case XML_SCHEMA_TYPE_ELEMENT:
4934
return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4935
name, targetNs));
4936
default:
4937
TODO
4938
return (NULL);
4939
}
4940
}
4941
4942
/************************************************************************
4943
* *
4944
* Parsing functions *
4945
* *
4946
************************************************************************/
4947
4948
#define IS_BLANK_NODE(n) \
4949
(((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4950
4951
/**
4952
* xmlSchemaIsBlank:
4953
* @str: a string
4954
* @len: the length of the string or -1
4955
*
4956
* Check if a string is ignorable
4957
*
4958
* Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4959
*/
4960
static int
4961
xmlSchemaIsBlank(xmlChar * str, int len)
4962
{
4963
if (str == NULL)
4964
return (1);
4965
if (len < 0) {
4966
while (*str != 0) {
4967
if (!(IS_BLANK_CH(*str)))
4968
return (0);
4969
str++;
4970
}
4971
} else while ((*str != 0) && (len != 0)) {
4972
if (!(IS_BLANK_CH(*str)))
4973
return (0);
4974
str++;
4975
len--;
4976
}
4977
4978
return (1);
4979
}
4980
4981
#define WXS_COMP_NAME(c, t) ((t) (c))->name
4982
#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4983
/*
4984
* xmlSchemaFindRedefCompInGraph:
4985
* ATTENTION TODO: This uses pointer comp. for strings.
4986
*/
4987
static xmlSchemaBasicItemPtr
4988
xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
4989
xmlSchemaTypeType type,
4990
const xmlChar *name,
4991
const xmlChar *nsName)
4992
{
4993
xmlSchemaBasicItemPtr ret;
4994
int i;
4995
4996
if ((bucket == NULL) || (name == NULL))
4997
return(NULL);
4998
if ((bucket->globals == NULL) ||
4999
(bucket->globals->nbItems == 0))
5000
goto subschemas;
5001
/*
5002
* Search in global components.
5003
*/
5004
for (i = 0; i < bucket->globals->nbItems; i++) {
5005
ret = bucket->globals->items[i];
5006
if (ret->type == type) {
5007
switch (type) {
5008
case XML_SCHEMA_TYPE_COMPLEX:
5009
case XML_SCHEMA_TYPE_SIMPLE:
5010
if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5011
(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5012
nsName))
5013
{
5014
return(ret);
5015
}
5016
break;
5017
case XML_SCHEMA_TYPE_GROUP:
5018
if ((WXS_COMP_NAME(ret,
5019
xmlSchemaModelGroupDefPtr) == name) &&
5020
(WXS_COMP_TNS(ret,
5021
xmlSchemaModelGroupDefPtr) == nsName))
5022
{
5023
return(ret);
5024
}
5025
break;
5026
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5027
if ((WXS_COMP_NAME(ret,
5028
xmlSchemaAttributeGroupPtr) == name) &&
5029
(WXS_COMP_TNS(ret,
5030
xmlSchemaAttributeGroupPtr) == nsName))
5031
{
5032
return(ret);
5033
}
5034
break;
5035
default:
5036
/* Should not be hit. */
5037
return(NULL);
5038
}
5039
}
5040
}
5041
subschemas:
5042
/*
5043
* Process imported/included schemas.
5044
*/
5045
if (bucket->relations != NULL) {
5046
xmlSchemaSchemaRelationPtr rel = bucket->relations;
5047
5048
/*
5049
* TODO: Marking the bucket will not avoid multiple searches
5050
* in the same schema, but avoids at least circularity.
5051
*/
5052
bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5053
do {
5054
if ((rel->bucket != NULL) &&
5055
((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5056
ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5057
type, name, nsName);
5058
if (ret != NULL)
5059
return(ret);
5060
}
5061
rel = rel->next;
5062
} while (rel != NULL);
5063
bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5064
}
5065
return(NULL);
5066
}
5067
5068
/**
5069
* xmlSchemaAddNotation:
5070
* @ctxt: a schema parser context
5071
* @schema: the schema being built
5072
* @name: the item name
5073
*
5074
* Add an XML schema annotation declaration
5075
* *WARNING* this interface is highly subject to change
5076
*
5077
* Returns the new structure or NULL in case of error
5078
*/
5079
static xmlSchemaNotationPtr
5080
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5081
const xmlChar *name, const xmlChar *nsName,
5082
xmlNodePtr node ATTRIBUTE_UNUSED)
5083
{
5084
xmlSchemaNotationPtr ret = NULL;
5085
5086
if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5087
return (NULL);
5088
5089
ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5090
if (ret == NULL) {
5091
xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5092
return (NULL);
5093
}
5094
memset(ret, 0, sizeof(xmlSchemaNotation));
5095
ret->type = XML_SCHEMA_TYPE_NOTATION;
5096
ret->name = name;
5097
ret->targetNamespace = nsName;
5098
/* TODO: do we need the node to be set?
5099
* ret->node = node;*/
5100
WXS_ADD_GLOBAL(ctxt, ret);
5101
return (ret);
5102
}
5103
5104
/**
5105
* xmlSchemaAddAttribute:
5106
* @ctxt: a schema parser context
5107
* @schema: the schema being built
5108
* @name: the item name
5109
* @namespace: the namespace
5110
*
5111
* Add an XML schema Attribute declaration
5112
* *WARNING* this interface is highly subject to change
5113
*
5114
* Returns the new structure or NULL in case of error
5115
*/
5116
static xmlSchemaAttributePtr
5117
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5118
const xmlChar * name, const xmlChar * nsName,
5119
xmlNodePtr node, int topLevel)
5120
{
5121
xmlSchemaAttributePtr ret = NULL;
5122
5123
if ((ctxt == NULL) || (schema == NULL))
5124
return (NULL);
5125
5126
ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5127
if (ret == NULL) {
5128
xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5129
return (NULL);
5130
}
5131
memset(ret, 0, sizeof(xmlSchemaAttribute));
5132
ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5133
ret->node = node;
5134
ret->name = name;
5135
ret->targetNamespace = nsName;
5136
5137
if (topLevel)
5138
WXS_ADD_GLOBAL(ctxt, ret);
5139
else
5140
WXS_ADD_LOCAL(ctxt, ret);
5141
WXS_ADD_PENDING(ctxt, ret);
5142
return (ret);
5143
}
5144
5145
/**
5146
* xmlSchemaAddAttributeUse:
5147
* @ctxt: a schema parser context
5148
* @schema: the schema being built
5149
* @name: the item name
5150
* @namespace: the namespace
5151
*
5152
* Add an XML schema Attribute declaration
5153
* *WARNING* this interface is highly subject to change
5154
*
5155
* Returns the new structure or NULL in case of error
5156
*/
5157
static xmlSchemaAttributeUsePtr
5158
xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5159
xmlNodePtr node)
5160
{
5161
xmlSchemaAttributeUsePtr ret = NULL;
5162
5163
if (pctxt == NULL)
5164
return (NULL);
5165
5166
ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5167
if (ret == NULL) {
5168
xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5169
return (NULL);
5170
}
5171
memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5172
ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5173
ret->node = node;
5174
5175
WXS_ADD_LOCAL(pctxt, ret);
5176
return (ret);
5177
}
5178
5179
/*
5180
* xmlSchemaAddRedef:
5181
*
5182
* Adds a redefinition information. This is used at a later stage to:
5183
* resolve references to the redefined components and to check constraints.
5184
*/
5185
static xmlSchemaRedefPtr
5186
xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5187
xmlSchemaBucketPtr targetBucket,
5188
void *item,
5189
const xmlChar *refName,
5190
const xmlChar *refTargetNs)
5191
{
5192
xmlSchemaRedefPtr ret;
5193
5194
ret = (xmlSchemaRedefPtr)
5195
xmlMalloc(sizeof(xmlSchemaRedef));
5196
if (ret == NULL) {
5197
xmlSchemaPErrMemory(pctxt,
5198
"allocating redefinition info", NULL);
5199
return (NULL);
5200
}
5201
memset(ret, 0, sizeof(xmlSchemaRedef));
5202
ret->item = item;
5203
ret->targetBucket = targetBucket;
5204
ret->refName = refName;
5205
ret->refTargetNs = refTargetNs;
5206
if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5207
WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5208
else
5209
WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5210
WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5211
5212
return (ret);
5213
}
5214
5215
/**
5216
* xmlSchemaAddAttributeGroupDefinition:
5217
* @ctxt: a schema parser context
5218
* @schema: the schema being built
5219
* @name: the item name
5220
* @nsName: the target namespace
5221
* @node: the corresponding node
5222
*
5223
* Add an XML schema Attribute Group definition.
5224
*
5225
* Returns the new structure or NULL in case of error
5226
*/
5227
static xmlSchemaAttributeGroupPtr
5228
xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5229
xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5230
const xmlChar *name,
5231
const xmlChar *nsName,
5232
xmlNodePtr node)
5233
{
5234
xmlSchemaAttributeGroupPtr ret = NULL;
5235
5236
if ((pctxt == NULL) || (name == NULL))
5237
return (NULL);
5238
5239
ret = (xmlSchemaAttributeGroupPtr)
5240
xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5241
if (ret == NULL) {
5242
xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5243
return (NULL);
5244
}
5245
memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5246
ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5247
ret->name = name;
5248
ret->targetNamespace = nsName;
5249
ret->node = node;
5250
5251
/* TODO: Remove the flag. */
5252
ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5253
if (pctxt->isRedefine) {
5254
pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5255
ret, name, nsName);
5256
if (pctxt->redef == NULL) {
5257
xmlFree(ret);
5258
return(NULL);
5259
}
5260
pctxt->redefCounter = 0;
5261
}
5262
WXS_ADD_GLOBAL(pctxt, ret);
5263
WXS_ADD_PENDING(pctxt, ret);
5264
return (ret);
5265
}
5266
5267
/**
5268
* xmlSchemaAddElement:
5269
* @ctxt: a schema parser context
5270
* @schema: the schema being built
5271
* @name: the type name
5272
* @namespace: the type namespace
5273
*
5274
* Add an XML schema Element declaration
5275
* *WARNING* this interface is highly subject to change
5276
*
5277
* Returns the new structure or NULL in case of error
5278
*/
5279
static xmlSchemaElementPtr
5280
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5281
const xmlChar * name, const xmlChar * nsName,
5282
xmlNodePtr node, int topLevel)
5283
{
5284
xmlSchemaElementPtr ret = NULL;
5285
5286
if ((ctxt == NULL) || (name == NULL))
5287
return (NULL);
5288
5289
ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5290
if (ret == NULL) {
5291
xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5292
return (NULL);
5293
}
5294
memset(ret, 0, sizeof(xmlSchemaElement));
5295
ret->type = XML_SCHEMA_TYPE_ELEMENT;
5296
ret->name = name;
5297
ret->targetNamespace = nsName;
5298
ret->node = node;
5299
5300
if (topLevel)
5301
WXS_ADD_GLOBAL(ctxt, ret);
5302
else
5303
WXS_ADD_LOCAL(ctxt, ret);
5304
WXS_ADD_PENDING(ctxt, ret);
5305
return (ret);
5306
}
5307
5308
/**
5309
* xmlSchemaAddType:
5310
* @ctxt: a schema parser context
5311
* @schema: the schema being built
5312
* @name: the item name
5313
* @namespace: the namespace
5314
*
5315
* Add an XML schema item
5316
* *WARNING* this interface is highly subject to change
5317
*
5318
* Returns the new structure or NULL in case of error
5319
*/
5320
static xmlSchemaTypePtr
5321
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5322
xmlSchemaTypeType type,
5323
const xmlChar * name, const xmlChar * nsName,
5324
xmlNodePtr node, int topLevel)
5325
{
5326
xmlSchemaTypePtr ret = NULL;
5327
5328
if ((ctxt == NULL) || (schema == NULL))
5329
return (NULL);
5330
5331
ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5332
if (ret == NULL) {
5333
xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5334
return (NULL);
5335
}
5336
memset(ret, 0, sizeof(xmlSchemaType));
5337
ret->type = type;
5338
ret->name = name;
5339
ret->targetNamespace = nsName;
5340
ret->node = node;
5341
if (topLevel) {
5342
if (ctxt->isRedefine) {
5343
ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5344
ret, name, nsName);
5345
if (ctxt->redef == NULL) {
5346
xmlFree(ret);
5347
return(NULL);
5348
}
5349
ctxt->redefCounter = 0;
5350
}
5351
WXS_ADD_GLOBAL(ctxt, ret);
5352
} else
5353
WXS_ADD_LOCAL(ctxt, ret);
5354
WXS_ADD_PENDING(ctxt, ret);
5355
return (ret);
5356
}
5357
5358
static xmlSchemaQNameRefPtr
5359
xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5360
xmlSchemaTypeType refType,
5361
const xmlChar *refName,
5362
const xmlChar *refNs)
5363
{
5364
xmlSchemaQNameRefPtr ret;
5365
5366
ret = (xmlSchemaQNameRefPtr)
5367
xmlMalloc(sizeof(xmlSchemaQNameRef));
5368
if (ret == NULL) {
5369
xmlSchemaPErrMemory(pctxt,
5370
"allocating QName reference item", NULL);
5371
return (NULL);
5372
}
5373
ret->node = NULL;
5374
ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5375
ret->name = refName;
5376
ret->targetNamespace = refNs;
5377
ret->item = NULL;
5378
ret->itemType = refType;
5379
/*
5380
* Store the reference item in the schema.
5381
*/
5382
WXS_ADD_LOCAL(pctxt, ret);
5383
return (ret);
5384
}
5385
5386
static xmlSchemaAttributeUseProhibPtr
5387
xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5388
{
5389
xmlSchemaAttributeUseProhibPtr ret;
5390
5391
ret = (xmlSchemaAttributeUseProhibPtr)
5392
xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5393
if (ret == NULL) {
5394
xmlSchemaPErrMemory(pctxt,
5395
"allocating attribute use prohibition", NULL);
5396
return (NULL);
5397
}
5398
memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5399
ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5400
WXS_ADD_LOCAL(pctxt, ret);
5401
return (ret);
5402
}
5403
5404
5405
/**
5406
* xmlSchemaAddModelGroup:
5407
* @ctxt: a schema parser context
5408
* @schema: the schema being built
5409
* @type: the "compositor" type of the model group
5410
* @node: the node in the schema doc
5411
*
5412
* Adds a schema model group
5413
* *WARNING* this interface is highly subject to change
5414
*
5415
* Returns the new structure or NULL in case of error
5416
*/
5417
static xmlSchemaModelGroupPtr
5418
xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5419
xmlSchemaPtr schema,
5420
xmlSchemaTypeType type,
5421
xmlNodePtr node)
5422
{
5423
xmlSchemaModelGroupPtr ret = NULL;
5424
5425
if ((ctxt == NULL) || (schema == NULL))
5426
return (NULL);
5427
5428
ret = (xmlSchemaModelGroupPtr)
5429
xmlMalloc(sizeof(xmlSchemaModelGroup));
5430
if (ret == NULL) {
5431
xmlSchemaPErrMemory(ctxt, "allocating model group component",
5432
NULL);
5433
return (NULL);
5434
}
5435
memset(ret, 0, sizeof(xmlSchemaModelGroup));
5436
ret->type = type;
5437
ret->node = node;
5438
WXS_ADD_LOCAL(ctxt, ret);
5439
if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5440
(type == XML_SCHEMA_TYPE_CHOICE))
5441
WXS_ADD_PENDING(ctxt, ret);
5442
return (ret);
5443
}
5444
5445
5446
/**
5447
* xmlSchemaAddParticle:
5448
* @ctxt: a schema parser context
5449
* @schema: the schema being built
5450
* @node: the corresponding node in the schema doc
5451
* @min: the minOccurs
5452
* @max: the maxOccurs
5453
*
5454
* Adds an XML schema particle component.
5455
* *WARNING* this interface is highly subject to change
5456
*
5457
* Returns the new structure or NULL in case of error
5458
*/
5459
static xmlSchemaParticlePtr
5460
xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5461
xmlNodePtr node, int min, int max)
5462
{
5463
xmlSchemaParticlePtr ret = NULL;
5464
if (ctxt == NULL)
5465
return (NULL);
5466
5467
ret = (xmlSchemaParticlePtr)
5468
xmlMalloc(sizeof(xmlSchemaParticle));
5469
if (ret == NULL) {
5470
xmlSchemaPErrMemory(ctxt, "allocating particle component",
5471
NULL);
5472
return (NULL);
5473
}
5474
ret->type = XML_SCHEMA_TYPE_PARTICLE;
5475
ret->annot = NULL;
5476
ret->node = node;
5477
ret->minOccurs = min;
5478
ret->maxOccurs = max;
5479
ret->next = NULL;
5480
ret->children = NULL;
5481
5482
WXS_ADD_LOCAL(ctxt, ret);
5483
/*
5484
* Note that addition to pending components will be done locally
5485
* to the specific parsing function, since the most particles
5486
* need not to be fixed up (i.e. the reference to be resolved).
5487
* REMOVED: WXS_ADD_PENDING(ctxt, ret);
5488
*/
5489
return (ret);
5490
}
5491
5492
/**
5493
* xmlSchemaAddModelGroupDefinition:
5494
* @ctxt: a schema validation context
5495
* @schema: the schema being built
5496
* @name: the group name
5497
*
5498
* Add an XML schema Group definition
5499
*
5500
* Returns the new structure or NULL in case of error
5501
*/
5502
static xmlSchemaModelGroupDefPtr
5503
xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5504
xmlSchemaPtr schema,
5505
const xmlChar *name,
5506
const xmlChar *nsName,
5507
xmlNodePtr node)
5508
{
5509
xmlSchemaModelGroupDefPtr ret = NULL;
5510
5511
if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5512
return (NULL);
5513
5514
ret = (xmlSchemaModelGroupDefPtr)
5515
xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5516
if (ret == NULL) {
5517
xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5518
return (NULL);
5519
}
5520
memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5521
ret->name = name;
5522
ret->type = XML_SCHEMA_TYPE_GROUP;
5523
ret->node = node;
5524
ret->targetNamespace = nsName;
5525
5526
if (ctxt->isRedefine) {
5527
ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5528
ret, name, nsName);
5529
if (ctxt->redef == NULL) {
5530
xmlFree(ret);
5531
return(NULL);
5532
}
5533
ctxt->redefCounter = 0;
5534
}
5535
WXS_ADD_GLOBAL(ctxt, ret);
5536
WXS_ADD_PENDING(ctxt, ret);
5537
return (ret);
5538
}
5539
5540
/**
5541
* xmlSchemaNewWildcardNs:
5542
* @ctxt: a schema validation context
5543
*
5544
* Creates a new wildcard namespace constraint.
5545
*
5546
* Returns the new structure or NULL in case of error
5547
*/
5548
static xmlSchemaWildcardNsPtr
5549
xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5550
{
5551
xmlSchemaWildcardNsPtr ret;
5552
5553
ret = (xmlSchemaWildcardNsPtr)
5554
xmlMalloc(sizeof(xmlSchemaWildcardNs));
5555
if (ret == NULL) {
5556
xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5557
return (NULL);
5558
}
5559
ret->value = NULL;
5560
ret->next = NULL;
5561
return (ret);
5562
}
5563
5564
static xmlSchemaIDCPtr
5565
xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5566
const xmlChar *name, const xmlChar *nsName,
5567
int category, xmlNodePtr node)
5568
{
5569
xmlSchemaIDCPtr ret = NULL;
5570
5571
if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5572
return (NULL);
5573
5574
ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5575
if (ret == NULL) {
5576
xmlSchemaPErrMemory(ctxt,
5577
"allocating an identity-constraint definition", NULL);
5578
return (NULL);
5579
}
5580
memset(ret, 0, sizeof(xmlSchemaIDC));
5581
/* The target namespace of the parent element declaration. */
5582
ret->targetNamespace = nsName;
5583
ret->name = name;
5584
ret->type = category;
5585
ret->node = node;
5586
5587
WXS_ADD_GLOBAL(ctxt, ret);
5588
/*
5589
* Only keyrefs need to be fixup up.
5590
*/
5591
if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5592
WXS_ADD_PENDING(ctxt, ret);
5593
return (ret);
5594
}
5595
5596
/**
5597
* xmlSchemaAddWildcard:
5598
* @ctxt: a schema validation context
5599
* @schema: a schema
5600
*
5601
* Adds a wildcard.
5602
* It corresponds to a xsd:anyAttribute and xsd:any.
5603
*
5604
* Returns the new structure or NULL in case of error
5605
*/
5606
static xmlSchemaWildcardPtr
5607
xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5608
xmlSchemaTypeType type, xmlNodePtr node)
5609
{
5610
xmlSchemaWildcardPtr ret = NULL;
5611
5612
if ((ctxt == NULL) || (schema == NULL))
5613
return (NULL);
5614
5615
ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5616
if (ret == NULL) {
5617
xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5618
return (NULL);
5619
}
5620
memset(ret, 0, sizeof(xmlSchemaWildcard));
5621
ret->type = type;
5622
ret->node = node;
5623
WXS_ADD_LOCAL(ctxt, ret);
5624
return (ret);
5625
}
5626
5627
static void
5628
xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5629
{
5630
if (group == NULL)
5631
return;
5632
if (group->members != NULL)
5633
xmlSchemaItemListFree(group->members);
5634
xmlFree(group);
5635
}
5636
5637
static void
5638
xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5639
{
5640
xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5641
}
5642
5643
static xmlSchemaSubstGroupPtr
5644
xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5645
xmlSchemaElementPtr head)
5646
{
5647
xmlSchemaSubstGroupPtr ret;
5648
5649
/* Init subst group hash. */
5650
if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5651
WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5652
if (WXS_SUBST_GROUPS(pctxt) == NULL)
5653
return(NULL);
5654
}
5655
/* Create a new substitution group. */
5656
ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5657
if (ret == NULL) {
5658
xmlSchemaPErrMemory(NULL,
5659
"allocating a substitution group container", NULL);
5660
return(NULL);
5661
}
5662
memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5663
ret->head = head;
5664
/* Create list of members. */
5665
ret->members = xmlSchemaItemListCreate();
5666
if (ret->members == NULL) {
5667
xmlSchemaSubstGroupFree(ret);
5668
return(NULL);
5669
}
5670
/* Add subst group to hash. */
5671
if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5672
head->name, head->targetNamespace, ret) != 0) {
5673
PERROR_INT("xmlSchemaSubstGroupAdd",
5674
"failed to add a new substitution container");
5675
xmlSchemaSubstGroupFree(ret);
5676
return(NULL);
5677
}
5678
return(ret);
5679
}
5680
5681
static xmlSchemaSubstGroupPtr
5682
xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5683
xmlSchemaElementPtr head)
5684
{
5685
if (WXS_SUBST_GROUPS(pctxt) == NULL)
5686
return(NULL);
5687
return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5688
head->name, head->targetNamespace));
5689
5690
}
5691
5692
/**
5693
* xmlSchemaAddElementSubstitutionMember:
5694
* @pctxt: a schema parser context
5695
* @head: the head of the substitution group
5696
* @member: the new member of the substitution group
5697
*
5698
* Allocate a new annotation structure.
5699
*
5700
* Returns the newly allocated structure or NULL in case or error
5701
*/
5702
static int
5703
xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5704
xmlSchemaElementPtr head,
5705
xmlSchemaElementPtr member)
5706
{
5707
xmlSchemaSubstGroupPtr substGroup = NULL;
5708
5709
if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5710
return (-1);
5711
5712
substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5713
if (substGroup == NULL)
5714
substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5715
if (substGroup == NULL)
5716
return(-1);
5717
if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5718
return(-1);
5719
return(0);
5720
}
5721
5722
/************************************************************************
5723
* *
5724
* Utilities for parsing *
5725
* *
5726
************************************************************************/
5727
5728
/**
5729
* xmlSchemaPValAttrNodeQNameValue:
5730
* @ctxt: a schema parser context
5731
* @schema: the schema context
5732
* @ownerItem: the parent as a schema object
5733
* @value: the QName value
5734
* @uri: the resulting namespace URI if found
5735
* @local: the resulting local part if found, the attribute value otherwise
5736
*
5737
* Extracts the local name and the URI of a QName value and validates it.
5738
* This one is intended to be used on attribute values that
5739
* should resolve to schema components.
5740
*
5741
* Returns 0, in case the QName is valid, a positive error code
5742
* if not valid and -1 if an internal error occurs.
5743
*/
5744
static int
5745
xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5746
xmlSchemaPtr schema,
5747
xmlSchemaBasicItemPtr ownerItem,
5748
xmlAttrPtr attr,
5749
const xmlChar *value,
5750
const xmlChar **uri,
5751
const xmlChar **local)
5752
{
5753
const xmlChar *pref;
5754
xmlNsPtr ns;
5755
int len, ret;
5756
5757
*uri = NULL;
5758
*local = NULL;
5759
ret = xmlValidateQName(value, 1);
5760
if (ret > 0) {
5761
xmlSchemaPSimpleTypeErr(ctxt,
5762
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5763
ownerItem, (xmlNodePtr) attr,
5764
xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5765
NULL, value, NULL, NULL, NULL);
5766
*local = value;
5767
return (ctxt->err);
5768
} else if (ret < 0)
5769
return (-1);
5770
5771
if (!strchr((char *) value, ':')) {
5772
ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5773
if (ns && ns->href && ns->href[0])
5774
*uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5775
else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5776
/* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5777
* parser context. */
5778
/*
5779
* This one takes care of included schemas with no
5780
* target namespace.
5781
*/
5782
*uri = ctxt->targetNamespace;
5783
}
5784
*local = xmlDictLookup(ctxt->dict, value, -1);
5785
return (0);
5786
}
5787
/*
5788
* At this point xmlSplitQName3 has to return a local name.
5789
*/
5790
*local = xmlSplitQName3(value, &len);
5791
*local = xmlDictLookup(ctxt->dict, *local, -1);
5792
pref = xmlDictLookup(ctxt->dict, value, len);
5793
ns = xmlSearchNs(attr->doc, attr->parent, pref);
5794
if (ns == NULL) {
5795
xmlSchemaPSimpleTypeErr(ctxt,
5796
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5797
ownerItem, (xmlNodePtr) attr,
5798
xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5799
"The value '%s' of simple type 'xs:QName' has no "
5800
"corresponding namespace declaration in scope", value, NULL);
5801
return (ctxt->err);
5802
} else {
5803
*uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5804
}
5805
return (0);
5806
}
5807
5808
/**
5809
* xmlSchemaPValAttrNodeQName:
5810
* @ctxt: a schema parser context
5811
* @schema: the schema context
5812
* @ownerItem: the owner as a schema object
5813
* @attr: the attribute node
5814
* @uri: the resulting namespace URI if found
5815
* @local: the resulting local part if found, the attribute value otherwise
5816
*
5817
* Extracts and validates the QName of an attribute value.
5818
* This one is intended to be used on attribute values that
5819
* should resolve to schema components.
5820
*
5821
* Returns 0, in case the QName is valid, a positive error code
5822
* if not valid and -1 if an internal error occurs.
5823
*/
5824
static int
5825
xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5826
xmlSchemaPtr schema,
5827
xmlSchemaBasicItemPtr ownerItem,
5828
xmlAttrPtr attr,
5829
const xmlChar **uri,
5830
const xmlChar **local)
5831
{
5832
const xmlChar *value;
5833
5834
value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5835
return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5836
ownerItem, attr, value, uri, local));
5837
}
5838
5839
/**
5840
* xmlSchemaPValAttrQName:
5841
* @ctxt: a schema parser context
5842
* @schema: the schema context
5843
* @ownerItem: the owner as a schema object
5844
* @ownerElem: the parent node of the attribute
5845
* @name: the name of the attribute
5846
* @uri: the resulting namespace URI if found
5847
* @local: the resulting local part if found, the attribute value otherwise
5848
*
5849
* Extracts and validates the QName of an attribute value.
5850
*
5851
* Returns 0, in case the QName is valid, a positive error code
5852
* if not valid and -1 if an internal error occurs.
5853
*/
5854
static int
5855
xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5856
xmlSchemaPtr schema,
5857
xmlSchemaBasicItemPtr ownerItem,
5858
xmlNodePtr ownerElem,
5859
const char *name,
5860
const xmlChar **uri,
5861
const xmlChar **local)
5862
{
5863
xmlAttrPtr attr;
5864
5865
attr = xmlSchemaGetPropNode(ownerElem, name);
5866
if (attr == NULL) {
5867
*local = NULL;
5868
*uri = NULL;
5869
return (0);
5870
}
5871
return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5872
ownerItem, attr, uri, local));
5873
}
5874
5875
/**
5876
* xmlSchemaPValAttrID:
5877
* @ctxt: a schema parser context
5878
*
5879
* Extracts and validates the ID of an attribute value.
5880
*
5881
* Returns 0, in case the ID is valid, a positive error code
5882
* if not valid and -1 if an internal error occurs.
5883
*/
5884
static int
5885
xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5886
{
5887
int ret;
5888
const xmlChar *value;
5889
5890
if (attr == NULL)
5891
return(0);
5892
value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5893
ret = xmlValidateNCName(value, 1);
5894
if (ret == 0) {
5895
/*
5896
* NOTE: the IDness might have already be declared in the DTD
5897
*/
5898
if (attr->atype != XML_ATTRIBUTE_ID) {
5899
xmlIDPtr res;
5900
xmlChar *strip;
5901
5902
/*
5903
* TODO: Use xmlSchemaStrip here; it's not exported at this
5904
* moment.
5905
*/
5906
strip = xmlSchemaCollapseString(value);
5907
if (strip != NULL) {
5908
xmlFree((xmlChar *) value);
5909
value = strip;
5910
}
5911
res = xmlAddID(NULL, attr->doc, value, attr);
5912
if (res == NULL) {
5913
ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5914
xmlSchemaPSimpleTypeErr(ctxt,
5915
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5916
NULL, (xmlNodePtr) attr,
5917
xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5918
NULL, NULL, "Duplicate value '%s' of simple "
5919
"type 'xs:ID'", value, NULL);
5920
} else
5921
attr->atype = XML_ATTRIBUTE_ID;
5922
}
5923
} else if (ret > 0) {
5924
ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5925
xmlSchemaPSimpleTypeErr(ctxt,
5926
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5927
NULL, (xmlNodePtr) attr,
5928
xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5929
NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5930
"not a valid 'xs:NCName'",
5931
value, NULL);
5932
}
5933
if (value != NULL)
5934
xmlFree((xmlChar *)value);
5935
5936
return (ret);
5937
}
5938
5939
static int
5940
xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5941
xmlNodePtr ownerElem,
5942
const xmlChar *name)
5943
{
5944
xmlAttrPtr attr;
5945
5946
attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5947
if (attr == NULL)
5948
return(0);
5949
return(xmlSchemaPValAttrNodeID(ctxt, attr));
5950
5951
}
5952
5953
/**
5954
* xmlGetMaxOccurs:
5955
* @ctxt: a schema validation context
5956
* @node: a subtree containing XML Schema information
5957
*
5958
* Get the maxOccurs property
5959
*
5960
* Returns the default if not found, or the value
5961
*/
5962
static int
5963
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5964
int min, int max, int def, const char *expected)
5965
{
5966
const xmlChar *val, *cur;
5967
int ret = 0;
5968
xmlAttrPtr attr;
5969
5970
attr = xmlSchemaGetPropNode(node, "maxOccurs");
5971
if (attr == NULL)
5972
return (def);
5973
val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5974
if (val == NULL)
5975
return (def);
5976
5977
if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
5978
if (max != UNBOUNDED) {
5979
xmlSchemaPSimpleTypeErr(ctxt,
5980
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5981
/* XML_SCHEMAP_INVALID_MINOCCURS, */
5982
NULL, (xmlNodePtr) attr, NULL, expected,
5983
val, NULL, NULL, NULL);
5984
return (def);
5985
} else
5986
return (UNBOUNDED); /* encoding it with -1 might be another option */
5987
}
5988
5989
cur = val;
5990
while (IS_BLANK_CH(*cur))
5991
cur++;
5992
if (*cur == 0) {
5993
xmlSchemaPSimpleTypeErr(ctxt,
5994
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5995
/* XML_SCHEMAP_INVALID_MINOCCURS, */
5996
NULL, (xmlNodePtr) attr, NULL, expected,
5997
val, NULL, NULL, NULL);
5998
return (def);
5999
}
6000
while ((*cur >= '0') && (*cur <= '9')) {
6001
if (ret > INT_MAX / 10) {
6002
ret = INT_MAX;
6003
} else {
6004
int digit = *cur - '0';
6005
ret *= 10;
6006
if (ret > INT_MAX - digit)
6007
ret = INT_MAX;
6008
else
6009
ret += digit;
6010
}
6011
cur++;
6012
}
6013
while (IS_BLANK_CH(*cur))
6014
cur++;
6015
/*
6016
* TODO: Restrict the maximal value to Integer.
6017
*/
6018
if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6019
xmlSchemaPSimpleTypeErr(ctxt,
6020
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6021
/* XML_SCHEMAP_INVALID_MINOCCURS, */
6022
NULL, (xmlNodePtr) attr, NULL, expected,
6023
val, NULL, NULL, NULL);
6024
return (def);
6025
}
6026
return (ret);
6027
}
6028
6029
/**
6030
* xmlGetMinOccurs:
6031
* @ctxt: a schema validation context
6032
* @node: a subtree containing XML Schema information
6033
*
6034
* Get the minOccurs property
6035
*
6036
* Returns the default if not found, or the value
6037
*/
6038
static int
6039
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6040
int min, int max, int def, const char *expected)
6041
{
6042
const xmlChar *val, *cur;
6043
int ret = 0;
6044
xmlAttrPtr attr;
6045
6046
attr = xmlSchemaGetPropNode(node, "minOccurs");
6047
if (attr == NULL)
6048
return (def);
6049
val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6050
if (val == NULL)
6051
return (def);
6052
cur = val;
6053
while (IS_BLANK_CH(*cur))
6054
cur++;
6055
if (*cur == 0) {
6056
xmlSchemaPSimpleTypeErr(ctxt,
6057
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6058
/* XML_SCHEMAP_INVALID_MINOCCURS, */
6059
NULL, (xmlNodePtr) attr, NULL, expected,
6060
val, NULL, NULL, NULL);
6061
return (def);
6062
}
6063
while ((*cur >= '0') && (*cur <= '9')) {
6064
if (ret > INT_MAX / 10) {
6065
ret = INT_MAX;
6066
} else {
6067
int digit = *cur - '0';
6068
ret *= 10;
6069
if (ret > INT_MAX - digit)
6070
ret = INT_MAX;
6071
else
6072
ret += digit;
6073
}
6074
cur++;
6075
}
6076
while (IS_BLANK_CH(*cur))
6077
cur++;
6078
/*
6079
* TODO: Restrict the maximal value to Integer.
6080
*/
6081
if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6082
xmlSchemaPSimpleTypeErr(ctxt,
6083
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6084
/* XML_SCHEMAP_INVALID_MINOCCURS, */
6085
NULL, (xmlNodePtr) attr, NULL, expected,
6086
val, NULL, NULL, NULL);
6087
return (def);
6088
}
6089
return (ret);
6090
}
6091
6092
/**
6093
* xmlSchemaPGetBoolNodeValue:
6094
* @ctxt: a schema validation context
6095
* @ownerItem: the owner as a schema item
6096
* @node: the node holding the value
6097
*
6098
* Converts a boolean string value into 1 or 0.
6099
*
6100
* Returns 0 or 1.
6101
*/
6102
static int
6103
xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6104
xmlSchemaBasicItemPtr ownerItem,
6105
xmlNodePtr node)
6106
{
6107
xmlChar *value = NULL;
6108
int res = 0;
6109
6110
value = xmlNodeGetContent(node);
6111
/*
6112
* 3.2.2.1 Lexical representation
6113
* An instance of a datatype that is defined as `boolean`
6114
* can have the following legal literals {true, false, 1, 0}.
6115
*/
6116
if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6117
res = 1;
6118
else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6119
res = 0;
6120
else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6121
res = 1;
6122
else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6123
res = 0;
6124
else {
6125
xmlSchemaPSimpleTypeErr(ctxt,
6126
XML_SCHEMAP_INVALID_BOOLEAN,
6127
ownerItem, node,
6128
xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6129
NULL, BAD_CAST value,
6130
NULL, NULL, NULL);
6131
}
6132
if (value != NULL)
6133
xmlFree(value);
6134
return (res);
6135
}
6136
6137
/**
6138
* xmlGetBooleanProp:
6139
* @ctxt: a schema validation context
6140
* @node: a subtree containing XML Schema information
6141
* @name: the attribute name
6142
* @def: the default value
6143
*
6144
* Evaluate if a boolean property is set
6145
*
6146
* Returns the default if not found, 0 if found to be false,
6147
* 1 if found to be true
6148
*/
6149
static int
6150
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6151
xmlNodePtr node,
6152
const char *name, int def)
6153
{
6154
const xmlChar *val;
6155
6156
val = xmlSchemaGetProp(ctxt, node, name);
6157
if (val == NULL)
6158
return (def);
6159
/*
6160
* 3.2.2.1 Lexical representation
6161
* An instance of a datatype that is defined as `boolean`
6162
* can have the following legal literals {true, false, 1, 0}.
6163
*/
6164
if (xmlStrEqual(val, BAD_CAST "true"))
6165
def = 1;
6166
else if (xmlStrEqual(val, BAD_CAST "false"))
6167
def = 0;
6168
else if (xmlStrEqual(val, BAD_CAST "1"))
6169
def = 1;
6170
else if (xmlStrEqual(val, BAD_CAST "0"))
6171
def = 0;
6172
else {
6173
xmlSchemaPSimpleTypeErr(ctxt,
6174
XML_SCHEMAP_INVALID_BOOLEAN,
6175
NULL,
6176
(xmlNodePtr) xmlSchemaGetPropNode(node, name),
6177
xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6178
NULL, val, NULL, NULL, NULL);
6179
}
6180
return (def);
6181
}
6182
6183
/************************************************************************
6184
* *
6185
* Schema extraction from an Infoset *
6186
* *
6187
************************************************************************/
6188
static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6189
ctxt, xmlSchemaPtr schema,
6190
xmlNodePtr node,
6191
int topLevel);
6192
static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6193
ctxt,
6194
xmlSchemaPtr schema,
6195
xmlNodePtr node,
6196
int topLevel);
6197
static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6198
ctxt,
6199
xmlSchemaPtr schema,
6200
xmlNodePtr node,
6201
xmlSchemaTypeType parentType);
6202
static xmlSchemaBasicItemPtr
6203
xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6204
xmlSchemaPtr schema,
6205
xmlNodePtr node,
6206
xmlSchemaItemListPtr uses,
6207
int parentType);
6208
static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6209
xmlSchemaPtr schema,
6210
xmlNodePtr node);
6211
static xmlSchemaWildcardPtr
6212
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6213
xmlSchemaPtr schema, xmlNodePtr node);
6214
6215
/**
6216
* xmlSchemaPValAttrNodeValue:
6217
*
6218
* @pctxt: a schema parser context
6219
* @ownerItem: the schema object owner if existent
6220
* @attr: the schema attribute node being validated
6221
* @value: the value
6222
* @type: the built-in type to be validated against
6223
*
6224
* Validates a value against the given built-in type.
6225
* This one is intended to be used internally for validation
6226
* of schema attribute values during parsing of the schema.
6227
*
6228
* Returns 0 if the value is valid, a positive error code
6229
* number otherwise and -1 in case of an internal or API error.
6230
*/
6231
static int
6232
xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6233
xmlSchemaBasicItemPtr ownerItem,
6234
xmlAttrPtr attr,
6235
const xmlChar *value,
6236
xmlSchemaTypePtr type)
6237
{
6238
6239
int ret = 0;
6240
6241
/*
6242
* NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6243
* one is really meant to be used internally, so better not.
6244
*/
6245
if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6246
return (-1);
6247
if (type->type != XML_SCHEMA_TYPE_BASIC) {
6248
PERROR_INT("xmlSchemaPValAttrNodeValue",
6249
"the given type is not a built-in type");
6250
return (-1);
6251
}
6252
switch (type->builtInType) {
6253
case XML_SCHEMAS_NCNAME:
6254
case XML_SCHEMAS_QNAME:
6255
case XML_SCHEMAS_ANYURI:
6256
case XML_SCHEMAS_TOKEN:
6257
case XML_SCHEMAS_LANGUAGE:
6258
ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6259
(xmlNodePtr) attr);
6260
break;
6261
default: {
6262
PERROR_INT("xmlSchemaPValAttrNodeValue",
6263
"validation using the given type is not supported while "
6264
"parsing a schema");
6265
return (-1);
6266
}
6267
}
6268
/*
6269
* TODO: Should we use the S4S error codes instead?
6270
*/
6271
if (ret < 0) {
6272
PERROR_INT("xmlSchemaPValAttrNodeValue",
6273
"failed to validate a schema attribute value");
6274
return (-1);
6275
} else if (ret > 0) {
6276
if (WXS_IS_LIST(type))
6277
ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6278
else
6279
ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6280
xmlSchemaPSimpleTypeErr(pctxt,
6281
ret, ownerItem, (xmlNodePtr) attr,
6282
type, NULL, value, NULL, NULL, NULL);
6283
}
6284
return (ret);
6285
}
6286
6287
/**
6288
* xmlSchemaPValAttrNode:
6289
*
6290
* @ctxt: a schema parser context
6291
* @ownerItem: the schema object owner if existent
6292
* @attr: the schema attribute node being validated
6293
* @type: the built-in type to be validated against
6294
* @value: the resulting value if any
6295
*
6296
* Extracts and validates a value against the given built-in type.
6297
* This one is intended to be used internally for validation
6298
* of schema attribute values during parsing of the schema.
6299
*
6300
* Returns 0 if the value is valid, a positive error code
6301
* number otherwise and -1 in case of an internal or API error.
6302
*/
6303
static int
6304
xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6305
xmlSchemaBasicItemPtr ownerItem,
6306
xmlAttrPtr attr,
6307
xmlSchemaTypePtr type,
6308
const xmlChar **value)
6309
{
6310
const xmlChar *val;
6311
6312
if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6313
return (-1);
6314
6315
val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6316
if (value != NULL)
6317
*value = val;
6318
6319
return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6320
val, type));
6321
}
6322
6323
/**
6324
* xmlSchemaPValAttr:
6325
*
6326
* @ctxt: a schema parser context
6327
* @node: the element node of the attribute
6328
* @ownerItem: the schema object owner if existent
6329
* @ownerElem: the owner element node
6330
* @name: the name of the schema attribute node
6331
* @type: the built-in type to be validated against
6332
* @value: the resulting value if any
6333
*
6334
* Extracts and validates a value against the given built-in type.
6335
* This one is intended to be used internally for validation
6336
* of schema attribute values during parsing of the schema.
6337
*
6338
* Returns 0 if the value is valid, a positive error code
6339
* number otherwise and -1 in case of an internal or API error.
6340
*/
6341
static int
6342
xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6343
xmlSchemaBasicItemPtr ownerItem,
6344
xmlNodePtr ownerElem,
6345
const char *name,
6346
xmlSchemaTypePtr type,
6347
const xmlChar **value)
6348
{
6349
xmlAttrPtr attr;
6350
6351
if ((ctxt == NULL) || (type == NULL)) {
6352
if (value != NULL)
6353
*value = NULL;
6354
return (-1);
6355
}
6356
if (type->type != XML_SCHEMA_TYPE_BASIC) {
6357
if (value != NULL)
6358
*value = NULL;
6359
xmlSchemaPErr(ctxt, ownerElem,
6360
XML_SCHEMAP_INTERNAL,
6361
"Internal error: xmlSchemaPValAttr, the given "
6362
"type '%s' is not a built-in type.\n",
6363
type->name, NULL);
6364
return (-1);
6365
}
6366
attr = xmlSchemaGetPropNode(ownerElem, name);
6367
if (attr == NULL) {
6368
if (value != NULL)
6369
*value = NULL;
6370
return (0);
6371
}
6372
return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6373
type, value));
6374
}
6375
6376
static int
6377
xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6378
xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6379
xmlNodePtr node,
6380
xmlAttrPtr attr,
6381
const xmlChar *namespaceName)
6382
{
6383
/* TODO: Pointer comparison instead? */
6384
if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6385
return (0);
6386
if (xmlStrEqual(xmlSchemaNs, namespaceName))
6387
return (0);
6388
/*
6389
* Check if the referenced namespace was <import>ed.
6390
*/
6391
if (WXS_BUCKET(pctxt)->relations != NULL) {
6392
xmlSchemaSchemaRelationPtr rel;
6393
6394
rel = WXS_BUCKET(pctxt)->relations;
6395
do {
6396
if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6397
xmlStrEqual(namespaceName, rel->importNamespace))
6398
return (0);
6399
rel = rel->next;
6400
} while (rel != NULL);
6401
}
6402
/*
6403
* No matching <import>ed namespace found.
6404
*/
6405
{
6406
xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6407
6408
if (namespaceName == NULL)
6409
xmlSchemaCustomErr(ACTXT_CAST pctxt,
6410
XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6411
"References from this schema to components in no "
6412
"namespace are not allowed, since not indicated by an "
6413
"import statement", NULL, NULL);
6414
else
6415
xmlSchemaCustomErr(ACTXT_CAST pctxt,
6416
XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6417
"References from this schema to components in the "
6418
"namespace '%s' are not allowed, since not indicated by an "
6419
"import statement", namespaceName, NULL);
6420
}
6421
return (XML_SCHEMAP_SRC_RESOLVE);
6422
}
6423
6424
/**
6425
* xmlSchemaParseLocalAttributes:
6426
* @ctxt: a schema validation context
6427
* @schema: the schema being built
6428
* @node: a subtree containing XML Schema information
6429
* @type: the hosting type where the attributes will be anchored
6430
*
6431
* Parses attribute uses and attribute declarations and
6432
* attribute group references.
6433
*/
6434
static int
6435
xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6436
xmlNodePtr *child, xmlSchemaItemListPtr *list,
6437
int parentType, int *hasRefs)
6438
{
6439
void *item;
6440
6441
while ((IS_SCHEMA((*child), "attribute")) ||
6442
(IS_SCHEMA((*child), "attributeGroup"))) {
6443
if (IS_SCHEMA((*child), "attribute")) {
6444
item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6445
*list, parentType);
6446
} else {
6447
item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6448
if ((item != NULL) && (hasRefs != NULL))
6449
*hasRefs = 1;
6450
}
6451
if (item != NULL) {
6452
if (*list == NULL) {
6453
/* TODO: Customize grow factor. */
6454
*list = xmlSchemaItemListCreate();
6455
if (*list == NULL)
6456
return(-1);
6457
}
6458
if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6459
return(-1);
6460
}
6461
*child = (*child)->next;
6462
}
6463
return (0);
6464
}
6465
6466
/**
6467
* xmlSchemaParseAnnotation:
6468
* @ctxt: a schema validation context
6469
* @schema: the schema being built
6470
* @node: a subtree containing XML Schema information
6471
*
6472
* parse a XML schema Attribute declaration
6473
* *WARNING* this interface is highly subject to change
6474
*
6475
* Returns -1 in case of error, 0 if the declaration is improper and
6476
* 1 in case of success.
6477
*/
6478
static xmlSchemaAnnotPtr
6479
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6480
{
6481
xmlSchemaAnnotPtr ret;
6482
xmlNodePtr child = NULL;
6483
xmlAttrPtr attr;
6484
int barked = 0;
6485
6486
/*
6487
* INFO: S4S completed.
6488
*/
6489
/*
6490
* id = ID
6491
* {any attributes with non-schema namespace . . .}>
6492
* Content: (appinfo | documentation)*
6493
*/
6494
if ((ctxt == NULL) || (node == NULL))
6495
return (NULL);
6496
if (needed)
6497
ret = xmlSchemaNewAnnot(ctxt, node);
6498
else
6499
ret = NULL;
6500
attr = node->properties;
6501
while (attr != NULL) {
6502
if (((attr->ns == NULL) &&
6503
(!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6504
((attr->ns != NULL) &&
6505
xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6506
6507
xmlSchemaPIllegalAttrErr(ctxt,
6508
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6509
}
6510
attr = attr->next;
6511
}
6512
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6513
/*
6514
* And now for the children...
6515
*/
6516
child = node->children;
6517
while (child != NULL) {
6518
if (IS_SCHEMA(child, "appinfo")) {
6519
/* TODO: make available the content of "appinfo". */
6520
/*
6521
* source = anyURI
6522
* {any attributes with non-schema namespace . . .}>
6523
* Content: ({any})*
6524
*/
6525
attr = child->properties;
6526
while (attr != NULL) {
6527
if (((attr->ns == NULL) &&
6528
(!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6529
((attr->ns != NULL) &&
6530
xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6531
6532
xmlSchemaPIllegalAttrErr(ctxt,
6533
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6534
}
6535
attr = attr->next;
6536
}
6537
xmlSchemaPValAttr(ctxt, NULL, child, "source",
6538
xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6539
child = child->next;
6540
} else if (IS_SCHEMA(child, "documentation")) {
6541
/* TODO: make available the content of "documentation". */
6542
/*
6543
* source = anyURI
6544
* {any attributes with non-schema namespace . . .}>
6545
* Content: ({any})*
6546
*/
6547
attr = child->properties;
6548
while (attr != NULL) {
6549
if (attr->ns == NULL) {
6550
if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6551
xmlSchemaPIllegalAttrErr(ctxt,
6552
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6553
}
6554
} else {
6555
if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6556
(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6557
(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6558
6559
xmlSchemaPIllegalAttrErr(ctxt,
6560
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6561
}
6562
}
6563
attr = attr->next;
6564
}
6565
/*
6566
* Attribute "xml:lang".
6567
*/
6568
attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6569
if (attr != NULL)
6570
xmlSchemaPValAttrNode(ctxt, NULL, attr,
6571
xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6572
child = child->next;
6573
} else {
6574
if (!barked)
6575
xmlSchemaPContentErr(ctxt,
6576
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6577
NULL, node, child, NULL, "(appinfo | documentation)*");
6578
barked = 1;
6579
child = child->next;
6580
}
6581
}
6582
6583
return (ret);
6584
}
6585
6586
/**
6587
* xmlSchemaParseFacet:
6588
* @ctxt: a schema validation context
6589
* @schema: the schema being built
6590
* @node: a subtree containing XML Schema information
6591
*
6592
* parse a XML schema Facet declaration
6593
* *WARNING* this interface is highly subject to change
6594
*
6595
* Returns the new type structure or NULL in case of error
6596
*/
6597
static xmlSchemaFacetPtr
6598
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6599
xmlNodePtr node)
6600
{
6601
xmlSchemaFacetPtr facet;
6602
xmlNodePtr child = NULL;
6603
const xmlChar *value;
6604
6605
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6606
return (NULL);
6607
6608
facet = xmlSchemaNewFacet();
6609
if (facet == NULL) {
6610
xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6611
return (NULL);
6612
}
6613
facet->node = node;
6614
value = xmlSchemaGetProp(ctxt, node, "value");
6615
if (value == NULL) {
6616
xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6617
"Facet %s has no value\n", node->name, NULL);
6618
xmlSchemaFreeFacet(facet);
6619
return (NULL);
6620
}
6621
if (IS_SCHEMA(node, "minInclusive")) {
6622
facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6623
} else if (IS_SCHEMA(node, "minExclusive")) {
6624
facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6625
} else if (IS_SCHEMA(node, "maxInclusive")) {
6626
facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6627
} else if (IS_SCHEMA(node, "maxExclusive")) {
6628
facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6629
} else if (IS_SCHEMA(node, "totalDigits")) {
6630
facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6631
} else if (IS_SCHEMA(node, "fractionDigits")) {
6632
facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6633
} else if (IS_SCHEMA(node, "pattern")) {
6634
facet->type = XML_SCHEMA_FACET_PATTERN;
6635
} else if (IS_SCHEMA(node, "enumeration")) {
6636
facet->type = XML_SCHEMA_FACET_ENUMERATION;
6637
} else if (IS_SCHEMA(node, "whiteSpace")) {
6638
facet->type = XML_SCHEMA_FACET_WHITESPACE;
6639
} else if (IS_SCHEMA(node, "length")) {
6640
facet->type = XML_SCHEMA_FACET_LENGTH;
6641
} else if (IS_SCHEMA(node, "maxLength")) {
6642
facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6643
} else if (IS_SCHEMA(node, "minLength")) {
6644
facet->type = XML_SCHEMA_FACET_MINLENGTH;
6645
} else {
6646
xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6647
"Unknown facet type %s\n", node->name, NULL);
6648
xmlSchemaFreeFacet(facet);
6649
return (NULL);
6650
}
6651
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6652
facet->value = value;
6653
if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6654
(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6655
const xmlChar *fixed;
6656
6657
fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6658
if (fixed != NULL) {
6659
if (xmlStrEqual(fixed, BAD_CAST "true"))
6660
facet->fixed = 1;
6661
}
6662
}
6663
child = node->children;
6664
6665
if (IS_SCHEMA(child, "annotation")) {
6666
facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6667
child = child->next;
6668
}
6669
if (child != NULL) {
6670
xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6671
"Facet %s has unexpected child content\n",
6672
node->name, NULL);
6673
}
6674
return (facet);
6675
}
6676
6677
/**
6678
* xmlSchemaParseWildcardNs:
6679
* @ctxt: a schema parser context
6680
* @wildc: the wildcard, already created
6681
* @node: a subtree containing XML Schema information
6682
*
6683
* Parses the attribute "processContents" and "namespace"
6684
* of a xsd:anyAttribute and xsd:any.
6685
* *WARNING* this interface is highly subject to change
6686
*
6687
* Returns 0 if everything goes fine, a positive error code
6688
* if something is not valid and -1 if an internal error occurs.
6689
*/
6690
static int
6691
xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6692
xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6693
xmlSchemaWildcardPtr wildc,
6694
xmlNodePtr node)
6695
{
6696
const xmlChar *pc, *ns, *dictnsItem;
6697
int ret = 0;
6698
xmlChar *nsItem;
6699
xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6700
xmlAttrPtr attr;
6701
6702
pc = xmlSchemaGetProp(ctxt, node, "processContents");
6703
if ((pc == NULL)
6704
|| (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6705
wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6706
} else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6707
wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6708
} else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6709
wildc->processContents = XML_SCHEMAS_ANY_LAX;
6710
} else {
6711
xmlSchemaPSimpleTypeErr(ctxt,
6712
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6713
NULL, node,
6714
NULL, "(strict | skip | lax)", pc,
6715
NULL, NULL, NULL);
6716
wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6717
ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6718
}
6719
/*
6720
* Build the namespace constraints.
6721
*/
6722
attr = xmlSchemaGetPropNode(node, "namespace");
6723
ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6724
if (ns == NULL)
6725
return (-1);
6726
if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6727
wildc->any = 1;
6728
else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6729
wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6730
if (wildc->negNsSet == NULL) {
6731
return (-1);
6732
}
6733
wildc->negNsSet->value = ctxt->targetNamespace;
6734
} else {
6735
const xmlChar *end, *cur;
6736
6737
cur = ns;
6738
do {
6739
while (IS_BLANK_CH(*cur))
6740
cur++;
6741
end = cur;
6742
while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6743
end++;
6744
if (end == cur)
6745
break;
6746
nsItem = xmlStrndup(cur, end - cur);
6747
if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6748
(xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6749
xmlSchemaPSimpleTypeErr(ctxt,
6750
XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6751
NULL, (xmlNodePtr) attr,
6752
NULL,
6753
"((##any | ##other) | List of (xs:anyURI | "
6754
"(##targetNamespace | ##local)))",
6755
nsItem, NULL, NULL, NULL);
6756
ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6757
} else {
6758
if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6759
dictnsItem = ctxt->targetNamespace;
6760
} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6761
dictnsItem = NULL;
6762
} else {
6763
/*
6764
* Validate the item (anyURI).
6765
*/
6766
xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6767
nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6768
dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6769
}
6770
/*
6771
* Avoid duplicate namespaces.
6772
*/
6773
tmp = wildc->nsSet;
6774
while (tmp != NULL) {
6775
if (dictnsItem == tmp->value)
6776
break;
6777
tmp = tmp->next;
6778
}
6779
if (tmp == NULL) {
6780
tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6781
if (tmp == NULL) {
6782
xmlFree(nsItem);
6783
return (-1);
6784
}
6785
tmp->value = dictnsItem;
6786
tmp->next = NULL;
6787
if (wildc->nsSet == NULL)
6788
wildc->nsSet = tmp;
6789
else if (lastNs != NULL)
6790
lastNs->next = tmp;
6791
lastNs = tmp;
6792
}
6793
6794
}
6795
xmlFree(nsItem);
6796
cur = end;
6797
} while (*cur != 0);
6798
}
6799
return (ret);
6800
}
6801
6802
static int
6803
xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6804
xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6805
xmlNodePtr node,
6806
int minOccurs,
6807
int maxOccurs) {
6808
6809
if ((maxOccurs == 0) && ( minOccurs == 0))
6810
return (0);
6811
if (maxOccurs != UNBOUNDED) {
6812
/*
6813
* TODO: Maybe we should better not create the particle,
6814
* if min/max is invalid, since it could confuse the build of the
6815
* content model.
6816
*/
6817
/*
6818
* 3.9.6 Schema Component Constraint: Particle Correct
6819
*
6820
*/
6821
if (maxOccurs < 1) {
6822
/*
6823
* 2.2 {max occurs} must be greater than or equal to 1.
6824
*/
6825
xmlSchemaPCustomAttrErr(ctxt,
6826
XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6827
NULL, NULL,
6828
xmlSchemaGetPropNode(node, "maxOccurs"),
6829
"The value must be greater than or equal to 1");
6830
return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6831
} else if (minOccurs > maxOccurs) {
6832
/*
6833
* 2.1 {min occurs} must not be greater than {max occurs}.
6834
*/
6835
xmlSchemaPCustomAttrErr(ctxt,
6836
XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6837
NULL, NULL,
6838
xmlSchemaGetPropNode(node, "minOccurs"),
6839
"The value must not be greater than the value of 'maxOccurs'");
6840
return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6841
}
6842
}
6843
return (0);
6844
}
6845
6846
/**
6847
* xmlSchemaParseAny:
6848
* @ctxt: a schema validation context
6849
* @schema: the schema being built
6850
* @node: a subtree containing XML Schema information
6851
*
6852
* Parsea a XML schema <any> element. A particle and wildcard
6853
* will be created (except if minOccurs==maxOccurs==0, in this case
6854
* nothing will be created).
6855
* *WARNING* this interface is highly subject to change
6856
*
6857
* Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6858
*/
6859
static xmlSchemaParticlePtr
6860
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6861
xmlNodePtr node)
6862
{
6863
xmlSchemaParticlePtr particle;
6864
xmlNodePtr child = NULL;
6865
xmlSchemaWildcardPtr wild;
6866
int min, max;
6867
xmlAttrPtr attr;
6868
xmlSchemaAnnotPtr annot = NULL;
6869
6870
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6871
return (NULL);
6872
/*
6873
* Check for illegal attributes.
6874
*/
6875
attr = node->properties;
6876
while (attr != NULL) {
6877
if (attr->ns == NULL) {
6878
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6879
(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6880
(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6881
(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6882
(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6883
xmlSchemaPIllegalAttrErr(ctxt,
6884
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6885
}
6886
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6887
xmlSchemaPIllegalAttrErr(ctxt,
6888
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6889
}
6890
attr = attr->next;
6891
}
6892
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6893
/*
6894
* minOccurs/maxOccurs.
6895
*/
6896
max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6897
"(xs:nonNegativeInteger | unbounded)");
6898
min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6899
"xs:nonNegativeInteger");
6900
xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6901
/*
6902
* Create & parse the wildcard.
6903
*/
6904
wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6905
if (wild == NULL)
6906
return (NULL);
6907
xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6908
/*
6909
* And now for the children...
6910
*/
6911
child = node->children;
6912
if (IS_SCHEMA(child, "annotation")) {
6913
annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6914
child = child->next;
6915
}
6916
if (child != NULL) {
6917
xmlSchemaPContentErr(ctxt,
6918
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6919
NULL, node, child,
6920
NULL, "(annotation?)");
6921
}
6922
/*
6923
* No component if minOccurs==maxOccurs==0.
6924
*/
6925
if ((min == 0) && (max == 0)) {
6926
/* Don't free the wildcard, since it's already on the list. */
6927
return (NULL);
6928
}
6929
/*
6930
* Create the particle.
6931
*/
6932
particle = xmlSchemaAddParticle(ctxt, node, min, max);
6933
if (particle == NULL)
6934
return (NULL);
6935
particle->annot = annot;
6936
particle->children = (xmlSchemaTreeItemPtr) wild;
6937
6938
return (particle);
6939
}
6940
6941
/**
6942
* xmlSchemaParseNotation:
6943
* @ctxt: a schema validation context
6944
* @schema: the schema being built
6945
* @node: a subtree containing XML Schema information
6946
*
6947
* parse a XML schema Notation declaration
6948
*
6949
* Returns the new structure or NULL in case of error
6950
*/
6951
static xmlSchemaNotationPtr
6952
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6953
xmlNodePtr node)
6954
{
6955
const xmlChar *name;
6956
xmlSchemaNotationPtr ret;
6957
xmlNodePtr child = NULL;
6958
6959
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6960
return (NULL);
6961
name = xmlSchemaGetProp(ctxt, node, "name");
6962
if (name == NULL) {
6963
xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6964
"Notation has no name\n", NULL, NULL);
6965
return (NULL);
6966
}
6967
ret = xmlSchemaAddNotation(ctxt, schema, name,
6968
ctxt->targetNamespace, node);
6969
if (ret == NULL)
6970
return (NULL);
6971
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6972
6973
child = node->children;
6974
if (IS_SCHEMA(child, "annotation")) {
6975
ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6976
child = child->next;
6977
}
6978
if (child != NULL) {
6979
xmlSchemaPContentErr(ctxt,
6980
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6981
NULL, node, child,
6982
NULL, "(annotation?)");
6983
}
6984
6985
return (ret);
6986
}
6987
6988
/**
6989
* xmlSchemaParseAnyAttribute:
6990
* @ctxt: a schema validation context
6991
* @schema: the schema being built
6992
* @node: a subtree containing XML Schema information
6993
*
6994
* parse a XML schema AnyAttribute declaration
6995
* *WARNING* this interface is highly subject to change
6996
*
6997
* Returns a wildcard or NULL.
6998
*/
6999
static xmlSchemaWildcardPtr
7000
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7001
xmlSchemaPtr schema, xmlNodePtr node)
7002
{
7003
xmlSchemaWildcardPtr ret;
7004
xmlNodePtr child = NULL;
7005
xmlAttrPtr attr;
7006
7007
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7008
return (NULL);
7009
7010
ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7011
node);
7012
if (ret == NULL) {
7013
return (NULL);
7014
}
7015
/*
7016
* Check for illegal attributes.
7017
*/
7018
attr = node->properties;
7019
while (attr != NULL) {
7020
if (attr->ns == NULL) {
7021
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7022
(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7023
(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7024
xmlSchemaPIllegalAttrErr(ctxt,
7025
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7026
}
7027
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7028
xmlSchemaPIllegalAttrErr(ctxt,
7029
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7030
}
7031
attr = attr->next;
7032
}
7033
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7034
/*
7035
* Parse the namespace list.
7036
*/
7037
if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7038
return (NULL);
7039
/*
7040
* And now for the children...
7041
*/
7042
child = node->children;
7043
if (IS_SCHEMA(child, "annotation")) {
7044
ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7045
child = child->next;
7046
}
7047
if (child != NULL) {
7048
xmlSchemaPContentErr(ctxt,
7049
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7050
NULL, node, child,
7051
NULL, "(annotation?)");
7052
}
7053
7054
return (ret);
7055
}
7056
7057
7058
/**
7059
* xmlSchemaParseAttribute:
7060
* @ctxt: a schema validation context
7061
* @schema: the schema being built
7062
* @node: a subtree containing XML Schema information
7063
*
7064
* parse a XML schema Attribute declaration
7065
* *WARNING* this interface is highly subject to change
7066
*
7067
* Returns the attribute declaration.
7068
*/
7069
static xmlSchemaBasicItemPtr
7070
xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7071
xmlSchemaPtr schema,
7072
xmlNodePtr node,
7073
xmlSchemaItemListPtr uses,
7074
int parentType)
7075
{
7076
const xmlChar *attrValue, *name = NULL, *ns = NULL;
7077
xmlSchemaAttributeUsePtr use = NULL;
7078
xmlNodePtr child = NULL;
7079
xmlAttrPtr attr;
7080
const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7081
int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7082
int nberrors, hasForm = 0, defValueType = 0;
7083
7084
#define WXS_ATTR_DEF_VAL_DEFAULT 1
7085
#define WXS_ATTR_DEF_VAL_FIXED 2
7086
7087
/*
7088
* 3.2.3 Constraints on XML Representations of Attribute Declarations
7089
*/
7090
7091
if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7092
return (NULL);
7093
attr = xmlSchemaGetPropNode(node, "ref");
7094
if (attr != NULL) {
7095
if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7096
NULL, attr, &tmpNs, &tmpName) != 0) {
7097
return (NULL);
7098
}
7099
if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7100
return(NULL);
7101
isRef = 1;
7102
}
7103
nberrors = pctxt->nberrors;
7104
/*
7105
* Check for illegal attributes.
7106
*/
7107
attr = node->properties;
7108
while (attr != NULL) {
7109
if (attr->ns == NULL) {
7110
if (isRef) {
7111
if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7112
xmlSchemaPValAttrNodeID(pctxt, attr);
7113
goto attr_next;
7114
} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7115
goto attr_next;
7116
}
7117
} else {
7118
if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7119
goto attr_next;
7120
} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7121
xmlSchemaPValAttrNodeID(pctxt, attr);
7122
goto attr_next;
7123
} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7124
xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7125
attr, &tmpNs, &tmpName);
7126
goto attr_next;
7127
} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7128
/*
7129
* Evaluate the target namespace
7130
*/
7131
hasForm = 1;
7132
attrValue = xmlSchemaGetNodeContent(pctxt,
7133
(xmlNodePtr) attr);
7134
if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7135
ns = pctxt->targetNamespace;
7136
} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7137
{
7138
xmlSchemaPSimpleTypeErr(pctxt,
7139
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7140
NULL, (xmlNodePtr) attr,
7141
NULL, "(qualified | unqualified)",
7142
attrValue, NULL, NULL, NULL);
7143
}
7144
goto attr_next;
7145
}
7146
}
7147
if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7148
7149
attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7150
/* TODO: Maybe we need to normalize the value beforehand. */
7151
if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7152
occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7153
else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7154
occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7155
else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7156
occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7157
else {
7158
xmlSchemaPSimpleTypeErr(pctxt,
7159
XML_SCHEMAP_INVALID_ATTR_USE,
7160
NULL, (xmlNodePtr) attr,
7161
NULL, "(optional | prohibited | required)",
7162
attrValue, NULL, NULL, NULL);
7163
}
7164
goto attr_next;
7165
} else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7166
/*
7167
* 3.2.3 : 1
7168
* default and fixed must not both be present.
7169
*/
7170
if (defValue) {
7171
xmlSchemaPMutualExclAttrErr(pctxt,
7172
XML_SCHEMAP_SRC_ATTRIBUTE_1,
7173
NULL, attr, "default", "fixed");
7174
} else {
7175
defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7176
defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7177
}
7178
goto attr_next;
7179
} else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7180
/*
7181
* 3.2.3 : 1
7182
* default and fixed must not both be present.
7183
*/
7184
if (defValue) {
7185
xmlSchemaPMutualExclAttrErr(pctxt,
7186
XML_SCHEMAP_SRC_ATTRIBUTE_1,
7187
NULL, attr, "default", "fixed");
7188
} else {
7189
defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7190
defValueType = WXS_ATTR_DEF_VAL_FIXED;
7191
}
7192
goto attr_next;
7193
}
7194
} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7195
goto attr_next;
7196
7197
xmlSchemaPIllegalAttrErr(pctxt,
7198
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7199
7200
attr_next:
7201
attr = attr->next;
7202
}
7203
/*
7204
* 3.2.3 : 2
7205
* If default and use are both present, use must have
7206
* the actual value optional.
7207
*/
7208
if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7209
(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7210
xmlSchemaPSimpleTypeErr(pctxt,
7211
XML_SCHEMAP_SRC_ATTRIBUTE_2,
7212
NULL, node, NULL,
7213
"(optional | prohibited | required)", NULL,
7214
"The value of the attribute 'use' must be 'optional' "
7215
"if the attribute 'default' is present",
7216
NULL, NULL);
7217
}
7218
/*
7219
* We want correct attributes.
7220
*/
7221
if (nberrors != pctxt->nberrors)
7222
return(NULL);
7223
if (! isRef) {
7224
xmlSchemaAttributePtr attrDecl;
7225
7226
/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7227
if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7228
ns = pctxt->targetNamespace;
7229
/*
7230
* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7231
* TODO: Move this to the component layer.
7232
*/
7233
if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7234
xmlSchemaCustomErr(ACTXT_CAST pctxt,
7235
XML_SCHEMAP_NO_XSI,
7236
node, NULL,
7237
"The target namespace must not match '%s'",
7238
xmlSchemaInstanceNs, NULL);
7239
}
7240
attr = xmlSchemaGetPropNode(node, "name");
7241
if (attr == NULL) {
7242
xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7243
NULL, node, "name", NULL);
7244
return (NULL);
7245
}
7246
if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7247
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7248
return (NULL);
7249
}
7250
/*
7251
* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7252
* TODO: Move this to the component layer.
7253
*/
7254
if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7255
xmlSchemaPSimpleTypeErr(pctxt,
7256
XML_SCHEMAP_NO_XMLNS,
7257
NULL, (xmlNodePtr) attr,
7258
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7259
"The value of the attribute must not match 'xmlns'",
7260
NULL, NULL);
7261
return (NULL);
7262
}
7263
if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7264
goto check_children;
7265
/*
7266
* Create the attribute use component.
7267
*/
7268
use = xmlSchemaAddAttributeUse(pctxt, node);
7269
if (use == NULL)
7270
return(NULL);
7271
use->occurs = occurs;
7272
/*
7273
* Create the attribute declaration.
7274
*/
7275
attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7276
if (attrDecl == NULL)
7277
return (NULL);
7278
if (tmpName != NULL) {
7279
attrDecl->typeName = tmpName;
7280
attrDecl->typeNs = tmpNs;
7281
}
7282
use->attrDecl = attrDecl;
7283
/*
7284
* Value constraint.
7285
*/
7286
if (defValue != NULL) {
7287
attrDecl->defValue = defValue;
7288
if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7289
attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7290
}
7291
} else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7292
xmlSchemaQNameRefPtr ref;
7293
7294
/*
7295
* Create the attribute use component.
7296
*/
7297
use = xmlSchemaAddAttributeUse(pctxt, node);
7298
if (use == NULL)
7299
return(NULL);
7300
/*
7301
* We need to resolve the reference at later stage.
7302
*/
7303
WXS_ADD_PENDING(pctxt, use);
7304
use->occurs = occurs;
7305
/*
7306
* Create a QName reference to the attribute declaration.
7307
*/
7308
ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7309
tmpName, tmpNs);
7310
if (ref == NULL)
7311
return(NULL);
7312
/*
7313
* Assign the reference. This will be substituted for the
7314
* referenced attribute declaration when the QName is resolved.
7315
*/
7316
use->attrDecl = WXS_ATTR_CAST ref;
7317
/*
7318
* Value constraint.
7319
*/
7320
if (defValue != NULL)
7321
use->defValue = defValue;
7322
if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7323
use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7324
}
7325
7326
check_children:
7327
/*
7328
* And now for the children...
7329
*/
7330
child = node->children;
7331
if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7332
xmlSchemaAttributeUseProhibPtr prohib;
7333
7334
if (IS_SCHEMA(child, "annotation")) {
7335
xmlSchemaParseAnnotation(pctxt, child, 0);
7336
child = child->next;
7337
}
7338
if (child != NULL) {
7339
xmlSchemaPContentErr(pctxt,
7340
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7341
NULL, node, child, NULL,
7342
"(annotation?)");
7343
}
7344
/*
7345
* Check for pointlessness of attribute prohibitions.
7346
*/
7347
if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7348
xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7349
XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7350
node, NULL,
7351
"Skipping attribute use prohibition, since it is "
7352
"pointless inside an <attributeGroup>",
7353
NULL, NULL, NULL);
7354
return(NULL);
7355
} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7356
xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7357
XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7358
node, NULL,
7359
"Skipping attribute use prohibition, since it is "
7360
"pointless when extending a type",
7361
NULL, NULL, NULL);
7362
return(NULL);
7363
}
7364
if (! isRef) {
7365
tmpName = name;
7366
tmpNs = ns;
7367
}
7368
/*
7369
* Check for duplicate attribute prohibitions.
7370
*/
7371
if (uses) {
7372
int i;
7373
7374
for (i = 0; i < uses->nbItems; i++) {
7375
use = uses->items[i];
7376
if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7377
(tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7378
(tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7379
{
7380
xmlChar *str = NULL;
7381
7382
xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7383
XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7384
node, NULL,
7385
"Skipping duplicate attribute use prohibition '%s'",
7386
xmlSchemaFormatQName(&str, tmpNs, tmpName),
7387
NULL, NULL);
7388
FREE_AND_NULL(str)
7389
return(NULL);
7390
}
7391
}
7392
}
7393
/*
7394
* Create the attribute prohibition helper component.
7395
*/
7396
prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7397
if (prohib == NULL)
7398
return(NULL);
7399
prohib->node = node;
7400
prohib->name = tmpName;
7401
prohib->targetNamespace = tmpNs;
7402
if (isRef) {
7403
/*
7404
* We need at least to resolve to the attribute declaration.
7405
*/
7406
WXS_ADD_PENDING(pctxt, prohib);
7407
}
7408
return(WXS_BASIC_CAST prohib);
7409
} else {
7410
if (IS_SCHEMA(child, "annotation")) {
7411
/*
7412
* TODO: Should this go into the attr decl?
7413
*/
7414
use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7415
child = child->next;
7416
}
7417
if (isRef) {
7418
if (child != NULL) {
7419
if (IS_SCHEMA(child, "simpleType"))
7420
/*
7421
* 3.2.3 : 3.2
7422
* If ref is present, then all of <simpleType>,
7423
* form and type must be absent.
7424
*/
7425
xmlSchemaPContentErr(pctxt,
7426
XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7427
NULL, node, child, NULL,
7428
"(annotation?)");
7429
else
7430
xmlSchemaPContentErr(pctxt,
7431
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7432
NULL, node, child, NULL,
7433
"(annotation?)");
7434
}
7435
} else {
7436
if (IS_SCHEMA(child, "simpleType")) {
7437
if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7438
/*
7439
* 3.2.3 : 4
7440
* type and <simpleType> must not both be present.
7441
*/
7442
xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7443
NULL, node, child,
7444
"The attribute 'type' and the <simpleType> child "
7445
"are mutually exclusive", NULL);
7446
} else
7447
WXS_ATTRUSE_TYPEDEF(use) =
7448
xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7449
child = child->next;
7450
}
7451
if (child != NULL)
7452
xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7453
NULL, node, child, NULL,
7454
"(annotation?, simpleType?)");
7455
}
7456
}
7457
return (WXS_BASIC_CAST use);
7458
}
7459
7460
7461
static xmlSchemaAttributePtr
7462
xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7463
xmlSchemaPtr schema,
7464
xmlNodePtr node)
7465
{
7466
const xmlChar *attrValue;
7467
xmlSchemaAttributePtr ret;
7468
xmlNodePtr child = NULL;
7469
xmlAttrPtr attr;
7470
7471
/*
7472
* Note that the w3c spec assumes the schema to be validated with schema
7473
* for schemas beforehand.
7474
*
7475
* 3.2.3 Constraints on XML Representations of Attribute Declarations
7476
*/
7477
if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7478
return (NULL);
7479
/*
7480
* 3.2.3 : 3.1
7481
* One of ref or name must be present, but not both
7482
*/
7483
attr = xmlSchemaGetPropNode(node, "name");
7484
if (attr == NULL) {
7485
xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7486
NULL, node, "name", NULL);
7487
return (NULL);
7488
}
7489
if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7490
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7491
return (NULL);
7492
}
7493
/*
7494
* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7495
* TODO: Move this to the component layer.
7496
*/
7497
if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7498
xmlSchemaPSimpleTypeErr(pctxt,
7499
XML_SCHEMAP_NO_XMLNS,
7500
NULL, (xmlNodePtr) attr,
7501
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7502
"The value of the attribute must not match 'xmlns'",
7503
NULL, NULL);
7504
return (NULL);
7505
}
7506
/*
7507
* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7508
* TODO: Move this to the component layer.
7509
* Or better leave it here and add it to the component layer
7510
* if we have a schema construction API.
7511
*/
7512
if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7513
xmlSchemaCustomErr(ACTXT_CAST pctxt,
7514
XML_SCHEMAP_NO_XSI, node, NULL,
7515
"The target namespace must not match '%s'",
7516
xmlSchemaInstanceNs, NULL);
7517
}
7518
7519
ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7520
pctxt->targetNamespace, node, 1);
7521
if (ret == NULL)
7522
return (NULL);
7523
ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7524
7525
/*
7526
* Check for illegal attributes.
7527
*/
7528
attr = node->properties;
7529
while (attr != NULL) {
7530
if (attr->ns == NULL) {
7531
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7532
(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7533
(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7534
(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7535
(!xmlStrEqual(attr->name, BAD_CAST "type")))
7536
{
7537
xmlSchemaPIllegalAttrErr(pctxt,
7538
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7539
}
7540
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7541
xmlSchemaPIllegalAttrErr(pctxt,
7542
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7543
}
7544
attr = attr->next;
7545
}
7546
xmlSchemaPValAttrQName(pctxt, schema, NULL,
7547
node, "type", &ret->typeNs, &ret->typeName);
7548
7549
xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7550
/*
7551
* Attribute "fixed".
7552
*/
7553
ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7554
if (ret->defValue != NULL)
7555
ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7556
/*
7557
* Attribute "default".
7558
*/
7559
attr = xmlSchemaGetPropNode(node, "default");
7560
if (attr != NULL) {
7561
/*
7562
* 3.2.3 : 1
7563
* default and fixed must not both be present.
7564
*/
7565
if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7566
xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7567
WXS_BASIC_CAST ret, attr, "default", "fixed");
7568
} else
7569
ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7570
}
7571
/*
7572
* And now for the children...
7573
*/
7574
child = node->children;
7575
if (IS_SCHEMA(child, "annotation")) {
7576
ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7577
child = child->next;
7578
}
7579
if (IS_SCHEMA(child, "simpleType")) {
7580
if (ret->typeName != NULL) {
7581
/*
7582
* 3.2.3 : 4
7583
* type and <simpleType> must not both be present.
7584
*/
7585
xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7586
NULL, node, child,
7587
"The attribute 'type' and the <simpleType> child "
7588
"are mutually exclusive", NULL);
7589
} else
7590
ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7591
child = child->next;
7592
}
7593
if (child != NULL)
7594
xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7595
NULL, node, child, NULL,
7596
"(annotation?, simpleType?)");
7597
7598
return (ret);
7599
}
7600
7601
/**
7602
* xmlSchemaParseAttributeGroupRef:
7603
* @ctxt: a schema validation context
7604
* @schema: the schema being built
7605
* @node: a subtree containing XML Schema information
7606
*
7607
* Parse an attribute group definition reference.
7608
* Note that a reference to an attribute group does not
7609
* correspond to any component at all.
7610
* *WARNING* this interface is highly subject to change
7611
*
7612
* Returns the attribute group or NULL in case of error.
7613
*/
7614
static xmlSchemaQNameRefPtr
7615
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7616
xmlSchemaPtr schema,
7617
xmlNodePtr node)
7618
{
7619
xmlSchemaQNameRefPtr ret;
7620
xmlNodePtr child = NULL;
7621
xmlAttrPtr attr;
7622
const xmlChar *refNs = NULL, *ref = NULL;
7623
7624
if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7625
return (NULL);
7626
7627
attr = xmlSchemaGetPropNode(node, "ref");
7628
if (attr == NULL) {
7629
xmlSchemaPMissingAttrErr(pctxt,
7630
XML_SCHEMAP_S4S_ATTR_MISSING,
7631
NULL, node, "ref", NULL);
7632
return (NULL);
7633
}
7634
xmlSchemaPValAttrNodeQName(pctxt, schema,
7635
NULL, attr, &refNs, &ref);
7636
if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7637
return(NULL);
7638
7639
/*
7640
* Check for illegal attributes.
7641
*/
7642
attr = node->properties;
7643
while (attr != NULL) {
7644
if (attr->ns == NULL) {
7645
if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7646
(!xmlStrEqual(attr->name, BAD_CAST "id")))
7647
{
7648
xmlSchemaPIllegalAttrErr(pctxt,
7649
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7650
}
7651
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7652
xmlSchemaPIllegalAttrErr(pctxt,
7653
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7654
}
7655
attr = attr->next;
7656
}
7657
/* Attribute ID */
7658
xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7659
7660
/*
7661
* And now for the children...
7662
*/
7663
child = node->children;
7664
if (IS_SCHEMA(child, "annotation")) {
7665
/*
7666
* TODO: We do not have a place to store the annotation, do we?
7667
*/
7668
xmlSchemaParseAnnotation(pctxt, child, 0);
7669
child = child->next;
7670
}
7671
if (child != NULL) {
7672
xmlSchemaPContentErr(pctxt,
7673
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7674
NULL, node, child, NULL,
7675
"(annotation?)");
7676
}
7677
7678
/*
7679
* Handle attribute group redefinitions.
7680
*/
7681
if (pctxt->isRedefine && pctxt->redef &&
7682
(pctxt->redef->item->type ==
7683
XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7684
(ref == pctxt->redef->refName) &&
7685
(refNs == pctxt->redef->refTargetNs))
7686
{
7687
/*
7688
* SPEC src-redefine:
7689
* (7.1) "If it has an <attributeGroup> among its contents
7690
* the `actual value` of whose ref [attribute] is the same
7691
* as the `actual value` of its own name attribute plus
7692
* target namespace, then it must have exactly one such group."
7693
*/
7694
if (pctxt->redefCounter != 0) {
7695
xmlChar *str = NULL;
7696
7697
xmlSchemaCustomErr(ACTXT_CAST pctxt,
7698
XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7699
"The redefining attribute group definition "
7700
"'%s' must not contain more than one "
7701
"reference to the redefined definition",
7702
xmlSchemaFormatQName(&str, refNs, ref), NULL);
7703
FREE_AND_NULL(str);
7704
return(NULL);
7705
}
7706
pctxt->redefCounter++;
7707
/*
7708
* URGENT TODO: How to ensure that the reference will not be
7709
* handled by the normal component resolution mechanism?
7710
*/
7711
ret = xmlSchemaNewQNameRef(pctxt,
7712
XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7713
if (ret == NULL)
7714
return(NULL);
7715
ret->node = node;
7716
pctxt->redef->reference = WXS_BASIC_CAST ret;
7717
} else {
7718
/*
7719
* Create a QName-reference helper component. We will substitute this
7720
* component for the attribute uses of the referenced attribute group
7721
* definition.
7722
*/
7723
ret = xmlSchemaNewQNameRef(pctxt,
7724
XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7725
if (ret == NULL)
7726
return(NULL);
7727
ret->node = node;
7728
/* Add to pending items, to be able to resolve the reference. */
7729
WXS_ADD_PENDING(pctxt, ret);
7730
}
7731
return (ret);
7732
}
7733
7734
/**
7735
* xmlSchemaParseAttributeGroupDefinition:
7736
* @pctxt: a schema validation context
7737
* @schema: the schema being built
7738
* @node: a subtree containing XML Schema information
7739
*
7740
* parse a XML schema Attribute Group declaration
7741
* *WARNING* this interface is highly subject to change
7742
*
7743
* Returns the attribute group definition or NULL in case of error.
7744
*/
7745
static xmlSchemaAttributeGroupPtr
7746
xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7747
xmlSchemaPtr schema,
7748
xmlNodePtr node)
7749
{
7750
const xmlChar *name;
7751
xmlSchemaAttributeGroupPtr ret;
7752
xmlNodePtr child = NULL;
7753
xmlAttrPtr attr;
7754
int hasRefs = 0;
7755
7756
if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7757
return (NULL);
7758
7759
attr = xmlSchemaGetPropNode(node, "name");
7760
if (attr == NULL) {
7761
xmlSchemaPMissingAttrErr(pctxt,
7762
XML_SCHEMAP_S4S_ATTR_MISSING,
7763
NULL, node, "name", NULL);
7764
return (NULL);
7765
}
7766
/*
7767
* The name is crucial, exit if invalid.
7768
*/
7769
if (xmlSchemaPValAttrNode(pctxt,
7770
NULL, attr,
7771
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7772
return (NULL);
7773
}
7774
ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7775
name, pctxt->targetNamespace, node);
7776
if (ret == NULL)
7777
return (NULL);
7778
/*
7779
* Check for illegal attributes.
7780
*/
7781
attr = node->properties;
7782
while (attr != NULL) {
7783
if (attr->ns == NULL) {
7784
if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7785
(!xmlStrEqual(attr->name, BAD_CAST "id")))
7786
{
7787
xmlSchemaPIllegalAttrErr(pctxt,
7788
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7789
}
7790
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7791
xmlSchemaPIllegalAttrErr(pctxt,
7792
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7793
}
7794
attr = attr->next;
7795
}
7796
/* Attribute ID */
7797
xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7798
/*
7799
* And now for the children...
7800
*/
7801
child = node->children;
7802
if (IS_SCHEMA(child, "annotation")) {
7803
ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7804
child = child->next;
7805
}
7806
/*
7807
* Parse contained attribute decls/refs.
7808
*/
7809
if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7810
(xmlSchemaItemListPtr *) &(ret->attrUses),
7811
XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7812
return(NULL);
7813
if (hasRefs)
7814
ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7815
/*
7816
* Parse the attribute wildcard.
7817
*/
7818
if (IS_SCHEMA(child, "anyAttribute")) {
7819
ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7820
schema, child);
7821
child = child->next;
7822
}
7823
if (child != NULL) {
7824
xmlSchemaPContentErr(pctxt,
7825
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7826
NULL, node, child, NULL,
7827
"(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7828
}
7829
return (ret);
7830
}
7831
7832
/**
7833
* xmlSchemaPValAttrFormDefault:
7834
* @value: the value
7835
* @flags: the flags to be modified
7836
* @flagQualified: the specific flag for "qualified"
7837
*
7838
* Returns 0 if the value is valid, 1 otherwise.
7839
*/
7840
static int
7841
xmlSchemaPValAttrFormDefault(const xmlChar *value,
7842
int *flags,
7843
int flagQualified)
7844
{
7845
if (xmlStrEqual(value, BAD_CAST "qualified")) {
7846
if ((*flags & flagQualified) == 0)
7847
*flags |= flagQualified;
7848
} else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7849
return (1);
7850
7851
return (0);
7852
}
7853
7854
/**
7855
* xmlSchemaPValAttrBlockFinal:
7856
* @value: the value
7857
* @flags: the flags to be modified
7858
* @flagAll: the specific flag for "#all"
7859
* @flagExtension: the specific flag for "extension"
7860
* @flagRestriction: the specific flag for "restriction"
7861
* @flagSubstitution: the specific flag for "substitution"
7862
* @flagList: the specific flag for "list"
7863
* @flagUnion: the specific flag for "union"
7864
*
7865
* Validates the value of the attribute "final" and "block". The value
7866
* is converted into the specified flag values and returned in @flags.
7867
*
7868
* Returns 0 if the value is valid, 1 otherwise.
7869
*/
7870
7871
static int
7872
xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7873
int *flags,
7874
int flagAll,
7875
int flagExtension,
7876
int flagRestriction,
7877
int flagSubstitution,
7878
int flagList,
7879
int flagUnion)
7880
{
7881
int ret = 0;
7882
7883
/*
7884
* TODO: This does not check for duplicate entries.
7885
*/
7886
if ((flags == NULL) || (value == NULL))
7887
return (-1);
7888
if (value[0] == 0)
7889
return (0);
7890
if (xmlStrEqual(value, BAD_CAST "#all")) {
7891
if (flagAll != -1)
7892
*flags |= flagAll;
7893
else {
7894
if (flagExtension != -1)
7895
*flags |= flagExtension;
7896
if (flagRestriction != -1)
7897
*flags |= flagRestriction;
7898
if (flagSubstitution != -1)
7899
*flags |= flagSubstitution;
7900
if (flagList != -1)
7901
*flags |= flagList;
7902
if (flagUnion != -1)
7903
*flags |= flagUnion;
7904
}
7905
} else {
7906
const xmlChar *end, *cur = value;
7907
xmlChar *item;
7908
7909
do {
7910
while (IS_BLANK_CH(*cur))
7911
cur++;
7912
end = cur;
7913
while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7914
end++;
7915
if (end == cur)
7916
break;
7917
item = xmlStrndup(cur, end - cur);
7918
if (xmlStrEqual(item, BAD_CAST "extension")) {
7919
if (flagExtension != -1) {
7920
if ((*flags & flagExtension) == 0)
7921
*flags |= flagExtension;
7922
} else
7923
ret = 1;
7924
} else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7925
if (flagRestriction != -1) {
7926
if ((*flags & flagRestriction) == 0)
7927
*flags |= flagRestriction;
7928
} else
7929
ret = 1;
7930
} else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7931
if (flagSubstitution != -1) {
7932
if ((*flags & flagSubstitution) == 0)
7933
*flags |= flagSubstitution;
7934
} else
7935
ret = 1;
7936
} else if (xmlStrEqual(item, BAD_CAST "list")) {
7937
if (flagList != -1) {
7938
if ((*flags & flagList) == 0)
7939
*flags |= flagList;
7940
} else
7941
ret = 1;
7942
} else if (xmlStrEqual(item, BAD_CAST "union")) {
7943
if (flagUnion != -1) {
7944
if ((*flags & flagUnion) == 0)
7945
*flags |= flagUnion;
7946
} else
7947
ret = 1;
7948
} else
7949
ret = 1;
7950
if (item != NULL)
7951
xmlFree(item);
7952
cur = end;
7953
} while ((ret == 0) && (*cur != 0));
7954
}
7955
7956
return (ret);
7957
}
7958
7959
static int
7960
xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7961
xmlSchemaIDCPtr idc,
7962
xmlSchemaIDCSelectPtr selector,
7963
xmlAttrPtr attr,
7964
int isField)
7965
{
7966
xmlNodePtr node;
7967
7968
/*
7969
* c-selector-xpath:
7970
* Schema Component Constraint: Selector Value OK
7971
*
7972
* TODO: 1 The {selector} must be a valid XPath expression, as defined
7973
* in [XPath].
7974
*/
7975
if (selector == NULL) {
7976
xmlSchemaPErr(ctxt, idc->node,
7977
XML_SCHEMAP_INTERNAL,
7978
"Internal error: xmlSchemaCheckCSelectorXPath, "
7979
"the selector is not specified.\n", NULL, NULL);
7980
return (-1);
7981
}
7982
if (attr == NULL)
7983
node = idc->node;
7984
else
7985
node = (xmlNodePtr) attr;
7986
if (selector->xpath == NULL) {
7987
xmlSchemaPCustomErr(ctxt,
7988
/* TODO: Adjust error code. */
7989
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7990
NULL, node,
7991
"The XPath expression of the selector is not valid", NULL);
7992
return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7993
} else {
7994
const xmlChar **nsArray = NULL;
7995
xmlNsPtr *nsList = NULL;
7996
/*
7997
* Compile the XPath expression.
7998
*/
7999
/*
8000
* TODO: We need the array of in-scope namespaces for compilation.
8001
* TODO: Call xmlPatterncompile with different options for selector/
8002
* field.
8003
*/
8004
if (attr == NULL)
8005
nsList = NULL;
8006
else
8007
nsList = xmlGetNsList(attr->doc, attr->parent);
8008
/*
8009
* Build an array of prefixes and namespaces.
8010
*/
8011
if (nsList != NULL) {
8012
int i, count = 0;
8013
8014
for (i = 0; nsList[i] != NULL; i++)
8015
count++;
8016
8017
nsArray = (const xmlChar **) xmlMalloc(
8018
(count * 2 + 1) * sizeof(const xmlChar *));
8019
if (nsArray == NULL) {
8020
xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8021
NULL);
8022
xmlFree(nsList);
8023
return (-1);
8024
}
8025
for (i = 0; i < count; i++) {
8026
nsArray[2 * i] = nsList[i]->href;
8027
nsArray[2 * i + 1] = nsList[i]->prefix;
8028
}
8029
nsArray[count * 2] = NULL;
8030
xmlFree(nsList);
8031
}
8032
/*
8033
* TODO: Differentiate between "selector" and "field".
8034
*/
8035
if (isField)
8036
selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8037
NULL, XML_PATTERN_XSFIELD, nsArray);
8038
else
8039
selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8040
NULL, XML_PATTERN_XSSEL, nsArray);
8041
if (nsArray != NULL)
8042
xmlFree((xmlChar **) nsArray);
8043
8044
if (selector->xpathComp == NULL) {
8045
xmlSchemaPCustomErr(ctxt,
8046
/* TODO: Adjust error code? */
8047
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8048
NULL, node,
8049
"The XPath expression '%s' could not be "
8050
"compiled", selector->xpath);
8051
return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8052
}
8053
}
8054
return (0);
8055
}
8056
8057
#define ADD_ANNOTATION(annot) \
8058
xmlSchemaAnnotPtr cur = item->annot; \
8059
if (item->annot == NULL) { \
8060
item->annot = annot; \
8061
return (annot); \
8062
} \
8063
cur = item->annot; \
8064
if (cur->next != NULL) { \
8065
cur = cur->next; \
8066
} \
8067
cur->next = annot;
8068
8069
/**
8070
* xmlSchemaAssignAnnotation:
8071
* @item: the schema component
8072
* @annot: the annotation
8073
*
8074
* Adds the annotation to the given schema component.
8075
*
8076
* Returns the given annotation.
8077
*/
8078
static xmlSchemaAnnotPtr
8079
xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8080
xmlSchemaAnnotPtr annot)
8081
{
8082
if ((annItem == NULL) || (annot == NULL))
8083
return (NULL);
8084
switch (annItem->type) {
8085
case XML_SCHEMA_TYPE_ELEMENT: {
8086
xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8087
ADD_ANNOTATION(annot)
8088
}
8089
break;
8090
case XML_SCHEMA_TYPE_ATTRIBUTE: {
8091
xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8092
ADD_ANNOTATION(annot)
8093
}
8094
break;
8095
case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8096
case XML_SCHEMA_TYPE_ANY: {
8097
xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8098
ADD_ANNOTATION(annot)
8099
}
8100
break;
8101
case XML_SCHEMA_TYPE_PARTICLE:
8102
case XML_SCHEMA_TYPE_IDC_KEY:
8103
case XML_SCHEMA_TYPE_IDC_KEYREF:
8104
case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8105
xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8106
ADD_ANNOTATION(annot)
8107
}
8108
break;
8109
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8110
xmlSchemaAttributeGroupPtr item =
8111
(xmlSchemaAttributeGroupPtr) annItem;
8112
ADD_ANNOTATION(annot)
8113
}
8114
break;
8115
case XML_SCHEMA_TYPE_NOTATION: {
8116
xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8117
ADD_ANNOTATION(annot)
8118
}
8119
break;
8120
case XML_SCHEMA_FACET_MININCLUSIVE:
8121
case XML_SCHEMA_FACET_MINEXCLUSIVE:
8122
case XML_SCHEMA_FACET_MAXINCLUSIVE:
8123
case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8124
case XML_SCHEMA_FACET_TOTALDIGITS:
8125
case XML_SCHEMA_FACET_FRACTIONDIGITS:
8126
case XML_SCHEMA_FACET_PATTERN:
8127
case XML_SCHEMA_FACET_ENUMERATION:
8128
case XML_SCHEMA_FACET_WHITESPACE:
8129
case XML_SCHEMA_FACET_LENGTH:
8130
case XML_SCHEMA_FACET_MAXLENGTH:
8131
case XML_SCHEMA_FACET_MINLENGTH: {
8132
xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8133
ADD_ANNOTATION(annot)
8134
}
8135
break;
8136
case XML_SCHEMA_TYPE_SIMPLE:
8137
case XML_SCHEMA_TYPE_COMPLEX: {
8138
xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8139
ADD_ANNOTATION(annot)
8140
}
8141
break;
8142
case XML_SCHEMA_TYPE_GROUP: {
8143
xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8144
ADD_ANNOTATION(annot)
8145
}
8146
break;
8147
case XML_SCHEMA_TYPE_SEQUENCE:
8148
case XML_SCHEMA_TYPE_CHOICE:
8149
case XML_SCHEMA_TYPE_ALL: {
8150
xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8151
ADD_ANNOTATION(annot)
8152
}
8153
break;
8154
default:
8155
xmlSchemaPCustomErr(NULL,
8156
XML_SCHEMAP_INTERNAL,
8157
NULL, NULL,
8158
"Internal error: xmlSchemaAddAnnotation, "
8159
"The item is not a annotated schema component", NULL);
8160
break;
8161
}
8162
return (annot);
8163
}
8164
8165
/**
8166
* xmlSchemaParseIDCSelectorAndField:
8167
* @ctxt: a schema validation context
8168
* @schema: the schema being built
8169
* @node: a subtree containing XML Schema information
8170
*
8171
* Parses a XML Schema identity-constraint definition's
8172
* <selector> and <field> elements.
8173
*
8174
* Returns the parsed identity-constraint definition.
8175
*/
8176
static xmlSchemaIDCSelectPtr
8177
xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8178
xmlSchemaIDCPtr idc,
8179
xmlNodePtr node,
8180
int isField)
8181
{
8182
xmlSchemaIDCSelectPtr item;
8183
xmlNodePtr child = NULL;
8184
xmlAttrPtr attr;
8185
8186
/*
8187
* Check for illegal attributes.
8188
*/
8189
attr = node->properties;
8190
while (attr != NULL) {
8191
if (attr->ns == NULL) {
8192
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8193
(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8194
xmlSchemaPIllegalAttrErr(ctxt,
8195
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8196
}
8197
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8198
xmlSchemaPIllegalAttrErr(ctxt,
8199
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8200
}
8201
attr = attr->next;
8202
}
8203
/*
8204
* Create the item.
8205
*/
8206
item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8207
if (item == NULL) {
8208
xmlSchemaPErrMemory(ctxt,
8209
"allocating a 'selector' of an identity-constraint definition",
8210
NULL);
8211
return (NULL);
8212
}
8213
memset(item, 0, sizeof(xmlSchemaIDCSelect));
8214
/*
8215
* Attribute "xpath" (mandatory).
8216
*/
8217
attr = xmlSchemaGetPropNode(node, "xpath");
8218
if (attr == NULL) {
8219
xmlSchemaPMissingAttrErr(ctxt,
8220
XML_SCHEMAP_S4S_ATTR_MISSING,
8221
NULL, node,
8222
"name", NULL);
8223
} else {
8224
item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8225
/*
8226
* URGENT TODO: "field"s have an other syntax than "selector"s.
8227
*/
8228
8229
if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8230
isField) == -1) {
8231
xmlSchemaPErr(ctxt,
8232
(xmlNodePtr) attr,
8233
XML_SCHEMAP_INTERNAL,
8234
"Internal error: xmlSchemaParseIDCSelectorAndField, "
8235
"validating the XPath expression of a IDC selector.\n",
8236
NULL, NULL);
8237
}
8238
8239
}
8240
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8241
/*
8242
* And now for the children...
8243
*/
8244
child = node->children;
8245
if (IS_SCHEMA(child, "annotation")) {
8246
/*
8247
* Add the annotation to the parent IDC.
8248
*/
8249
xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8250
xmlSchemaParseAnnotation(ctxt, child, 1));
8251
child = child->next;
8252
}
8253
if (child != NULL) {
8254
xmlSchemaPContentErr(ctxt,
8255
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8256
NULL, node, child,
8257
NULL, "(annotation?)");
8258
}
8259
8260
return (item);
8261
}
8262
8263
/**
8264
* xmlSchemaParseIDC:
8265
* @ctxt: a schema validation context
8266
* @schema: the schema being built
8267
* @node: a subtree containing XML Schema information
8268
*
8269
* Parses a XML Schema identity-constraint definition.
8270
*
8271
* Returns the parsed identity-constraint definition.
8272
*/
8273
static xmlSchemaIDCPtr
8274
xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8275
xmlSchemaPtr schema,
8276
xmlNodePtr node,
8277
xmlSchemaTypeType idcCategory,
8278
const xmlChar *targetNamespace)
8279
{
8280
xmlSchemaIDCPtr item = NULL;
8281
xmlNodePtr child = NULL;
8282
xmlAttrPtr attr;
8283
const xmlChar *name = NULL;
8284
xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8285
8286
/*
8287
* Check for illegal attributes.
8288
*/
8289
attr = node->properties;
8290
while (attr != NULL) {
8291
if (attr->ns == NULL) {
8292
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8293
(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8294
((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8295
(!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8296
xmlSchemaPIllegalAttrErr(ctxt,
8297
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8298
}
8299
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8300
xmlSchemaPIllegalAttrErr(ctxt,
8301
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8302
}
8303
attr = attr->next;
8304
}
8305
/*
8306
* Attribute "name" (mandatory).
8307
*/
8308
attr = xmlSchemaGetPropNode(node, "name");
8309
if (attr == NULL) {
8310
xmlSchemaPMissingAttrErr(ctxt,
8311
XML_SCHEMAP_S4S_ATTR_MISSING,
8312
NULL, node,
8313
"name", NULL);
8314
return (NULL);
8315
} else if (xmlSchemaPValAttrNode(ctxt,
8316
NULL, attr,
8317
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8318
return (NULL);
8319
}
8320
/* Create the component. */
8321
item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8322
idcCategory, node);
8323
if (item == NULL)
8324
return(NULL);
8325
8326
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8327
if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8328
/*
8329
* Attribute "refer" (mandatory).
8330
*/
8331
attr = xmlSchemaGetPropNode(node, "refer");
8332
if (attr == NULL) {
8333
xmlSchemaPMissingAttrErr(ctxt,
8334
XML_SCHEMAP_S4S_ATTR_MISSING,
8335
NULL, node,
8336
"refer", NULL);
8337
} else {
8338
/*
8339
* Create a reference item.
8340
*/
8341
item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8342
NULL, NULL);
8343
if (item->ref == NULL)
8344
return (NULL);
8345
xmlSchemaPValAttrNodeQName(ctxt, schema,
8346
NULL, attr,
8347
&(item->ref->targetNamespace),
8348
&(item->ref->name));
8349
xmlSchemaCheckReference(ctxt, schema, node, attr,
8350
item->ref->targetNamespace);
8351
}
8352
}
8353
/*
8354
* And now for the children...
8355
*/
8356
child = node->children;
8357
if (IS_SCHEMA(child, "annotation")) {
8358
item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8359
child = child->next;
8360
}
8361
if (child == NULL) {
8362
xmlSchemaPContentErr(ctxt,
8363
XML_SCHEMAP_S4S_ELEM_MISSING,
8364
NULL, node, child,
8365
"A child element is missing",
8366
"(annotation?, (selector, field+))");
8367
}
8368
/*
8369
* Child element <selector>.
8370
*/
8371
if (IS_SCHEMA(child, "selector")) {
8372
item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8373
item, child, 0);
8374
child = child->next;
8375
/*
8376
* Child elements <field>.
8377
*/
8378
if (IS_SCHEMA(child, "field")) {
8379
do {
8380
field = xmlSchemaParseIDCSelectorAndField(ctxt,
8381
item, child, 1);
8382
if (field != NULL) {
8383
field->index = item->nbFields;
8384
item->nbFields++;
8385
if (lastField != NULL)
8386
lastField->next = field;
8387
else
8388
item->fields = field;
8389
lastField = field;
8390
}
8391
child = child->next;
8392
} while (IS_SCHEMA(child, "field"));
8393
} else {
8394
xmlSchemaPContentErr(ctxt,
8395
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8396
NULL, node, child,
8397
NULL, "(annotation?, (selector, field+))");
8398
}
8399
}
8400
if (child != NULL) {
8401
xmlSchemaPContentErr(ctxt,
8402
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8403
NULL, node, child,
8404
NULL, "(annotation?, (selector, field+))");
8405
}
8406
8407
return (item);
8408
}
8409
8410
/**
8411
* xmlSchemaParseElement:
8412
* @ctxt: a schema validation context
8413
* @schema: the schema being built
8414
* @node: a subtree containing XML Schema information
8415
* @topLevel: indicates if this is global declaration
8416
*
8417
* Parses a XML schema element declaration.
8418
* *WARNING* this interface is highly subject to change
8419
*
8420
* Returns the element declaration or a particle; NULL in case
8421
* of an error or if the particle has minOccurs==maxOccurs==0.
8422
*/
8423
static xmlSchemaBasicItemPtr
8424
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8425
xmlNodePtr node, int *isElemRef, int topLevel)
8426
{
8427
xmlSchemaElementPtr decl = NULL;
8428
xmlSchemaParticlePtr particle = NULL;
8429
xmlSchemaAnnotPtr annot = NULL;
8430
xmlNodePtr child = NULL;
8431
xmlAttrPtr attr, nameAttr;
8432
int min, max, isRef = 0;
8433
xmlChar *des = NULL;
8434
8435
/* 3.3.3 Constraints on XML Representations of Element Declarations */
8436
/* TODO: Complete implementation of 3.3.6 */
8437
8438
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8439
return (NULL);
8440
8441
if (isElemRef != NULL)
8442
*isElemRef = 0;
8443
/*
8444
* If we get a "ref" attribute on a local <element> we will assume it's
8445
* a reference - even if there's a "name" attribute; this seems to be more
8446
* robust.
8447
*/
8448
nameAttr = xmlSchemaGetPropNode(node, "name");
8449
attr = xmlSchemaGetPropNode(node, "ref");
8450
if ((topLevel) || (attr == NULL)) {
8451
if (nameAttr == NULL) {
8452
xmlSchemaPMissingAttrErr(ctxt,
8453
XML_SCHEMAP_S4S_ATTR_MISSING,
8454
NULL, node, "name", NULL);
8455
return (NULL);
8456
}
8457
} else
8458
isRef = 1;
8459
8460
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8461
child = node->children;
8462
if (IS_SCHEMA(child, "annotation")) {
8463
annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8464
child = child->next;
8465
}
8466
/*
8467
* Skip particle part if a global declaration.
8468
*/
8469
if (topLevel)
8470
goto declaration_part;
8471
/*
8472
* The particle part ==================================================
8473
*/
8474
min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8475
max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8476
xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8477
particle = xmlSchemaAddParticle(ctxt, node, min, max);
8478
if (particle == NULL)
8479
goto return_null;
8480
8481
/* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8482
8483
if (isRef) {
8484
const xmlChar *refNs = NULL, *ref = NULL;
8485
xmlSchemaQNameRefPtr refer = NULL;
8486
/*
8487
* The reference part =============================================
8488
*/
8489
if (isElemRef != NULL)
8490
*isElemRef = 1;
8491
8492
xmlSchemaPValAttrNodeQName(ctxt, schema,
8493
NULL, attr, &refNs, &ref);
8494
xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8495
/*
8496
* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8497
*/
8498
if (nameAttr != NULL) {
8499
xmlSchemaPMutualExclAttrErr(ctxt,
8500
XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8501
}
8502
/*
8503
* Check for illegal attributes.
8504
*/
8505
attr = node->properties;
8506
while (attr != NULL) {
8507
if (attr->ns == NULL) {
8508
if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8509
xmlStrEqual(attr->name, BAD_CAST "name") ||
8510
xmlStrEqual(attr->name, BAD_CAST "id") ||
8511
xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8512
xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8513
{
8514
attr = attr->next;
8515
continue;
8516
} else {
8517
/* SPEC (3.3.3 : 2.2) */
8518
xmlSchemaPCustomAttrErr(ctxt,
8519
XML_SCHEMAP_SRC_ELEMENT_2_2,
8520
NULL, NULL, attr,
8521
"Only the attributes 'minOccurs', 'maxOccurs' and "
8522
"'id' are allowed in addition to 'ref'");
8523
break;
8524
}
8525
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8526
xmlSchemaPIllegalAttrErr(ctxt,
8527
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8528
}
8529
attr = attr->next;
8530
}
8531
/*
8532
* No children except <annotation> expected.
8533
*/
8534
if (child != NULL) {
8535
xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8536
NULL, node, child, NULL, "(annotation?)");
8537
}
8538
if ((min == 0) && (max == 0))
8539
goto return_null;
8540
/*
8541
* Create the reference item and attach it to the particle.
8542
*/
8543
refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8544
ref, refNs);
8545
if (refer == NULL)
8546
goto return_null;
8547
particle->children = (xmlSchemaTreeItemPtr) refer;
8548
particle->annot = annot;
8549
/*
8550
* Add the particle to pending components, since the reference
8551
* need to be resolved.
8552
*/
8553
WXS_ADD_PENDING(ctxt, particle);
8554
return ((xmlSchemaBasicItemPtr) particle);
8555
}
8556
/*
8557
* The declaration part ===============================================
8558
*/
8559
declaration_part:
8560
{
8561
const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8562
xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8563
8564
if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8565
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8566
goto return_null;
8567
/*
8568
* Evaluate the target namespace.
8569
*/
8570
if (topLevel) {
8571
ns = ctxt->targetNamespace;
8572
} else {
8573
attr = xmlSchemaGetPropNode(node, "form");
8574
if (attr != NULL) {
8575
attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8576
if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8577
ns = ctxt->targetNamespace;
8578
} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8579
xmlSchemaPSimpleTypeErr(ctxt,
8580
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8581
NULL, (xmlNodePtr) attr,
8582
NULL, "(qualified | unqualified)",
8583
attrValue, NULL, NULL, NULL);
8584
}
8585
} else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8586
ns = ctxt->targetNamespace;
8587
}
8588
decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8589
if (decl == NULL) {
8590
goto return_null;
8591
}
8592
/*
8593
* Check for illegal attributes.
8594
*/
8595
attr = node->properties;
8596
while (attr != NULL) {
8597
if (attr->ns == NULL) {
8598
if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8599
(!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8600
(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8601
(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8602
(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8603
(!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8604
(!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8605
{
8606
if (topLevel == 0) {
8607
if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8608
(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8609
(!xmlStrEqual(attr->name, BAD_CAST "form")))
8610
{
8611
xmlSchemaPIllegalAttrErr(ctxt,
8612
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8613
}
8614
} else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8615
(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8616
(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8617
8618
xmlSchemaPIllegalAttrErr(ctxt,
8619
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8620
}
8621
}
8622
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8623
8624
xmlSchemaPIllegalAttrErr(ctxt,
8625
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8626
}
8627
attr = attr->next;
8628
}
8629
/*
8630
* Extract/validate attributes.
8631
*/
8632
if (topLevel) {
8633
/*
8634
* Process top attributes of global element declarations here.
8635
*/
8636
decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8637
decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8638
xmlSchemaPValAttrQName(ctxt, schema,
8639
NULL, node, "substitutionGroup",
8640
&(decl->substGroupNs), &(decl->substGroup));
8641
if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8642
decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8643
/*
8644
* Attribute "final".
8645
*/
8646
attr = xmlSchemaGetPropNode(node, "final");
8647
if (attr == NULL) {
8648
if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8649
decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8650
if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8651
decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8652
} else {
8653
attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8654
if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8655
-1,
8656
XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8657
XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8658
xmlSchemaPSimpleTypeErr(ctxt,
8659
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8660
NULL, (xmlNodePtr) attr,
8661
NULL, "(#all | List of (extension | restriction))",
8662
attrValue, NULL, NULL, NULL);
8663
}
8664
}
8665
}
8666
/*
8667
* Attribute "block".
8668
*/
8669
attr = xmlSchemaGetPropNode(node, "block");
8670
if (attr == NULL) {
8671
/*
8672
* Apply default "block" values.
8673
*/
8674
if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8675
decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8676
if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8677
decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8678
if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8679
decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8680
} else {
8681
attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8682
if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8683
-1,
8684
XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8685
XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8686
XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8687
xmlSchemaPSimpleTypeErr(ctxt,
8688
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8689
NULL, (xmlNodePtr) attr,
8690
NULL, "(#all | List of (extension | "
8691
"restriction | substitution))", attrValue,
8692
NULL, NULL, NULL);
8693
}
8694
}
8695
if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8696
decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8697
8698
attr = xmlSchemaGetPropNode(node, "type");
8699
if (attr != NULL) {
8700
xmlSchemaPValAttrNodeQName(ctxt, schema,
8701
NULL, attr,
8702
&(decl->namedTypeNs), &(decl->namedType));
8703
xmlSchemaCheckReference(ctxt, schema, node,
8704
attr, decl->namedTypeNs);
8705
}
8706
decl->value = xmlSchemaGetProp(ctxt, node, "default");
8707
attr = xmlSchemaGetPropNode(node, "fixed");
8708
if (attr != NULL) {
8709
fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8710
if (decl->value != NULL) {
8711
/*
8712
* 3.3.3 : 1
8713
* default and fixed must not both be present.
8714
*/
8715
xmlSchemaPMutualExclAttrErr(ctxt,
8716
XML_SCHEMAP_SRC_ELEMENT_1,
8717
NULL, attr, "default", "fixed");
8718
} else {
8719
decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8720
decl->value = fixed;
8721
}
8722
}
8723
/*
8724
* And now for the children...
8725
*/
8726
if (IS_SCHEMA(child, "complexType")) {
8727
/*
8728
* 3.3.3 : 3
8729
* "type" and either <simpleType> or <complexType> are mutually
8730
* exclusive
8731
*/
8732
if (decl->namedType != NULL) {
8733
xmlSchemaPContentErr(ctxt,
8734
XML_SCHEMAP_SRC_ELEMENT_3,
8735
NULL, node, child,
8736
"The attribute 'type' and the <complexType> child are "
8737
"mutually exclusive", NULL);
8738
} else
8739
WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8740
child = child->next;
8741
} else if (IS_SCHEMA(child, "simpleType")) {
8742
/*
8743
* 3.3.3 : 3
8744
* "type" and either <simpleType> or <complexType> are
8745
* mutually exclusive
8746
*/
8747
if (decl->namedType != NULL) {
8748
xmlSchemaPContentErr(ctxt,
8749
XML_SCHEMAP_SRC_ELEMENT_3,
8750
NULL, node, child,
8751
"The attribute 'type' and the <simpleType> child are "
8752
"mutually exclusive", NULL);
8753
} else
8754
WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8755
child = child->next;
8756
}
8757
while ((IS_SCHEMA(child, "unique")) ||
8758
(IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8759
if (IS_SCHEMA(child, "unique")) {
8760
curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8761
XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8762
} else if (IS_SCHEMA(child, "key")) {
8763
curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8764
XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8765
} else if (IS_SCHEMA(child, "keyref")) {
8766
curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8767
XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8768
}
8769
if (lastIDC != NULL)
8770
lastIDC->next = curIDC;
8771
else
8772
decl->idcs = (void *) curIDC;
8773
lastIDC = curIDC;
8774
child = child->next;
8775
}
8776
if (child != NULL) {
8777
xmlSchemaPContentErr(ctxt,
8778
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8779
NULL, node, child,
8780
NULL, "(annotation?, ((simpleType | complexType)?, "
8781
"(unique | key | keyref)*))");
8782
}
8783
decl->annot = annot;
8784
}
8785
/*
8786
* NOTE: Element Declaration Representation OK 4. will be checked at a
8787
* different layer.
8788
*/
8789
FREE_AND_NULL(des)
8790
if (topLevel)
8791
return ((xmlSchemaBasicItemPtr) decl);
8792
else {
8793
particle->children = (xmlSchemaTreeItemPtr) decl;
8794
return ((xmlSchemaBasicItemPtr) particle);
8795
}
8796
8797
return_null:
8798
FREE_AND_NULL(des);
8799
if (annot != NULL) {
8800
if (particle != NULL)
8801
particle->annot = NULL;
8802
if (decl != NULL)
8803
decl->annot = NULL;
8804
xmlSchemaFreeAnnot(annot);
8805
}
8806
return (NULL);
8807
}
8808
8809
/**
8810
* xmlSchemaParseUnion:
8811
* @ctxt: a schema validation context
8812
* @schema: the schema being built
8813
* @node: a subtree containing XML Schema information
8814
*
8815
* parse a XML schema Union definition
8816
* *WARNING* this interface is highly subject to change
8817
*
8818
* Returns -1 in case of internal error, 0 in case of success and a positive
8819
* error code otherwise.
8820
*/
8821
static int
8822
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8823
xmlNodePtr node)
8824
{
8825
xmlSchemaTypePtr type;
8826
xmlNodePtr child = NULL;
8827
xmlAttrPtr attr;
8828
const xmlChar *cur = NULL;
8829
8830
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8831
return (-1);
8832
/* Not a component, don't create it. */
8833
type = ctxt->ctxtType;
8834
/*
8835
* Mark the simple type as being of variety "union".
8836
*/
8837
type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8838
/*
8839
* SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8840
* then the `simple ur-type definition`."
8841
*/
8842
type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8843
/*
8844
* Check for illegal attributes.
8845
*/
8846
attr = node->properties;
8847
while (attr != NULL) {
8848
if (attr->ns == NULL) {
8849
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8850
(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8851
xmlSchemaPIllegalAttrErr(ctxt,
8852
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8853
}
8854
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8855
xmlSchemaPIllegalAttrErr(ctxt,
8856
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8857
}
8858
attr = attr->next;
8859
}
8860
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8861
/*
8862
* Attribute "memberTypes". This is a list of QNames.
8863
* TODO: Check the value to contain anything.
8864
*/
8865
attr = xmlSchemaGetPropNode(node, "memberTypes");
8866
if (attr != NULL) {
8867
const xmlChar *end;
8868
xmlChar *tmp;
8869
const xmlChar *localName, *nsName;
8870
xmlSchemaTypeLinkPtr link, lastLink = NULL;
8871
xmlSchemaQNameRefPtr ref;
8872
8873
cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8874
if (cur == NULL)
8875
return (-1);
8876
type->base = cur;
8877
do {
8878
while (IS_BLANK_CH(*cur))
8879
cur++;
8880
end = cur;
8881
while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8882
end++;
8883
if (end == cur)
8884
break;
8885
tmp = xmlStrndup(cur, end - cur);
8886
if (tmp == NULL) {
8887
xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8888
"duplicating type name", NULL);
8889
return (-1);
8890
}
8891
if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8892
NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8893
/*
8894
* Create the member type link.
8895
*/
8896
link = (xmlSchemaTypeLinkPtr)
8897
xmlMalloc(sizeof(xmlSchemaTypeLink));
8898
if (link == NULL) {
8899
xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8900
"allocating a type link", NULL);
8901
FREE_AND_NULL(tmp)
8902
return (-1);
8903
}
8904
link->type = NULL;
8905
link->next = NULL;
8906
if (lastLink == NULL)
8907
type->memberTypes = link;
8908
else
8909
lastLink->next = link;
8910
lastLink = link;
8911
/*
8912
* Create a reference item.
8913
*/
8914
ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8915
localName, nsName);
8916
if (ref == NULL) {
8917
FREE_AND_NULL(tmp)
8918
return (-1);
8919
}
8920
/*
8921
* Assign the reference to the link, it will be resolved
8922
* later during fixup of the union simple type.
8923
*/
8924
link->type = (xmlSchemaTypePtr) ref;
8925
}
8926
FREE_AND_NULL(tmp)
8927
cur = end;
8928
} while (*cur != 0);
8929
8930
}
8931
/*
8932
* And now for the children...
8933
*/
8934
child = node->children;
8935
if (IS_SCHEMA(child, "annotation")) {
8936
/*
8937
* Add the annotation to the simple type ancestor.
8938
*/
8939
xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8940
xmlSchemaParseAnnotation(ctxt, child, 1));
8941
child = child->next;
8942
}
8943
if (IS_SCHEMA(child, "simpleType")) {
8944
xmlSchemaTypePtr subtype, last = NULL;
8945
8946
/*
8947
* Anchor the member types in the "subtypes" field of the
8948
* simple type.
8949
*/
8950
while (IS_SCHEMA(child, "simpleType")) {
8951
subtype = (xmlSchemaTypePtr)
8952
xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8953
if (subtype != NULL) {
8954
if (last == NULL) {
8955
type->subtypes = subtype;
8956
last = subtype;
8957
} else {
8958
last->next = subtype;
8959
last = subtype;
8960
}
8961
last->next = NULL;
8962
}
8963
child = child->next;
8964
}
8965
}
8966
if (child != NULL) {
8967
xmlSchemaPContentErr(ctxt,
8968
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8969
NULL, node, child, NULL, "(annotation?, simpleType*)");
8970
}
8971
if ((attr == NULL) && (type->subtypes == NULL)) {
8972
/*
8973
* src-union-memberTypes-or-simpleTypes
8974
* Either the memberTypes [attribute] of the <union> element must
8975
* be non-empty or there must be at least one simpleType [child].
8976
*/
8977
xmlSchemaPCustomErr(ctxt,
8978
XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8979
NULL, node,
8980
"Either the attribute 'memberTypes' or "
8981
"at least one <simpleType> child must be present", NULL);
8982
}
8983
return (0);
8984
}
8985
8986
/**
8987
* xmlSchemaParseList:
8988
* @ctxt: a schema validation context
8989
* @schema: the schema being built
8990
* @node: a subtree containing XML Schema information
8991
*
8992
* parse a XML schema List definition
8993
* *WARNING* this interface is highly subject to change
8994
*
8995
* Returns -1 in case of error, 0 if the declaration is improper and
8996
* 1 in case of success.
8997
*/
8998
static xmlSchemaTypePtr
8999
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9000
xmlNodePtr node)
9001
{
9002
xmlSchemaTypePtr type;
9003
xmlNodePtr child = NULL;
9004
xmlAttrPtr attr;
9005
9006
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9007
return (NULL);
9008
/* Not a component, don't create it. */
9009
type = ctxt->ctxtType;
9010
/*
9011
* Mark the type as being of variety "list".
9012
*/
9013
type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9014
/*
9015
* SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9016
* then the `simple ur-type definition`."
9017
*/
9018
type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9019
/*
9020
* Check for illegal attributes.
9021
*/
9022
attr = node->properties;
9023
while (attr != NULL) {
9024
if (attr->ns == NULL) {
9025
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9026
(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9027
xmlSchemaPIllegalAttrErr(ctxt,
9028
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9029
}
9030
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9031
xmlSchemaPIllegalAttrErr(ctxt,
9032
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9033
}
9034
attr = attr->next;
9035
}
9036
9037
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9038
9039
/*
9040
* Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9041
* fields for holding the reference to the itemType.
9042
*
9043
* REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9044
* the "ref" fields.
9045
*/
9046
xmlSchemaPValAttrQName(ctxt, schema, NULL,
9047
node, "itemType", &(type->baseNs), &(type->base));
9048
/*
9049
* And now for the children...
9050
*/
9051
child = node->children;
9052
if (IS_SCHEMA(child, "annotation")) {
9053
xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9054
xmlSchemaParseAnnotation(ctxt, child, 1));
9055
child = child->next;
9056
}
9057
if (IS_SCHEMA(child, "simpleType")) {
9058
/*
9059
* src-list-itemType-or-simpleType
9060
* Either the itemType [attribute] or the <simpleType> [child] of
9061
* the <list> element must be present, but not both.
9062
*/
9063
if (type->base != NULL) {
9064
xmlSchemaPCustomErr(ctxt,
9065
XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9066
NULL, node,
9067
"The attribute 'itemType' and the <simpleType> child "
9068
"are mutually exclusive", NULL);
9069
} else {
9070
type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9071
}
9072
child = child->next;
9073
} else if (type->base == NULL) {
9074
xmlSchemaPCustomErr(ctxt,
9075
XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9076
NULL, node,
9077
"Either the attribute 'itemType' or the <simpleType> child "
9078
"must be present", NULL);
9079
}
9080
if (child != NULL) {
9081
xmlSchemaPContentErr(ctxt,
9082
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9083
NULL, node, child, NULL, "(annotation?, simpleType?)");
9084
}
9085
if ((type->base == NULL) &&
9086
(type->subtypes == NULL) &&
9087
(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9088
xmlSchemaPCustomErr(ctxt,
9089
XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9090
NULL, node,
9091
"Either the attribute 'itemType' or the <simpleType> child "
9092
"must be present", NULL);
9093
}
9094
return (NULL);
9095
}
9096
9097
/**
9098
* xmlSchemaParseSimpleType:
9099
* @ctxt: a schema validation context
9100
* @schema: the schema being built
9101
* @node: a subtree containing XML Schema information
9102
*
9103
* parse a XML schema Simple Type definition
9104
* *WARNING* this interface is highly subject to change
9105
*
9106
* Returns -1 in case of error, 0 if the declaration is improper and
9107
* 1 in case of success.
9108
*/
9109
static xmlSchemaTypePtr
9110
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9111
xmlNodePtr node, int topLevel)
9112
{
9113
xmlSchemaTypePtr type, oldCtxtType;
9114
xmlNodePtr child = NULL;
9115
const xmlChar *attrValue = NULL;
9116
xmlAttrPtr attr;
9117
int hasRestriction = 0;
9118
9119
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9120
return (NULL);
9121
9122
if (topLevel) {
9123
attr = xmlSchemaGetPropNode(node, "name");
9124
if (attr == NULL) {
9125
xmlSchemaPMissingAttrErr(ctxt,
9126
XML_SCHEMAP_S4S_ATTR_MISSING,
9127
NULL, node,
9128
"name", NULL);
9129
return (NULL);
9130
} else {
9131
if (xmlSchemaPValAttrNode(ctxt,
9132
NULL, attr,
9133
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9134
return (NULL);
9135
/*
9136
* Skip built-in types.
9137
*/
9138
if (ctxt->isS4S) {
9139
xmlSchemaTypePtr biType;
9140
9141
if (ctxt->isRedefine) {
9142
/*
9143
* REDEFINE: Disallow redefinition of built-in-types.
9144
* TODO: It seems that the spec does not say anything
9145
* about this case.
9146
*/
9147
xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9148
NULL, node,
9149
"Redefinition of built-in simple types is not "
9150
"supported", NULL);
9151
return(NULL);
9152
}
9153
biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9154
if (biType != NULL)
9155
return (biType);
9156
}
9157
}
9158
}
9159
/*
9160
* TargetNamespace:
9161
* SPEC "The `actual value` of the targetNamespace [attribute]
9162
* of the <schema> ancestor element information item if present,
9163
* otherwise `absent`.
9164
*/
9165
if (topLevel == 0) {
9166
#ifdef ENABLE_NAMED_LOCALS
9167
char buf[40];
9168
#endif
9169
/*
9170
* Parse as local simple type definition.
9171
*/
9172
#ifdef ENABLE_NAMED_LOCALS
9173
snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9174
type = xmlSchemaAddType(ctxt, schema,
9175
XML_SCHEMA_TYPE_SIMPLE,
9176
xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9177
ctxt->targetNamespace, node, 0);
9178
#else
9179
type = xmlSchemaAddType(ctxt, schema,
9180
XML_SCHEMA_TYPE_SIMPLE,
9181
NULL, ctxt->targetNamespace, node, 0);
9182
#endif
9183
if (type == NULL)
9184
return (NULL);
9185
type->type = XML_SCHEMA_TYPE_SIMPLE;
9186
type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9187
/*
9188
* Check for illegal attributes.
9189
*/
9190
attr = node->properties;
9191
while (attr != NULL) {
9192
if (attr->ns == NULL) {
9193
if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9194
xmlSchemaPIllegalAttrErr(ctxt,
9195
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9196
}
9197
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9198
xmlSchemaPIllegalAttrErr(ctxt,
9199
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9200
}
9201
attr = attr->next;
9202
}
9203
} else {
9204
/*
9205
* Parse as global simple type definition.
9206
*
9207
* Note that attrValue is the value of the attribute "name" here.
9208
*/
9209
type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9210
attrValue, ctxt->targetNamespace, node, 1);
9211
if (type == NULL)
9212
return (NULL);
9213
type->type = XML_SCHEMA_TYPE_SIMPLE;
9214
type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9215
type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9216
/*
9217
* Check for illegal attributes.
9218
*/
9219
attr = node->properties;
9220
while (attr != NULL) {
9221
if (attr->ns == NULL) {
9222
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9223
(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9224
(!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9225
xmlSchemaPIllegalAttrErr(ctxt,
9226
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9227
}
9228
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9229
xmlSchemaPIllegalAttrErr(ctxt,
9230
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9231
}
9232
attr = attr->next;
9233
}
9234
/*
9235
* Attribute "final".
9236
*/
9237
attr = xmlSchemaGetPropNode(node, "final");
9238
if (attr == NULL) {
9239
if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9240
type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9241
if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9242
type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9243
if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9244
type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9245
} else {
9246
attrValue = xmlSchemaGetProp(ctxt, node, "final");
9247
if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9248
-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9249
XML_SCHEMAS_TYPE_FINAL_LIST,
9250
XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9251
9252
xmlSchemaPSimpleTypeErr(ctxt,
9253
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9254
WXS_BASIC_CAST type, (xmlNodePtr) attr,
9255
NULL, "(#all | List of (list | union | restriction)",
9256
attrValue, NULL, NULL, NULL);
9257
}
9258
}
9259
}
9260
type->targetNamespace = ctxt->targetNamespace;
9261
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9262
/*
9263
* And now for the children...
9264
*/
9265
oldCtxtType = ctxt->ctxtType;
9266
9267
ctxt->ctxtType = type;
9268
9269
child = node->children;
9270
if (IS_SCHEMA(child, "annotation")) {
9271
type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9272
child = child->next;
9273
}
9274
if (child == NULL) {
9275
xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9276
NULL, node, child, NULL,
9277
"(annotation?, (restriction | list | union))");
9278
} else if (IS_SCHEMA(child, "restriction")) {
9279
xmlSchemaParseRestriction(ctxt, schema, child,
9280
XML_SCHEMA_TYPE_SIMPLE);
9281
hasRestriction = 1;
9282
child = child->next;
9283
} else if (IS_SCHEMA(child, "list")) {
9284
xmlSchemaParseList(ctxt, schema, child);
9285
child = child->next;
9286
} else if (IS_SCHEMA(child, "union")) {
9287
xmlSchemaParseUnion(ctxt, schema, child);
9288
child = child->next;
9289
}
9290
if (child != NULL) {
9291
xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9292
NULL, node, child, NULL,
9293
"(annotation?, (restriction | list | union))");
9294
}
9295
/*
9296
* REDEFINE: SPEC src-redefine (5)
9297
* "Within the [children], each <simpleType> must have a
9298
* <restriction> among its [children] ... the `actual value` of whose
9299
* base [attribute] must be the same as the `actual value` of its own
9300
* name attribute plus target namespace;"
9301
*/
9302
if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9303
xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9304
NULL, node, "This is a redefinition, thus the "
9305
"<simpleType> must have a <restriction> child", NULL);
9306
}
9307
9308
ctxt->ctxtType = oldCtxtType;
9309
return (type);
9310
}
9311
9312
/**
9313
* xmlSchemaParseModelGroupDefRef:
9314
* @ctxt: the parser context
9315
* @schema: the schema being built
9316
* @node: the node
9317
*
9318
* Parses a reference to a model group definition.
9319
*
9320
* We will return a particle component with a qname-component or
9321
* NULL in case of an error.
9322
*/
9323
static xmlSchemaTreeItemPtr
9324
xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9325
xmlSchemaPtr schema,
9326
xmlNodePtr node)
9327
{
9328
xmlSchemaParticlePtr item;
9329
xmlNodePtr child = NULL;
9330
xmlAttrPtr attr;
9331
const xmlChar *ref = NULL, *refNs = NULL;
9332
int min, max;
9333
9334
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9335
return (NULL);
9336
9337
attr = xmlSchemaGetPropNode(node, "ref");
9338
if (attr == NULL) {
9339
xmlSchemaPMissingAttrErr(ctxt,
9340
XML_SCHEMAP_S4S_ATTR_MISSING,
9341
NULL, node, "ref", NULL);
9342
return (NULL);
9343
} else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9344
attr, &refNs, &ref) != 0) {
9345
return (NULL);
9346
}
9347
xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9348
min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9349
max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9350
"(xs:nonNegativeInteger | unbounded)");
9351
/*
9352
* Check for illegal attributes.
9353
*/
9354
attr = node->properties;
9355
while (attr != NULL) {
9356
if (attr->ns == NULL) {
9357
if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9358
(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9359
(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9360
(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9361
xmlSchemaPIllegalAttrErr(ctxt,
9362
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9363
}
9364
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9365
xmlSchemaPIllegalAttrErr(ctxt,
9366
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9367
}
9368
attr = attr->next;
9369
}
9370
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9371
item = xmlSchemaAddParticle(ctxt, node, min, max);
9372
if (item == NULL)
9373
return (NULL);
9374
/*
9375
* Create a qname-reference and set as the term; it will be substituted
9376
* for the model group after the reference has been resolved.
9377
*/
9378
item->children = (xmlSchemaTreeItemPtr)
9379
xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9380
xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9381
/*
9382
* And now for the children...
9383
*/
9384
child = node->children;
9385
/* TODO: Is annotation even allowed for a model group reference? */
9386
if (IS_SCHEMA(child, "annotation")) {
9387
/*
9388
* TODO: What to do exactly with the annotation?
9389
*/
9390
item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9391
child = child->next;
9392
}
9393
if (child != NULL) {
9394
xmlSchemaPContentErr(ctxt,
9395
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9396
NULL, node, child, NULL,
9397
"(annotation?)");
9398
}
9399
/*
9400
* Corresponds to no component at all if minOccurs==maxOccurs==0.
9401
*/
9402
if ((min == 0) && (max == 0))
9403
return (NULL);
9404
9405
return ((xmlSchemaTreeItemPtr) item);
9406
}
9407
9408
/**
9409
* xmlSchemaParseModelGroupDefinition:
9410
* @ctxt: a schema validation context
9411
* @schema: the schema being built
9412
* @node: a subtree containing XML Schema information
9413
*
9414
* Parses a XML schema model group definition.
9415
*
9416
* Note that the constraint src-redefine (6.2) can't be applied until
9417
* references have been resolved. So we will do this at the
9418
* component fixup level.
9419
*
9420
* *WARNING* this interface is highly subject to change
9421
*
9422
* Returns -1 in case of error, 0 if the declaration is improper and
9423
* 1 in case of success.
9424
*/
9425
static xmlSchemaModelGroupDefPtr
9426
xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9427
xmlSchemaPtr schema,
9428
xmlNodePtr node)
9429
{
9430
xmlSchemaModelGroupDefPtr item;
9431
xmlNodePtr child = NULL;
9432
xmlAttrPtr attr;
9433
const xmlChar *name;
9434
9435
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9436
return (NULL);
9437
9438
attr = xmlSchemaGetPropNode(node, "name");
9439
if (attr == NULL) {
9440
xmlSchemaPMissingAttrErr(ctxt,
9441
XML_SCHEMAP_S4S_ATTR_MISSING,
9442
NULL, node,
9443
"name", NULL);
9444
return (NULL);
9445
} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9446
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9447
return (NULL);
9448
}
9449
item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9450
ctxt->targetNamespace, node);
9451
if (item == NULL)
9452
return (NULL);
9453
/*
9454
* Check for illegal attributes.
9455
*/
9456
attr = node->properties;
9457
while (attr != NULL) {
9458
if (attr->ns == NULL) {
9459
if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9460
(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9461
xmlSchemaPIllegalAttrErr(ctxt,
9462
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9463
}
9464
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9465
xmlSchemaPIllegalAttrErr(ctxt,
9466
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9467
}
9468
attr = attr->next;
9469
}
9470
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9471
/*
9472
* And now for the children...
9473
*/
9474
child = node->children;
9475
if (IS_SCHEMA(child, "annotation")) {
9476
item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9477
child = child->next;
9478
}
9479
if (IS_SCHEMA(child, "all")) {
9480
item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9481
XML_SCHEMA_TYPE_ALL, 0);
9482
child = child->next;
9483
} else if (IS_SCHEMA(child, "choice")) {
9484
item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9485
XML_SCHEMA_TYPE_CHOICE, 0);
9486
child = child->next;
9487
} else if (IS_SCHEMA(child, "sequence")) {
9488
item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9489
XML_SCHEMA_TYPE_SEQUENCE, 0);
9490
child = child->next;
9491
}
9492
9493
9494
9495
if (child != NULL) {
9496
xmlSchemaPContentErr(ctxt,
9497
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9498
NULL, node, child, NULL,
9499
"(annotation?, (all | choice | sequence)?)");
9500
}
9501
return (item);
9502
}
9503
9504
/**
9505
* xmlSchemaCleanupDoc:
9506
* @ctxt: a schema validation context
9507
* @node: the root of the document.
9508
*
9509
* removes unwanted nodes in a schemas document tree
9510
*/
9511
static void
9512
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9513
{
9514
xmlNodePtr delete, cur;
9515
9516
if ((ctxt == NULL) || (root == NULL)) return;
9517
9518
/*
9519
* Remove all the blank text nodes
9520
*/
9521
delete = NULL;
9522
cur = root;
9523
while (cur != NULL) {
9524
if (delete != NULL) {
9525
xmlUnlinkNode(delete);
9526
xmlFreeNode(delete);
9527
delete = NULL;
9528
}
9529
if (cur->type == XML_TEXT_NODE) {
9530
if (IS_BLANK_NODE(cur)) {
9531
if (xmlNodeGetSpacePreserve(cur) != 1) {
9532
delete = cur;
9533
}
9534
}
9535
} else if ((cur->type != XML_ELEMENT_NODE) &&
9536
(cur->type != XML_CDATA_SECTION_NODE)) {
9537
delete = cur;
9538
goto skip_children;
9539
}
9540
9541
/*
9542
* Skip to next node
9543
*/
9544
if (cur->children != NULL) {
9545
if ((cur->children->type != XML_ENTITY_DECL) &&
9546
(cur->children->type != XML_ENTITY_REF_NODE) &&
9547
(cur->children->type != XML_ENTITY_NODE)) {
9548
cur = cur->children;
9549
continue;
9550
}
9551
}
9552
skip_children:
9553
if (cur->next != NULL) {
9554
cur = cur->next;
9555
continue;
9556
}
9557
9558
do {
9559
cur = cur->parent;
9560
if (cur == NULL)
9561
break;
9562
if (cur == root) {
9563
cur = NULL;
9564
break;
9565
}
9566
if (cur->next != NULL) {
9567
cur = cur->next;
9568
break;
9569
}
9570
} while (cur != NULL);
9571
}
9572
if (delete != NULL) {
9573
xmlUnlinkNode(delete);
9574
xmlFreeNode(delete);
9575
delete = NULL;
9576
}
9577
}
9578
9579
9580
static void
9581
xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9582
{
9583
if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9584
schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9585
9586
if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9587
schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9588
9589
if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9590
schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9591
if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9592
schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9593
if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9594
schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9595
if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9596
schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9597
9598
if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9599
schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9600
if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9601
schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9602
if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9603
schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9604
}
9605
9606
static int
9607
xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9608
xmlSchemaPtr schema,
9609
xmlNodePtr node)
9610
{
9611
xmlAttrPtr attr;
9612
const xmlChar *val;
9613
int res = 0, oldErrs = ctxt->nberrors;
9614
9615
/*
9616
* Those flags should be moved to the parser context flags,
9617
* since they are not visible at the component level. I.e.
9618
* they are used if processing schema *documents* only.
9619
*/
9620
res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9621
HFAILURE;
9622
9623
/*
9624
* Since the version is of type xs:token, we won't bother to
9625
* check it.
9626
*/
9627
/* REMOVED:
9628
attr = xmlSchemaGetPropNode(node, "version");
9629
if (attr != NULL) {
9630
res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9631
xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9632
HFAILURE;
9633
}
9634
*/
9635
attr = xmlSchemaGetPropNode(node, "targetNamespace");
9636
if (attr != NULL) {
9637
res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9638
xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9639
HFAILURE;
9640
if (res != 0) {
9641
ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9642
goto exit;
9643
}
9644
}
9645
attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9646
if (attr != NULL) {
9647
val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9648
res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9649
XML_SCHEMAS_QUALIF_ELEM);
9650
HFAILURE;
9651
if (res != 0) {
9652
xmlSchemaPSimpleTypeErr(ctxt,
9653
XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9654
NULL, (xmlNodePtr) attr, NULL,
9655
"(qualified | unqualified)", val, NULL, NULL, NULL);
9656
}
9657
}
9658
attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9659
if (attr != NULL) {
9660
val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9661
res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9662
XML_SCHEMAS_QUALIF_ATTR);
9663
HFAILURE;
9664
if (res != 0) {
9665
xmlSchemaPSimpleTypeErr(ctxt,
9666
XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9667
NULL, (xmlNodePtr) attr, NULL,
9668
"(qualified | unqualified)", val, NULL, NULL, NULL);
9669
}
9670
}
9671
attr = xmlSchemaGetPropNode(node, "finalDefault");
9672
if (attr != NULL) {
9673
val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9674
res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9675
XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9676
XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9677
-1,
9678
XML_SCHEMAS_FINAL_DEFAULT_LIST,
9679
XML_SCHEMAS_FINAL_DEFAULT_UNION);
9680
HFAILURE;
9681
if (res != 0) {
9682
xmlSchemaPSimpleTypeErr(ctxt,
9683
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9684
NULL, (xmlNodePtr) attr, NULL,
9685
"(#all | List of (extension | restriction | list | union))",
9686
val, NULL, NULL, NULL);
9687
}
9688
}
9689
attr = xmlSchemaGetPropNode(node, "blockDefault");
9690
if (attr != NULL) {
9691
val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9692
res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9693
XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9694
XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9695
XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9696
HFAILURE;
9697
if (res != 0) {
9698
xmlSchemaPSimpleTypeErr(ctxt,
9699
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9700
NULL, (xmlNodePtr) attr, NULL,
9701
"(#all | List of (extension | restriction | substitution))",
9702
val, NULL, NULL, NULL);
9703
}
9704
}
9705
9706
exit:
9707
if (oldErrs != ctxt->nberrors)
9708
res = ctxt->err;
9709
return(res);
9710
exit_failure:
9711
return(-1);
9712
}
9713
9714
/**
9715
* xmlSchemaParseSchemaTopLevel:
9716
* @ctxt: a schema validation context
9717
* @schema: the schemas
9718
* @nodes: the list of top level nodes
9719
*
9720
* Returns the internal XML Schema structure built from the resource or
9721
* NULL in case of error
9722
*/
9723
static int
9724
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9725
xmlSchemaPtr schema, xmlNodePtr nodes)
9726
{
9727
xmlNodePtr child;
9728
xmlSchemaAnnotPtr annot;
9729
int res = 0, oldErrs, tmpOldErrs;
9730
9731
if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9732
return(-1);
9733
9734
oldErrs = ctxt->nberrors;
9735
child = nodes;
9736
while ((IS_SCHEMA(child, "include")) ||
9737
(IS_SCHEMA(child, "import")) ||
9738
(IS_SCHEMA(child, "redefine")) ||
9739
(IS_SCHEMA(child, "annotation"))) {
9740
if (IS_SCHEMA(child, "annotation")) {
9741
annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9742
if (schema->annot == NULL)
9743
schema->annot = annot;
9744
else
9745
xmlSchemaFreeAnnot(annot);
9746
} else if (IS_SCHEMA(child, "import")) {
9747
tmpOldErrs = ctxt->nberrors;
9748
res = xmlSchemaParseImport(ctxt, schema, child);
9749
HFAILURE;
9750
HSTOP(ctxt);
9751
if (tmpOldErrs != ctxt->nberrors)
9752
goto exit;
9753
} else if (IS_SCHEMA(child, "include")) {
9754
tmpOldErrs = ctxt->nberrors;
9755
res = xmlSchemaParseInclude(ctxt, schema, child);
9756
HFAILURE;
9757
HSTOP(ctxt);
9758
if (tmpOldErrs != ctxt->nberrors)
9759
goto exit;
9760
} else if (IS_SCHEMA(child, "redefine")) {
9761
tmpOldErrs = ctxt->nberrors;
9762
res = xmlSchemaParseRedefine(ctxt, schema, child);
9763
HFAILURE;
9764
HSTOP(ctxt);
9765
if (tmpOldErrs != ctxt->nberrors)
9766
goto exit;
9767
}
9768
child = child->next;
9769
}
9770
/*
9771
* URGENT TODO: Change the functions to return int results.
9772
* We need especially to catch internal errors.
9773
*/
9774
while (child != NULL) {
9775
if (IS_SCHEMA(child, "complexType")) {
9776
xmlSchemaParseComplexType(ctxt, schema, child, 1);
9777
child = child->next;
9778
} else if (IS_SCHEMA(child, "simpleType")) {
9779
xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9780
child = child->next;
9781
} else if (IS_SCHEMA(child, "element")) {
9782
xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9783
child = child->next;
9784
} else if (IS_SCHEMA(child, "attribute")) {
9785
xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9786
child = child->next;
9787
} else if (IS_SCHEMA(child, "attributeGroup")) {
9788
xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9789
child = child->next;
9790
} else if (IS_SCHEMA(child, "group")) {
9791
xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9792
child = child->next;
9793
} else if (IS_SCHEMA(child, "notation")) {
9794
xmlSchemaParseNotation(ctxt, schema, child);
9795
child = child->next;
9796
} else {
9797
xmlSchemaPContentErr(ctxt,
9798
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9799
NULL, child->parent, child,
9800
NULL, "((include | import | redefine | annotation)*, "
9801
"(((simpleType | complexType | group | attributeGroup) "
9802
"| element | attribute | notation), annotation*)*)");
9803
child = child->next;
9804
}
9805
while (IS_SCHEMA(child, "annotation")) {
9806
/*
9807
* TODO: We should add all annotations.
9808
*/
9809
annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9810
if (schema->annot == NULL)
9811
schema->annot = annot;
9812
else
9813
xmlSchemaFreeAnnot(annot);
9814
child = child->next;
9815
}
9816
}
9817
exit:
9818
ctxt->ctxtType = NULL;
9819
if (oldErrs != ctxt->nberrors)
9820
res = ctxt->err;
9821
return(res);
9822
exit_failure:
9823
return(-1);
9824
}
9825
9826
static xmlSchemaSchemaRelationPtr
9827
xmlSchemaSchemaRelationCreate(void)
9828
{
9829
xmlSchemaSchemaRelationPtr ret;
9830
9831
ret = (xmlSchemaSchemaRelationPtr)
9832
xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9833
if (ret == NULL) {
9834
xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9835
return(NULL);
9836
}
9837
memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9838
return(ret);
9839
}
9840
9841
#if 0
9842
static void
9843
xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9844
{
9845
xmlFree(rel);
9846
}
9847
#endif
9848
9849
static void
9850
xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9851
{
9852
xmlSchemaRedefPtr prev;
9853
9854
while (redef != NULL) {
9855
prev = redef;
9856
redef = redef->next;
9857
xmlFree(prev);
9858
}
9859
}
9860
9861
static void
9862
xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9863
{
9864
/*
9865
* After the construction context has been freed, there will be
9866
* no schema graph available any more. Only the schema buckets
9867
* will stay alive, which are put into the "schemasImports" and
9868
* "includes" slots of the xmlSchema.
9869
*/
9870
if (con->buckets != NULL)
9871
xmlSchemaItemListFree(con->buckets);
9872
if (con->pending != NULL)
9873
xmlSchemaItemListFree(con->pending);
9874
if (con->substGroups != NULL)
9875
xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
9876
if (con->redefs != NULL)
9877
xmlSchemaRedefListFree(con->redefs);
9878
if (con->dict != NULL)
9879
xmlDictFree(con->dict);
9880
xmlFree(con);
9881
}
9882
9883
static xmlSchemaConstructionCtxtPtr
9884
xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9885
{
9886
xmlSchemaConstructionCtxtPtr ret;
9887
9888
ret = (xmlSchemaConstructionCtxtPtr)
9889
xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9890
if (ret == NULL) {
9891
xmlSchemaPErrMemory(NULL,
9892
"allocating schema construction context", NULL);
9893
return (NULL);
9894
}
9895
memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9896
9897
ret->buckets = xmlSchemaItemListCreate();
9898
if (ret->buckets == NULL) {
9899
xmlSchemaPErrMemory(NULL,
9900
"allocating list of schema buckets", NULL);
9901
xmlFree(ret);
9902
return (NULL);
9903
}
9904
ret->pending = xmlSchemaItemListCreate();
9905
if (ret->pending == NULL) {
9906
xmlSchemaPErrMemory(NULL,
9907
"allocating list of pending global components", NULL);
9908
xmlSchemaConstructionCtxtFree(ret);
9909
return (NULL);
9910
}
9911
ret->dict = dict;
9912
xmlDictReference(dict);
9913
return(ret);
9914
}
9915
9916
static xmlSchemaParserCtxtPtr
9917
xmlSchemaParserCtxtCreate(void)
9918
{
9919
xmlSchemaParserCtxtPtr ret;
9920
9921
ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9922
if (ret == NULL) {
9923
xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9924
NULL);
9925
return (NULL);
9926
}
9927
memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9928
ret->type = XML_SCHEMA_CTXT_PARSER;
9929
ret->attrProhibs = xmlSchemaItemListCreate();
9930
if (ret->attrProhibs == NULL) {
9931
xmlFree(ret);
9932
return(NULL);
9933
}
9934
return(ret);
9935
}
9936
9937
/**
9938
* xmlSchemaNewParserCtxtUseDict:
9939
* @URL: the location of the schema
9940
* @dict: the dictionary to be used
9941
*
9942
* Create an XML Schemas parse context for that file/resource expected
9943
* to contain an XML Schemas file.
9944
*
9945
* Returns the parser context or NULL in case of error
9946
*/
9947
static xmlSchemaParserCtxtPtr
9948
xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9949
{
9950
xmlSchemaParserCtxtPtr ret;
9951
9952
ret = xmlSchemaParserCtxtCreate();
9953
if (ret == NULL)
9954
return (NULL);
9955
ret->dict = dict;
9956
xmlDictReference(dict);
9957
if (URL != NULL)
9958
ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9959
return (ret);
9960
}
9961
9962
static int
9963
xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9964
{
9965
if (vctxt->pctxt == NULL) {
9966
if (vctxt->schema != NULL)
9967
vctxt->pctxt =
9968
xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9969
else
9970
vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9971
if (vctxt->pctxt == NULL) {
9972
VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9973
"failed to create a temp. parser context");
9974
return (-1);
9975
}
9976
/* TODO: Pass user data. */
9977
xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9978
vctxt->warning, vctxt->errCtxt);
9979
xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9980
vctxt->errCtxt);
9981
}
9982
return (0);
9983
}
9984
9985
/**
9986
* xmlSchemaGetSchemaBucket:
9987
* @pctxt: the schema parser context
9988
* @schemaLocation: the URI of the schema document
9989
*
9990
* Returns a schema bucket if it was already parsed.
9991
*
9992
* Returns a schema bucket if it was already parsed from
9993
* @schemaLocation, NULL otherwise.
9994
*/
9995
static xmlSchemaBucketPtr
9996
xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9997
const xmlChar *schemaLocation)
9998
{
9999
xmlSchemaBucketPtr cur;
10000
xmlSchemaItemListPtr list;
10001
10002
list = pctxt->constructor->buckets;
10003
if (list->nbItems == 0)
10004
return(NULL);
10005
else {
10006
int i;
10007
for (i = 0; i < list->nbItems; i++) {
10008
cur = (xmlSchemaBucketPtr) list->items[i];
10009
/* Pointer comparison! */
10010
if (cur->schemaLocation == schemaLocation)
10011
return(cur);
10012
}
10013
}
10014
return(NULL);
10015
}
10016
10017
static xmlSchemaBucketPtr
10018
xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10019
const xmlChar *schemaLocation,
10020
const xmlChar *targetNamespace)
10021
{
10022
xmlSchemaBucketPtr cur;
10023
xmlSchemaItemListPtr list;
10024
10025
list = pctxt->constructor->buckets;
10026
if (list->nbItems == 0)
10027
return(NULL);
10028
else {
10029
int i;
10030
for (i = 0; i < list->nbItems; i++) {
10031
cur = (xmlSchemaBucketPtr) list->items[i];
10032
/* Pointer comparison! */
10033
if ((cur->origTargetNamespace == NULL) &&
10034
(cur->schemaLocation == schemaLocation) &&
10035
(cur->targetNamespace == targetNamespace))
10036
return(cur);
10037
}
10038
}
10039
return(NULL);
10040
}
10041
10042
10043
#define IS_BAD_SCHEMA_DOC(b) \
10044
(((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10045
10046
static xmlSchemaBucketPtr
10047
xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10048
const xmlChar *targetNamespace,
10049
int imported)
10050
{
10051
xmlSchemaBucketPtr cur;
10052
xmlSchemaItemListPtr list;
10053
10054
list = pctxt->constructor->buckets;
10055
if (list->nbItems == 0)
10056
return(NULL);
10057
else {
10058
int i;
10059
for (i = 0; i < list->nbItems; i++) {
10060
cur = (xmlSchemaBucketPtr) list->items[i];
10061
if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10062
(cur->origTargetNamespace == targetNamespace) &&
10063
((imported && cur->imported) ||
10064
((!imported) && (!cur->imported))))
10065
return(cur);
10066
}
10067
}
10068
return(NULL);
10069
}
10070
10071
static int
10072
xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10073
xmlSchemaPtr schema,
10074
xmlSchemaBucketPtr bucket)
10075
{
10076
int oldFlags;
10077
xmlDocPtr oldDoc;
10078
xmlNodePtr node;
10079
int ret, oldErrs;
10080
xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10081
10082
/*
10083
* Save old values; reset the *main* schema.
10084
* URGENT TODO: This is not good; move the per-document information
10085
* to the parser. Get rid of passing the main schema to the
10086
* parsing functions.
10087
*/
10088
oldFlags = schema->flags;
10089
oldDoc = schema->doc;
10090
if (schema->flags != 0)
10091
xmlSchemaClearSchemaDefaults(schema);
10092
schema->doc = bucket->doc;
10093
pctxt->schema = schema;
10094
/*
10095
* Keep the current target namespace on the parser *not* on the
10096
* main schema.
10097
*/
10098
pctxt->targetNamespace = bucket->targetNamespace;
10099
WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10100
10101
if ((bucket->targetNamespace != NULL) &&
10102
xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10103
/*
10104
* We are parsing the schema for schemas!
10105
*/
10106
pctxt->isS4S = 1;
10107
}
10108
/* Mark it as parsed, even if parsing fails. */
10109
bucket->parsed++;
10110
/* Compile the schema doc. */
10111
node = xmlDocGetRootElement(bucket->doc);
10112
ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10113
if (ret != 0)
10114
goto exit;
10115
/* An empty schema; just get out. */
10116
if (node->children == NULL)
10117
goto exit;
10118
oldErrs = pctxt->nberrors;
10119
ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10120
if (ret != 0)
10121
goto exit;
10122
/*
10123
* TODO: Not nice, but I'm not 100% sure we will get always an error
10124
* as a result of the above functions; so better rely on pctxt->err
10125
* as well.
10126
*/
10127
if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10128
ret = pctxt->err;
10129
goto exit;
10130
}
10131
10132
exit:
10133
WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10134
/* Restore schema values. */
10135
schema->doc = oldDoc;
10136
schema->flags = oldFlags;
10137
return(ret);
10138
}
10139
10140
static int
10141
xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10142
xmlSchemaPtr schema,
10143
xmlSchemaBucketPtr bucket)
10144
{
10145
xmlSchemaParserCtxtPtr newpctxt;
10146
int res = 0;
10147
10148
if (bucket == NULL)
10149
return(0);
10150
if (bucket->parsed) {
10151
PERROR_INT("xmlSchemaParseNewDoc",
10152
"reparsing a schema doc");
10153
return(-1);
10154
}
10155
if (bucket->doc == NULL) {
10156
PERROR_INT("xmlSchemaParseNewDoc",
10157
"parsing a schema doc, but there's no doc");
10158
return(-1);
10159
}
10160
if (pctxt->constructor == NULL) {
10161
PERROR_INT("xmlSchemaParseNewDoc",
10162
"no constructor");
10163
return(-1);
10164
}
10165
/* Create and init the temporary parser context. */
10166
newpctxt = xmlSchemaNewParserCtxtUseDict(
10167
(const char *) bucket->schemaLocation, pctxt->dict);
10168
if (newpctxt == NULL)
10169
return(-1);
10170
newpctxt->constructor = pctxt->constructor;
10171
/*
10172
* TODO: Can we avoid that the parser knows about the main schema?
10173
* It would be better if he knows about the current schema bucket
10174
* only.
10175
*/
10176
newpctxt->schema = schema;
10177
xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10178
pctxt->errCtxt);
10179
xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10180
pctxt->errCtxt);
10181
newpctxt->counter = pctxt->counter;
10182
10183
10184
res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10185
10186
/* Channel back errors and cleanup the temporary parser context. */
10187
if (res != 0)
10188
pctxt->err = res;
10189
pctxt->nberrors += newpctxt->nberrors;
10190
pctxt->counter = newpctxt->counter;
10191
newpctxt->constructor = NULL;
10192
/* Free the parser context. */
10193
xmlSchemaFreeParserCtxt(newpctxt);
10194
return(res);
10195
}
10196
10197
static void
10198
xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10199
xmlSchemaSchemaRelationPtr rel)
10200
{
10201
xmlSchemaSchemaRelationPtr cur = bucket->relations;
10202
10203
if (cur == NULL) {
10204
bucket->relations = rel;
10205
return;
10206
}
10207
while (cur->next != NULL)
10208
cur = cur->next;
10209
cur->next = rel;
10210
}
10211
10212
10213
static const xmlChar *
10214
xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10215
xmlNodePtr ctxtNode)
10216
{
10217
/*
10218
* Build an absolute location URI.
10219
*/
10220
if (location != NULL) {
10221
if (ctxtNode == NULL)
10222
return(location);
10223
else {
10224
xmlChar *base, *URI;
10225
const xmlChar *ret = NULL;
10226
10227
base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10228
if (base == NULL) {
10229
URI = xmlBuildURI(location, ctxtNode->doc->URL);
10230
} else {
10231
URI = xmlBuildURI(location, base);
10232
xmlFree(base);
10233
}
10234
if (URI != NULL) {
10235
ret = xmlDictLookup(dict, URI, -1);
10236
xmlFree(URI);
10237
return(ret);
10238
}
10239
}
10240
}
10241
return(NULL);
10242
}
10243
10244
10245
10246
/**
10247
* xmlSchemaAddSchemaDoc:
10248
* @pctxt: a schema validation context
10249
* @schema: the schema being built
10250
* @node: a subtree containing XML Schema information
10251
*
10252
* Parse an included (and to-be-redefined) XML schema document.
10253
*
10254
* Returns 0 on success, a positive error code on errors and
10255
* -1 in case of an internal or API error.
10256
*/
10257
10258
static int
10259
xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10260
int type, /* import or include or redefine */
10261
const xmlChar *schemaLocation,
10262
xmlDocPtr schemaDoc,
10263
const char *schemaBuffer,
10264
int schemaBufferLen,
10265
xmlNodePtr invokingNode,
10266
const xmlChar *sourceTargetNamespace,
10267
const xmlChar *importNamespace,
10268
xmlSchemaBucketPtr *bucket)
10269
{
10270
const xmlChar *targetNamespace = NULL;
10271
xmlSchemaSchemaRelationPtr relation = NULL;
10272
xmlDocPtr doc = NULL;
10273
int res = 0, err = 0, located = 0, preserveDoc = 0;
10274
xmlSchemaBucketPtr bkt = NULL;
10275
10276
if (bucket != NULL)
10277
*bucket = NULL;
10278
10279
switch (type) {
10280
case XML_SCHEMA_SCHEMA_IMPORT:
10281
case XML_SCHEMA_SCHEMA_MAIN:
10282
err = XML_SCHEMAP_SRC_IMPORT;
10283
break;
10284
case XML_SCHEMA_SCHEMA_INCLUDE:
10285
err = XML_SCHEMAP_SRC_INCLUDE;
10286
break;
10287
case XML_SCHEMA_SCHEMA_REDEFINE:
10288
err = XML_SCHEMAP_SRC_REDEFINE;
10289
break;
10290
}
10291
10292
10293
/* Special handling for the main schema:
10294
* skip the location and relation logic and just parse the doc.
10295
* We need just a bucket to be returned in this case.
10296
*/
10297
if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10298
goto doc_load;
10299
10300
/* Note that we expect the location to be an absolute URI. */
10301
if (schemaLocation != NULL) {
10302
bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10303
if ((bkt != NULL) &&
10304
(pctxt->constructor->bucket == bkt)) {
10305
/* Report self-imports/inclusions/redefinitions. */
10306
10307
xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10308
invokingNode, NULL,
10309
"The schema must not import/include/redefine itself",
10310
NULL, NULL);
10311
goto exit;
10312
}
10313
}
10314
/*
10315
* Create a relation for the graph of schemas.
10316
*/
10317
relation = xmlSchemaSchemaRelationCreate();
10318
if (relation == NULL)
10319
return(-1);
10320
xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10321
relation);
10322
relation->type = type;
10323
10324
/*
10325
* Save the namespace import information.
10326
*/
10327
if (WXS_IS_BUCKET_IMPMAIN(type)) {
10328
relation->importNamespace = importNamespace;
10329
if (schemaLocation == NULL) {
10330
/*
10331
* No location; this is just an import of the namespace.
10332
* Note that we don't assign a bucket to the relation
10333
* in this case.
10334
*/
10335
goto exit;
10336
}
10337
targetNamespace = importNamespace;
10338
}
10339
10340
/* Did we already fetch the doc? */
10341
if (bkt != NULL) {
10342
if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10343
/*
10344
* We included/redefined and then try to import a schema,
10345
* but the new location provided for import was different.
10346
*/
10347
if (schemaLocation == NULL)
10348
schemaLocation = BAD_CAST "in_memory_buffer";
10349
if (!xmlStrEqual(schemaLocation,
10350
bkt->schemaLocation)) {
10351
xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10352
invokingNode, NULL,
10353
"The schema document '%s' cannot be imported, since "
10354
"it was already included or redefined",
10355
schemaLocation, NULL);
10356
goto exit;
10357
}
10358
} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10359
/*
10360
* We imported and then try to include/redefine a schema,
10361
* but the new location provided for the include/redefine
10362
* was different.
10363
*/
10364
if (schemaLocation == NULL)
10365
schemaLocation = BAD_CAST "in_memory_buffer";
10366
if (!xmlStrEqual(schemaLocation,
10367
bkt->schemaLocation)) {
10368
xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10369
invokingNode, NULL,
10370
"The schema document '%s' cannot be included or "
10371
"redefined, since it was already imported",
10372
schemaLocation, NULL);
10373
goto exit;
10374
}
10375
}
10376
}
10377
10378
if (WXS_IS_BUCKET_IMPMAIN(type)) {
10379
/*
10380
* Given that the schemaLocation [attribute] is only a hint, it is open
10381
* to applications to ignore all but the first <import> for a given
10382
* namespace, regardless of the `actual value` of schemaLocation, but
10383
* such a strategy risks missing useful information when new
10384
* schemaLocations are offered.
10385
*
10386
* We will use the first <import> that comes with a location.
10387
* Further <import>s *with* a location, will result in an error.
10388
* TODO: Better would be to just report a warning here, but
10389
* we'll try it this way until someone complains.
10390
*
10391
* Schema Document Location Strategy:
10392
* 3 Based on the namespace name, identify an existing schema document,
10393
* either as a resource which is an XML document or a <schema> element
10394
* information item, in some local schema repository;
10395
* 5 Attempt to resolve the namespace name to locate such a resource.
10396
*
10397
* NOTE: (3) and (5) are not supported.
10398
*/
10399
if (bkt != NULL) {
10400
relation->bucket = bkt;
10401
goto exit;
10402
}
10403
bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10404
importNamespace, 1);
10405
10406
if (bkt != NULL) {
10407
relation->bucket = bkt;
10408
if (bkt->schemaLocation == NULL) {
10409
/* First given location of the schema; load the doc. */
10410
bkt->schemaLocation = schemaLocation;
10411
} else {
10412
if (!xmlStrEqual(schemaLocation,
10413
bkt->schemaLocation)) {
10414
/*
10415
* Additional location given; just skip it.
10416
* URGENT TODO: We should report a warning here.
10417
* res = XML_SCHEMAP_SRC_IMPORT;
10418
*/
10419
if (schemaLocation == NULL)
10420
schemaLocation = BAD_CAST "in_memory_buffer";
10421
10422
xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10423
XML_SCHEMAP_WARN_SKIP_SCHEMA,
10424
invokingNode, NULL,
10425
"Skipping import of schema located at '%s' for the "
10426
"namespace '%s', since this namespace was already "
10427
"imported with the schema located at '%s'",
10428
schemaLocation, importNamespace, bkt->schemaLocation);
10429
}
10430
goto exit;
10431
}
10432
}
10433
/*
10434
* No bucket + first location: load the doc and create a
10435
* bucket.
10436
*/
10437
} else {
10438
/* <include> and <redefine> */
10439
if (bkt != NULL) {
10440
10441
if ((bkt->origTargetNamespace == NULL) &&
10442
(bkt->targetNamespace != sourceTargetNamespace)) {
10443
xmlSchemaBucketPtr chamel;
10444
10445
/*
10446
* Chameleon include/redefine: skip loading only if it was
10447
* already build for the targetNamespace of the including
10448
* schema.
10449
*/
10450
/*
10451
* URGENT TODO: If the schema is a chameleon-include then copy
10452
* the components into the including schema and modify the
10453
* targetNamespace of those components, do nothing otherwise.
10454
* NOTE: This is currently worked-around by compiling the
10455
* chameleon for every distinct including targetNamespace; thus
10456
* not performant at the moment.
10457
* TODO: Check when the namespace in wildcards for chameleons
10458
* needs to be converted: before we built wildcard intersections
10459
* or after.
10460
* Answer: after!
10461
*/
10462
chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10463
schemaLocation, sourceTargetNamespace);
10464
if (chamel != NULL) {
10465
/* A fitting chameleon was already parsed; NOP. */
10466
relation->bucket = chamel;
10467
goto exit;
10468
}
10469
/*
10470
* We need to parse the chameleon again for a different
10471
* targetNamespace.
10472
* CHAMELEON TODO: Optimize this by only parsing the
10473
* chameleon once, and then copying the components to
10474
* the new targetNamespace.
10475
*/
10476
bkt = NULL;
10477
} else {
10478
relation->bucket = bkt;
10479
goto exit;
10480
}
10481
}
10482
}
10483
if ((bkt != NULL) && (bkt->doc != NULL)) {
10484
PERROR_INT("xmlSchemaAddSchemaDoc",
10485
"trying to load a schema doc, but a doc is already "
10486
"assigned to the schema bucket");
10487
goto exit_failure;
10488
}
10489
10490
doc_load:
10491
/*
10492
* Load the document.
10493
*/
10494
if (schemaDoc != NULL) {
10495
doc = schemaDoc;
10496
/* Don' free this one, since it was provided by the caller. */
10497
preserveDoc = 1;
10498
/* TODO: Does the context or the doc hold the location? */
10499
if (schemaDoc->URL != NULL)
10500
schemaLocation = xmlDictLookup(pctxt->dict,
10501
schemaDoc->URL, -1);
10502
else
10503
schemaLocation = BAD_CAST "in_memory_buffer";
10504
} else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10505
xmlParserCtxtPtr parserCtxt;
10506
10507
parserCtxt = xmlNewParserCtxt();
10508
if (parserCtxt == NULL) {
10509
xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10510
"allocating a parser context", NULL);
10511
goto exit_failure;
10512
}
10513
if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10514
/*
10515
* TODO: Do we have to burden the schema parser dict with all
10516
* the content of the schema doc?
10517
*/
10518
xmlDictFree(parserCtxt->dict);
10519
parserCtxt->dict = pctxt->dict;
10520
xmlDictReference(parserCtxt->dict);
10521
}
10522
if (schemaLocation != NULL) {
10523
/* Parse from file. */
10524
doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10525
NULL, SCHEMAS_PARSE_OPTIONS);
10526
} else if (schemaBuffer != NULL) {
10527
/* Parse from memory buffer. */
10528
doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10529
NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10530
schemaLocation = BAD_CAST "in_memory_buffer";
10531
if (doc != NULL)
10532
doc->URL = xmlStrdup(schemaLocation);
10533
}
10534
/*
10535
* For <import>:
10536
* 2.1 The referent is (a fragment of) a resource which is an
10537
* XML document (see clause 1.1), which in turn corresponds to
10538
* a <schema> element information item in a well-formed information
10539
* set, which in turn corresponds to a valid schema.
10540
* TODO: (2.1) fragments of XML documents are not supported.
10541
*
10542
* 2.2 The referent is a <schema> element information item in
10543
* a well-formed information set, which in turn corresponds
10544
* to a valid schema.
10545
* TODO: (2.2) is not supported.
10546
*/
10547
if (doc == NULL) {
10548
const xmlError *lerr;
10549
lerr = xmlGetLastError();
10550
/*
10551
* Check if this a parser error, or if the document could
10552
* just not be located.
10553
* TODO: Try to find specific error codes to react only on
10554
* localisation failures.
10555
*/
10556
if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10557
/*
10558
* We assume a parser error here.
10559
*/
10560
located = 1;
10561
/* TODO: Error code ?? */
10562
res = XML_SCHEMAP_SRC_IMPORT_2_1;
10563
xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10564
invokingNode, NULL,
10565
"Failed to parse the XML resource '%s'",
10566
schemaLocation, NULL);
10567
}
10568
}
10569
xmlFreeParserCtxt(parserCtxt);
10570
if ((doc == NULL) && located)
10571
goto exit_error;
10572
} else {
10573
xmlSchemaPErr(pctxt, NULL,
10574
XML_SCHEMAP_NOTHING_TO_PARSE,
10575
"No information for parsing was provided with the "
10576
"given schema parser context.\n",
10577
NULL, NULL);
10578
goto exit_failure;
10579
}
10580
/*
10581
* Preprocess the document.
10582
*/
10583
if (doc != NULL) {
10584
xmlNodePtr docElem = NULL;
10585
10586
located = 1;
10587
docElem = xmlDocGetRootElement(doc);
10588
if (docElem == NULL) {
10589
xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10590
invokingNode, NULL,
10591
"The document '%s' has no document element",
10592
schemaLocation, NULL);
10593
goto exit_error;
10594
}
10595
/*
10596
* Remove all the blank text nodes.
10597
*/
10598
xmlSchemaCleanupDoc(pctxt, docElem);
10599
/*
10600
* Check the schema's top level element.
10601
*/
10602
if (!IS_SCHEMA(docElem, "schema")) {
10603
xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10604
invokingNode, NULL,
10605
"The XML document '%s' is not a schema document",
10606
schemaLocation, NULL);
10607
goto exit_error;
10608
}
10609
/*
10610
* Note that we don't apply a type check for the
10611
* targetNamespace value here.
10612
*/
10613
targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10614
"targetNamespace");
10615
}
10616
10617
/* after_doc_loading: */
10618
if ((bkt == NULL) && located) {
10619
/* Only create a bucket if the schema was located. */
10620
bkt = xmlSchemaBucketCreate(pctxt, type,
10621
targetNamespace);
10622
if (bkt == NULL)
10623
goto exit_failure;
10624
}
10625
if (bkt != NULL) {
10626
bkt->schemaLocation = schemaLocation;
10627
bkt->located = located;
10628
if (doc != NULL) {
10629
bkt->doc = doc;
10630
bkt->targetNamespace = targetNamespace;
10631
bkt->origTargetNamespace = targetNamespace;
10632
if (preserveDoc)
10633
bkt->preserveDoc = 1;
10634
}
10635
if (WXS_IS_BUCKET_IMPMAIN(type))
10636
bkt->imported++;
10637
/*
10638
* Add it to the graph of schemas.
10639
*/
10640
if (relation != NULL)
10641
relation->bucket = bkt;
10642
}
10643
10644
exit:
10645
/*
10646
* Return the bucket explicitly; this is needed for the
10647
* main schema.
10648
*/
10649
if (bucket != NULL)
10650
*bucket = bkt;
10651
return (0);
10652
10653
exit_error:
10654
if ((doc != NULL) && (! preserveDoc)) {
10655
xmlFreeDoc(doc);
10656
if (bkt != NULL)
10657
bkt->doc = NULL;
10658
}
10659
return(pctxt->err);
10660
10661
exit_failure:
10662
if ((doc != NULL) && (! preserveDoc)) {
10663
xmlFreeDoc(doc);
10664
if (bkt != NULL)
10665
bkt->doc = NULL;
10666
}
10667
return (-1);
10668
}
10669
10670
/**
10671
* xmlSchemaParseImport:
10672
* @ctxt: a schema validation context
10673
* @schema: the schema being built
10674
* @node: a subtree containing XML Schema information
10675
*
10676
* parse a XML schema Import definition
10677
* *WARNING* this interface is highly subject to change
10678
*
10679
* Returns 0 in case of success, a positive error code if
10680
* not valid and -1 in case of an internal error.
10681
*/
10682
static int
10683
xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10684
xmlNodePtr node)
10685
{
10686
xmlNodePtr child;
10687
const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10688
const xmlChar *thisTargetNamespace;
10689
xmlAttrPtr attr;
10690
int ret = 0;
10691
xmlSchemaBucketPtr bucket = NULL;
10692
10693
if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10694
return (-1);
10695
10696
/*
10697
* Check for illegal attributes.
10698
*/
10699
attr = node->properties;
10700
while (attr != NULL) {
10701
if (attr->ns == NULL) {
10702
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10703
(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10704
(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10705
xmlSchemaPIllegalAttrErr(pctxt,
10706
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10707
}
10708
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10709
xmlSchemaPIllegalAttrErr(pctxt,
10710
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10711
}
10712
attr = attr->next;
10713
}
10714
/*
10715
* Extract and validate attributes.
10716
*/
10717
if (xmlSchemaPValAttr(pctxt, NULL, node,
10718
"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10719
&namespaceName) != 0) {
10720
xmlSchemaPSimpleTypeErr(pctxt,
10721
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10722
NULL, node,
10723
xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10724
NULL, namespaceName, NULL, NULL, NULL);
10725
return (pctxt->err);
10726
}
10727
10728
if (xmlSchemaPValAttr(pctxt, NULL, node,
10729
"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10730
&schemaLocation) != 0) {
10731
xmlSchemaPSimpleTypeErr(pctxt,
10732
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10733
NULL, node,
10734
xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10735
NULL, schemaLocation, NULL, NULL, NULL);
10736
return (pctxt->err);
10737
}
10738
/*
10739
* And now for the children...
10740
*/
10741
child = node->children;
10742
if (IS_SCHEMA(child, "annotation")) {
10743
/*
10744
* the annotation here is simply discarded ...
10745
* TODO: really?
10746
*/
10747
child = child->next;
10748
}
10749
if (child != NULL) {
10750
xmlSchemaPContentErr(pctxt,
10751
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10752
NULL, node, child, NULL,
10753
"(annotation?)");
10754
}
10755
/*
10756
* Apply additional constraints.
10757
*
10758
* Note that it is important to use the original @targetNamespace
10759
* (or none at all), to rule out imports of schemas _with_ a
10760
* @targetNamespace if the importing schema is a chameleon schema
10761
* (with no @targetNamespace).
10762
*/
10763
thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10764
if (namespaceName != NULL) {
10765
/*
10766
* 1.1 If the namespace [attribute] is present, then its `actual value`
10767
* must not match the `actual value` of the enclosing <schema>'s
10768
* targetNamespace [attribute].
10769
*/
10770
if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10771
xmlSchemaPCustomErr(pctxt,
10772
XML_SCHEMAP_SRC_IMPORT_1_1,
10773
NULL, node,
10774
"The value of the attribute 'namespace' must not match "
10775
"the target namespace '%s' of the importing schema",
10776
thisTargetNamespace);
10777
return (pctxt->err);
10778
}
10779
} else {
10780
/*
10781
* 1.2 If the namespace [attribute] is not present, then the enclosing
10782
* <schema> must have a targetNamespace [attribute].
10783
*/
10784
if (thisTargetNamespace == NULL) {
10785
xmlSchemaPCustomErr(pctxt,
10786
XML_SCHEMAP_SRC_IMPORT_1_2,
10787
NULL, node,
10788
"The attribute 'namespace' must be existent if "
10789
"the importing schema has no target namespace",
10790
NULL);
10791
return (pctxt->err);
10792
}
10793
}
10794
/*
10795
* Locate and acquire the schema document.
10796
*/
10797
if (schemaLocation != NULL)
10798
schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10799
schemaLocation, node);
10800
ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10801
schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10802
namespaceName, &bucket);
10803
10804
if (ret != 0)
10805
return(ret);
10806
10807
/*
10808
* For <import>: "It is *not* an error for the application
10809
* schema reference strategy to fail."
10810
* So just don't parse if no schema document was found.
10811
* Note that we will get no bucket if the schema could not be
10812
* located or if there was no schemaLocation.
10813
*/
10814
if ((bucket == NULL) && (schemaLocation != NULL)) {
10815
xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10816
XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10817
node, NULL,
10818
"Failed to locate a schema at location '%s'. "
10819
"Skipping the import", schemaLocation, NULL, NULL);
10820
}
10821
10822
if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10823
ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10824
}
10825
10826
return (ret);
10827
}
10828
10829
static int
10830
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10831
xmlSchemaPtr schema,
10832
xmlNodePtr node,
10833
xmlChar **schemaLocation,
10834
int type)
10835
{
10836
xmlAttrPtr attr;
10837
10838
if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10839
(schemaLocation == NULL))
10840
return (-1);
10841
10842
*schemaLocation = NULL;
10843
/*
10844
* Check for illegal attributes.
10845
* Applies for both <include> and <redefine>.
10846
*/
10847
attr = node->properties;
10848
while (attr != NULL) {
10849
if (attr->ns == NULL) {
10850
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10851
(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10852
xmlSchemaPIllegalAttrErr(pctxt,
10853
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10854
}
10855
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10856
xmlSchemaPIllegalAttrErr(pctxt,
10857
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10858
}
10859
attr = attr->next;
10860
}
10861
xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10862
/*
10863
* Preliminary step, extract the URI-Reference and make an URI
10864
* from the base.
10865
*/
10866
/*
10867
* Attribute "schemaLocation" is mandatory.
10868
*/
10869
attr = xmlSchemaGetPropNode(node, "schemaLocation");
10870
if (attr != NULL) {
10871
xmlChar *base = NULL;
10872
xmlChar *uri = NULL;
10873
10874
if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10875
xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10876
(const xmlChar **) schemaLocation) != 0)
10877
goto exit_error;
10878
base = xmlNodeGetBase(node->doc, node);
10879
if (base == NULL) {
10880
uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10881
} else {
10882
uri = xmlBuildURI(*schemaLocation, base);
10883
xmlFree(base);
10884
}
10885
if (uri == NULL) {
10886
PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10887
"could not build an URI from the schemaLocation")
10888
goto exit_failure;
10889
}
10890
(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10891
xmlFree(uri);
10892
} else {
10893
xmlSchemaPMissingAttrErr(pctxt,
10894
XML_SCHEMAP_S4S_ATTR_MISSING,
10895
NULL, node, "schemaLocation", NULL);
10896
goto exit_error;
10897
}
10898
/*
10899
* Report self-inclusion and self-redefinition.
10900
*/
10901
if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10902
if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10903
xmlSchemaPCustomErr(pctxt,
10904
XML_SCHEMAP_SRC_REDEFINE,
10905
NULL, node,
10906
"The schema document '%s' cannot redefine itself.",
10907
*schemaLocation);
10908
} else {
10909
xmlSchemaPCustomErr(pctxt,
10910
XML_SCHEMAP_SRC_INCLUDE,
10911
NULL, node,
10912
"The schema document '%s' cannot include itself.",
10913
*schemaLocation);
10914
}
10915
goto exit_error;
10916
}
10917
10918
return(0);
10919
exit_error:
10920
return(pctxt->err);
10921
exit_failure:
10922
return(-1);
10923
}
10924
10925
static int
10926
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10927
xmlSchemaPtr schema,
10928
xmlNodePtr node,
10929
int type)
10930
{
10931
xmlNodePtr child = NULL;
10932
const xmlChar *schemaLocation = NULL;
10933
int res = 0; /* hasRedefinitions = 0 */
10934
int isChameleon = 0, wasChameleon = 0;
10935
xmlSchemaBucketPtr bucket = NULL;
10936
10937
if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10938
return (-1);
10939
10940
/*
10941
* Parse attributes. Note that the returned schemaLocation will
10942
* be already converted to an absolute URI.
10943
*/
10944
res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10945
node, (xmlChar **) (&schemaLocation), type);
10946
if (res != 0)
10947
return(res);
10948
/*
10949
* Load and add the schema document.
10950
*/
10951
res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10952
NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10953
if (res != 0)
10954
return(res);
10955
/*
10956
* If we get no schema bucket back, then this means that the schema
10957
* document could not be located or was broken XML or was not
10958
* a schema document.
10959
*/
10960
if ((bucket == NULL) || (bucket->doc == NULL)) {
10961
if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10962
/*
10963
* WARNING for <include>:
10964
* We will raise an error if the schema cannot be located
10965
* for inclusions, since the that was the feedback from the
10966
* schema people. I.e. the following spec piece will *not* be
10967
* satisfied:
10968
* SPEC src-include: "It is not an error for the `actual value` of the
10969
* schemaLocation [attribute] to fail to resolve it all, in which
10970
* case no corresponding inclusion is performed.
10971
* So do we need a warning report here?"
10972
*/
10973
res = XML_SCHEMAP_SRC_INCLUDE;
10974
xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10975
node, NULL,
10976
"Failed to load the document '%s' for inclusion",
10977
schemaLocation, NULL);
10978
} else {
10979
/*
10980
* NOTE: This was changed to raise an error even if no redefinitions
10981
* are specified.
10982
*
10983
* SPEC src-redefine (1)
10984
* "If there are any element information items among the [children]
10985
* other than <annotation> then the `actual value` of the
10986
* schemaLocation [attribute] must successfully resolve."
10987
* TODO: Ask the WG if a the location has always to resolve
10988
* here as well!
10989
*/
10990
res = XML_SCHEMAP_SRC_REDEFINE;
10991
xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10992
node, NULL,
10993
"Failed to load the document '%s' for redefinition",
10994
schemaLocation, NULL);
10995
}
10996
} else {
10997
/*
10998
* Check targetNamespace sanity before parsing the new schema.
10999
* TODO: Note that we won't check further content if the
11000
* targetNamespace was bad.
11001
*/
11002
if (bucket->origTargetNamespace != NULL) {
11003
/*
11004
* SPEC src-include (2.1)
11005
* "SII has a targetNamespace [attribute], and its `actual
11006
* value` is identical to the `actual value` of the targetNamespace
11007
* [attribute] of SII' (which must have such an [attribute])."
11008
*/
11009
if (pctxt->targetNamespace == NULL) {
11010
xmlSchemaCustomErr(ACTXT_CAST pctxt,
11011
XML_SCHEMAP_SRC_INCLUDE,
11012
node, NULL,
11013
"The target namespace of the included/redefined schema "
11014
"'%s' has to be absent, since the including/redefining "
11015
"schema has no target namespace",
11016
schemaLocation, NULL);
11017
goto exit_error;
11018
} else if (!xmlStrEqual(bucket->origTargetNamespace,
11019
pctxt->targetNamespace)) {
11020
/* TODO: Change error function. */
11021
xmlSchemaPCustomErrExt(pctxt,
11022
XML_SCHEMAP_SRC_INCLUDE,
11023
NULL, node,
11024
"The target namespace '%s' of the included/redefined "
11025
"schema '%s' differs from '%s' of the "
11026
"including/redefining schema",
11027
bucket->origTargetNamespace, schemaLocation,
11028
pctxt->targetNamespace);
11029
goto exit_error;
11030
}
11031
} else if (pctxt->targetNamespace != NULL) {
11032
/*
11033
* Chameleons: the original target namespace will
11034
* differ from the resulting namespace.
11035
*/
11036
isChameleon = 1;
11037
bucket->targetNamespace = pctxt->targetNamespace;
11038
}
11039
}
11040
/*
11041
* Parse the schema.
11042
*/
11043
if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11044
if (isChameleon) {
11045
/* TODO: Get rid of this flag on the schema itself. */
11046
if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11047
schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11048
} else
11049
wasChameleon = 1;
11050
}
11051
xmlSchemaParseNewDoc(pctxt, schema, bucket);
11052
/* Restore chameleon flag. */
11053
if (isChameleon && (!wasChameleon))
11054
schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11055
}
11056
/*
11057
* And now for the children...
11058
*/
11059
child = node->children;
11060
if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11061
/*
11062
* Parse (simpleType | complexType | group | attributeGroup))*
11063
*/
11064
pctxt->redefined = bucket;
11065
/*
11066
* How to proceed if the redefined schema was not located?
11067
*/
11068
pctxt->isRedefine = 1;
11069
while (IS_SCHEMA(child, "annotation") ||
11070
IS_SCHEMA(child, "simpleType") ||
11071
IS_SCHEMA(child, "complexType") ||
11072
IS_SCHEMA(child, "group") ||
11073
IS_SCHEMA(child, "attributeGroup")) {
11074
if (IS_SCHEMA(child, "annotation")) {
11075
/*
11076
* TODO: discard or not?
11077
*/
11078
} else if (IS_SCHEMA(child, "simpleType")) {
11079
xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11080
} else if (IS_SCHEMA(child, "complexType")) {
11081
xmlSchemaParseComplexType(pctxt, schema, child, 1);
11082
/* hasRedefinitions = 1; */
11083
} else if (IS_SCHEMA(child, "group")) {
11084
/* hasRedefinitions = 1; */
11085
xmlSchemaParseModelGroupDefinition(pctxt,
11086
schema, child);
11087
} else if (IS_SCHEMA(child, "attributeGroup")) {
11088
/* hasRedefinitions = 1; */
11089
xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11090
child);
11091
}
11092
child = child->next;
11093
}
11094
pctxt->redefined = NULL;
11095
pctxt->isRedefine = 0;
11096
} else {
11097
if (IS_SCHEMA(child, "annotation")) {
11098
/*
11099
* TODO: discard or not?
11100
*/
11101
child = child->next;
11102
}
11103
}
11104
if (child != NULL) {
11105
res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11106
if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11107
xmlSchemaPContentErr(pctxt, res,
11108
NULL, node, child, NULL,
11109
"(annotation | (simpleType | complexType | group | attributeGroup))*");
11110
} else {
11111
xmlSchemaPContentErr(pctxt, res,
11112
NULL, node, child, NULL,
11113
"(annotation?)");
11114
}
11115
}
11116
return(res);
11117
11118
exit_error:
11119
return(pctxt->err);
11120
}
11121
11122
static int
11123
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11124
xmlNodePtr node)
11125
{
11126
int res;
11127
#ifndef ENABLE_REDEFINE
11128
TODO
11129
return(0);
11130
#endif
11131
res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11132
XML_SCHEMA_SCHEMA_REDEFINE);
11133
if (res != 0)
11134
return(res);
11135
return(0);
11136
}
11137
11138
static int
11139
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11140
xmlNodePtr node)
11141
{
11142
int res;
11143
11144
res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11145
XML_SCHEMA_SCHEMA_INCLUDE);
11146
if (res != 0)
11147
return(res);
11148
return(0);
11149
}
11150
11151
/**
11152
* xmlSchemaParseModelGroup:
11153
* @ctxt: a schema validation context
11154
* @schema: the schema being built
11155
* @node: a subtree containing XML Schema information
11156
* @type: the "compositor" type
11157
* @particleNeeded: if a a model group with a particle
11158
*
11159
* parse a XML schema Sequence definition.
11160
* Applies parts of:
11161
* Schema Representation Constraint:
11162
* Redefinition Constraints and Semantics (src-redefine)
11163
* (6.1), (6.1.1), (6.1.2)
11164
*
11165
* Schema Component Constraint:
11166
* All Group Limited (cos-all-limited) (2)
11167
* TODO: Actually this should go to component-level checks,
11168
* but is done here due to performance. Move it to an other layer
11169
* is schema construction via an API is implemented.
11170
*
11171
* *WARNING* this interface is highly subject to change
11172
*
11173
* Returns -1 in case of error, 0 if the declaration is improper and
11174
* 1 in case of success.
11175
*/
11176
static xmlSchemaTreeItemPtr
11177
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11178
xmlNodePtr node, xmlSchemaTypeType type,
11179
int withParticle)
11180
{
11181
xmlSchemaModelGroupPtr item;
11182
xmlSchemaParticlePtr particle = NULL;
11183
xmlNodePtr child = NULL;
11184
xmlAttrPtr attr;
11185
int min = 1, max = 1, isElemRef, hasRefs = 0;
11186
11187
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11188
return (NULL);
11189
/*
11190
* Create a model group with the given compositor.
11191
*/
11192
item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11193
if (item == NULL)
11194
return (NULL);
11195
11196
if (withParticle) {
11197
if (type == XML_SCHEMA_TYPE_ALL) {
11198
min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11199
max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11200
} else {
11201
/* choice + sequence */
11202
min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11203
max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11204
"(xs:nonNegativeInteger | unbounded)");
11205
}
11206
xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11207
/*
11208
* Create a particle
11209
*/
11210
particle = xmlSchemaAddParticle(ctxt, node, min, max);
11211
if (particle == NULL)
11212
return (NULL);
11213
particle->children = (xmlSchemaTreeItemPtr) item;
11214
/*
11215
* Check for illegal attributes.
11216
*/
11217
attr = node->properties;
11218
while (attr != NULL) {
11219
if (attr->ns == NULL) {
11220
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11221
(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11222
(!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11223
xmlSchemaPIllegalAttrErr(ctxt,
11224
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11225
}
11226
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11227
xmlSchemaPIllegalAttrErr(ctxt,
11228
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11229
}
11230
attr = attr->next;
11231
}
11232
} else {
11233
/*
11234
* Check for illegal attributes.
11235
*/
11236
attr = node->properties;
11237
while (attr != NULL) {
11238
if (attr->ns == NULL) {
11239
if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11240
xmlSchemaPIllegalAttrErr(ctxt,
11241
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11242
}
11243
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11244
xmlSchemaPIllegalAttrErr(ctxt,
11245
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11246
}
11247
attr = attr->next;
11248
}
11249
}
11250
11251
/*
11252
* Extract and validate attributes.
11253
*/
11254
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11255
/*
11256
* And now for the children...
11257
*/
11258
child = node->children;
11259
if (IS_SCHEMA(child, "annotation")) {
11260
item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11261
child = child->next;
11262
}
11263
if (type == XML_SCHEMA_TYPE_ALL) {
11264
xmlSchemaParticlePtr part, last = NULL;
11265
11266
while (IS_SCHEMA(child, "element")) {
11267
part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11268
schema, child, &isElemRef, 0);
11269
/*
11270
* SPEC cos-all-limited (2)
11271
* "The {max occurs} of all the particles in the {particles}
11272
* of the ('all') group must be 0 or 1.
11273
*/
11274
if (part != NULL) {
11275
if (isElemRef)
11276
hasRefs++;
11277
if (part->minOccurs > 1) {
11278
xmlSchemaPCustomErr(ctxt,
11279
XML_SCHEMAP_COS_ALL_LIMITED,
11280
NULL, child,
11281
"Invalid value for minOccurs (must be 0 or 1)",
11282
NULL);
11283
/* Reset to 1. */
11284
part->minOccurs = 1;
11285
}
11286
if (part->maxOccurs > 1) {
11287
xmlSchemaPCustomErr(ctxt,
11288
XML_SCHEMAP_COS_ALL_LIMITED,
11289
NULL, child,
11290
"Invalid value for maxOccurs (must be 0 or 1)",
11291
NULL);
11292
/* Reset to 1. */
11293
part->maxOccurs = 1;
11294
}
11295
if (last == NULL)
11296
item->children = (xmlSchemaTreeItemPtr) part;
11297
else
11298
last->next = (xmlSchemaTreeItemPtr) part;
11299
last = part;
11300
}
11301
child = child->next;
11302
}
11303
if (child != NULL) {
11304
xmlSchemaPContentErr(ctxt,
11305
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11306
NULL, node, child, NULL,
11307
"(annotation?, (annotation?, element*)");
11308
}
11309
} else {
11310
/* choice + sequence */
11311
xmlSchemaTreeItemPtr part = NULL, last = NULL;
11312
11313
while ((IS_SCHEMA(child, "element")) ||
11314
(IS_SCHEMA(child, "group")) ||
11315
(IS_SCHEMA(child, "any")) ||
11316
(IS_SCHEMA(child, "choice")) ||
11317
(IS_SCHEMA(child, "sequence"))) {
11318
11319
if (IS_SCHEMA(child, "element")) {
11320
part = (xmlSchemaTreeItemPtr)
11321
xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11322
if (part && isElemRef)
11323
hasRefs++;
11324
} else if (IS_SCHEMA(child, "group")) {
11325
part =
11326
xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11327
if (part != NULL)
11328
hasRefs++;
11329
/*
11330
* Handle redefinitions.
11331
*/
11332
if (ctxt->isRedefine && ctxt->redef &&
11333
(ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11334
part && part->children)
11335
{
11336
if ((xmlSchemaGetQNameRefName(part->children) ==
11337
ctxt->redef->refName) &&
11338
(xmlSchemaGetQNameRefTargetNs(part->children) ==
11339
ctxt->redef->refTargetNs))
11340
{
11341
/*
11342
* SPEC src-redefine:
11343
* (6.1) "If it has a <group> among its contents at
11344
* some level the `actual value` of whose ref
11345
* [attribute] is the same as the `actual value` of
11346
* its own name attribute plus target namespace, then
11347
* all of the following must be true:"
11348
* (6.1.1) "It must have exactly one such group."
11349
*/
11350
if (ctxt->redefCounter != 0) {
11351
xmlChar *str = NULL;
11352
11353
xmlSchemaCustomErr(ACTXT_CAST ctxt,
11354
XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11355
"The redefining model group definition "
11356
"'%s' must not contain more than one "
11357
"reference to the redefined definition",
11358
xmlSchemaFormatQName(&str,
11359
ctxt->redef->refTargetNs,
11360
ctxt->redef->refName),
11361
NULL);
11362
FREE_AND_NULL(str)
11363
part = NULL;
11364
} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11365
((WXS_PARTICLE(part))->maxOccurs != 1))
11366
{
11367
xmlChar *str = NULL;
11368
/*
11369
* SPEC src-redefine:
11370
* (6.1.2) "The `actual value` of both that
11371
* group's minOccurs and maxOccurs [attribute]
11372
* must be 1 (or `absent`).
11373
*/
11374
xmlSchemaCustomErr(ACTXT_CAST ctxt,
11375
XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11376
"The redefining model group definition "
11377
"'%s' must not contain a reference to the "
11378
"redefined definition with a "
11379
"maxOccurs/minOccurs other than 1",
11380
xmlSchemaFormatQName(&str,
11381
ctxt->redef->refTargetNs,
11382
ctxt->redef->refName),
11383
NULL);
11384
FREE_AND_NULL(str)
11385
part = NULL;
11386
}
11387
ctxt->redef->reference = WXS_BASIC_CAST part;
11388
ctxt->redefCounter++;
11389
}
11390
}
11391
} else if (IS_SCHEMA(child, "any")) {
11392
part = (xmlSchemaTreeItemPtr)
11393
xmlSchemaParseAny(ctxt, schema, child);
11394
} else if (IS_SCHEMA(child, "choice")) {
11395
part = xmlSchemaParseModelGroup(ctxt, schema, child,
11396
XML_SCHEMA_TYPE_CHOICE, 1);
11397
} else if (IS_SCHEMA(child, "sequence")) {
11398
part = xmlSchemaParseModelGroup(ctxt, schema, child,
11399
XML_SCHEMA_TYPE_SEQUENCE, 1);
11400
}
11401
if (part != NULL) {
11402
if (last == NULL)
11403
item->children = part;
11404
else
11405
last->next = part;
11406
last = part;
11407
}
11408
child = child->next;
11409
}
11410
if (child != NULL) {
11411
xmlSchemaPContentErr(ctxt,
11412
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11413
NULL, node, child, NULL,
11414
"(annotation?, (element | group | choice | sequence | any)*)");
11415
}
11416
}
11417
if ((max == 0) && (min == 0))
11418
return (NULL);
11419
if (hasRefs) {
11420
/*
11421
* We need to resolve references.
11422
*/
11423
WXS_ADD_PENDING(ctxt, item);
11424
}
11425
if (withParticle)
11426
return ((xmlSchemaTreeItemPtr) particle);
11427
else
11428
return ((xmlSchemaTreeItemPtr) item);
11429
}
11430
11431
/**
11432
* xmlSchemaParseRestriction:
11433
* @ctxt: a schema validation context
11434
* @schema: the schema being built
11435
* @node: a subtree containing XML Schema information
11436
*
11437
* parse a XML schema Restriction definition
11438
* *WARNING* this interface is highly subject to change
11439
*
11440
* Returns the type definition or NULL in case of error
11441
*/
11442
static xmlSchemaTypePtr
11443
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11444
xmlNodePtr node, xmlSchemaTypeType parentType)
11445
{
11446
xmlSchemaTypePtr type;
11447
xmlNodePtr child = NULL;
11448
xmlAttrPtr attr;
11449
11450
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11451
return (NULL);
11452
/* Not a component, don't create it. */
11453
type = ctxt->ctxtType;
11454
type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11455
11456
/*
11457
* Check for illegal attributes.
11458
*/
11459
attr = node->properties;
11460
while (attr != NULL) {
11461
if (attr->ns == NULL) {
11462
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11463
(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11464
xmlSchemaPIllegalAttrErr(ctxt,
11465
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11466
}
11467
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11468
xmlSchemaPIllegalAttrErr(ctxt,
11469
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11470
}
11471
attr = attr->next;
11472
}
11473
/*
11474
* Extract and validate attributes.
11475
*/
11476
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11477
/*
11478
* Attribute
11479
*/
11480
/*
11481
* Extract the base type. The "base" attribute is mandatory if inside
11482
* a complex type or if redefining.
11483
*
11484
* SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11485
* among its [children]), the simple type definition which is
11486
* the {content type} of the type definition `resolved` to by
11487
* the `actual value` of the base [attribute]"
11488
*/
11489
if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11490
&(type->baseNs), &(type->base)) == 0)
11491
{
11492
if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11493
xmlSchemaPMissingAttrErr(ctxt,
11494
XML_SCHEMAP_S4S_ATTR_MISSING,
11495
NULL, node, "base", NULL);
11496
} else if ((ctxt->isRedefine) &&
11497
(type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11498
{
11499
if (type->base == NULL) {
11500
xmlSchemaPMissingAttrErr(ctxt,
11501
XML_SCHEMAP_S4S_ATTR_MISSING,
11502
NULL, node, "base", NULL);
11503
} else if ((! xmlStrEqual(type->base, type->name)) ||
11504
(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11505
{
11506
xmlChar *str1 = NULL, *str2 = NULL;
11507
/*
11508
* REDEFINE: SPEC src-redefine (5)
11509
* "Within the [children], each <simpleType> must have a
11510
* <restriction> among its [children] ... the `actual value` of
11511
* whose base [attribute] must be the same as the `actual value`
11512
* of its own name attribute plus target namespace;"
11513
*/
11514
xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11515
NULL, node, "This is a redefinition, but the QName "
11516
"value '%s' of the 'base' attribute does not match the "
11517
"type's designation '%s'",
11518
xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11519
xmlSchemaFormatQName(&str2, type->targetNamespace,
11520
type->name), NULL);
11521
FREE_AND_NULL(str1);
11522
FREE_AND_NULL(str2);
11523
/* Avoid confusion and erase the values. */
11524
type->base = NULL;
11525
type->baseNs = NULL;
11526
}
11527
}
11528
}
11529
/*
11530
* And now for the children...
11531
*/
11532
child = node->children;
11533
if (IS_SCHEMA(child, "annotation")) {
11534
/*
11535
* Add the annotation to the simple type ancestor.
11536
*/
11537
xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11538
xmlSchemaParseAnnotation(ctxt, child, 1));
11539
child = child->next;
11540
}
11541
if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11542
/*
11543
* Corresponds to <simpleType><restriction><simpleType>.
11544
*/
11545
if (IS_SCHEMA(child, "simpleType")) {
11546
if (type->base != NULL) {
11547
/*
11548
* src-restriction-base-or-simpleType
11549
* Either the base [attribute] or the simpleType [child] of the
11550
* <restriction> element must be present, but not both.
11551
*/
11552
xmlSchemaPContentErr(ctxt,
11553
XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11554
NULL, node, child,
11555
"The attribute 'base' and the <simpleType> child are "
11556
"mutually exclusive", NULL);
11557
} else {
11558
type->baseType = (xmlSchemaTypePtr)
11559
xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11560
}
11561
child = child->next;
11562
} else if (type->base == NULL) {
11563
xmlSchemaPContentErr(ctxt,
11564
XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11565
NULL, node, child,
11566
"Either the attribute 'base' or a <simpleType> child "
11567
"must be present", NULL);
11568
}
11569
} else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11570
/*
11571
* Corresponds to <complexType><complexContent><restriction>...
11572
* followed by:
11573
*
11574
* Model groups <all>, <choice> and <sequence>.
11575
*/
11576
if (IS_SCHEMA(child, "all")) {
11577
type->subtypes = (xmlSchemaTypePtr)
11578
xmlSchemaParseModelGroup(ctxt, schema, child,
11579
XML_SCHEMA_TYPE_ALL, 1);
11580
child = child->next;
11581
} else if (IS_SCHEMA(child, "choice")) {
11582
type->subtypes = (xmlSchemaTypePtr)
11583
xmlSchemaParseModelGroup(ctxt,
11584
schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11585
child = child->next;
11586
} else if (IS_SCHEMA(child, "sequence")) {
11587
type->subtypes = (xmlSchemaTypePtr)
11588
xmlSchemaParseModelGroup(ctxt, schema, child,
11589
XML_SCHEMA_TYPE_SEQUENCE, 1);
11590
child = child->next;
11591
/*
11592
* Model group reference <group>.
11593
*/
11594
} else if (IS_SCHEMA(child, "group")) {
11595
type->subtypes = (xmlSchemaTypePtr)
11596
xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11597
/*
11598
* Note that the reference will be resolved in
11599
* xmlSchemaResolveTypeReferences();
11600
*/
11601
child = child->next;
11602
}
11603
} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11604
/*
11605
* Corresponds to <complexType><simpleContent><restriction>...
11606
*
11607
* "1.1 the simple type definition corresponding to the <simpleType>
11608
* among the [children] of <restriction> if there is one;"
11609
*/
11610
if (IS_SCHEMA(child, "simpleType")) {
11611
/*
11612
* We will store the to-be-restricted simple type in
11613
* type->contentTypeDef *temporarily*.
11614
*/
11615
type->contentTypeDef = (xmlSchemaTypePtr)
11616
xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11617
if ( type->contentTypeDef == NULL)
11618
return (NULL);
11619
child = child->next;
11620
}
11621
}
11622
11623
if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11624
(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11625
xmlSchemaFacetPtr facet, lastfacet = NULL;
11626
/*
11627
* Corresponds to <complexType><simpleContent><restriction>...
11628
* <simpleType><restriction>...
11629
*/
11630
11631
/*
11632
* Add the facets to the simple type ancestor.
11633
*/
11634
/*
11635
* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11636
* Simple Type Definition Schema Representation Constraint:
11637
* *Single Facet Value*
11638
*/
11639
while ((IS_SCHEMA(child, "minInclusive")) ||
11640
(IS_SCHEMA(child, "minExclusive")) ||
11641
(IS_SCHEMA(child, "maxInclusive")) ||
11642
(IS_SCHEMA(child, "maxExclusive")) ||
11643
(IS_SCHEMA(child, "totalDigits")) ||
11644
(IS_SCHEMA(child, "fractionDigits")) ||
11645
(IS_SCHEMA(child, "pattern")) ||
11646
(IS_SCHEMA(child, "enumeration")) ||
11647
(IS_SCHEMA(child, "whiteSpace")) ||
11648
(IS_SCHEMA(child, "length")) ||
11649
(IS_SCHEMA(child, "maxLength")) ||
11650
(IS_SCHEMA(child, "minLength"))) {
11651
facet = xmlSchemaParseFacet(ctxt, schema, child);
11652
if (facet != NULL) {
11653
if (lastfacet == NULL)
11654
type->facets = facet;
11655
else
11656
lastfacet->next = facet;
11657
lastfacet = facet;
11658
lastfacet->next = NULL;
11659
}
11660
child = child->next;
11661
}
11662
/*
11663
* Create links for derivation and validation.
11664
*/
11665
if (type->facets != NULL) {
11666
xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11667
11668
facet = type->facets;
11669
do {
11670
facetLink = (xmlSchemaFacetLinkPtr)
11671
xmlMalloc(sizeof(xmlSchemaFacetLink));
11672
if (facetLink == NULL) {
11673
xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11674
xmlFree(facetLink);
11675
return (NULL);
11676
}
11677
facetLink->facet = facet;
11678
facetLink->next = NULL;
11679
if (lastFacetLink == NULL)
11680
type->facetSet = facetLink;
11681
else
11682
lastFacetLink->next = facetLink;
11683
lastFacetLink = facetLink;
11684
facet = facet->next;
11685
} while (facet != NULL);
11686
}
11687
}
11688
if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11689
/*
11690
* Attribute uses/declarations.
11691
*/
11692
if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11693
(xmlSchemaItemListPtr *) &(type->attrUses),
11694
XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11695
return(NULL);
11696
/*
11697
* Attribute wildcard.
11698
*/
11699
if (IS_SCHEMA(child, "anyAttribute")) {
11700
type->attributeWildcard =
11701
xmlSchemaParseAnyAttribute(ctxt, schema, child);
11702
child = child->next;
11703
}
11704
}
11705
if (child != NULL) {
11706
if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11707
xmlSchemaPContentErr(ctxt,
11708
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11709
NULL, node, child, NULL,
11710
"annotation?, (group | all | choice | sequence)?, "
11711
"((attribute | attributeGroup)*, anyAttribute?))");
11712
} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11713
xmlSchemaPContentErr(ctxt,
11714
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11715
NULL, node, child, NULL,
11716
"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11717
"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11718
"length | minLength | maxLength | enumeration | whiteSpace | "
11719
"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11720
} else {
11721
/* Simple type */
11722
xmlSchemaPContentErr(ctxt,
11723
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11724
NULL, node, child, NULL,
11725
"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11726
"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11727
"length | minLength | maxLength | enumeration | whiteSpace | "
11728
"pattern)*))");
11729
}
11730
}
11731
return (NULL);
11732
}
11733
11734
/**
11735
* xmlSchemaParseExtension:
11736
* @ctxt: a schema validation context
11737
* @schema: the schema being built
11738
* @node: a subtree containing XML Schema information
11739
*
11740
* Parses an <extension>, which is found inside a
11741
* <simpleContent> or <complexContent>.
11742
* *WARNING* this interface is highly subject to change.
11743
*
11744
* TODO: Returns the type definition or NULL in case of error
11745
*/
11746
static xmlSchemaTypePtr
11747
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11748
xmlNodePtr node, xmlSchemaTypeType parentType)
11749
{
11750
xmlSchemaTypePtr type;
11751
xmlNodePtr child = NULL;
11752
xmlAttrPtr attr;
11753
11754
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11755
return (NULL);
11756
/* Not a component, don't create it. */
11757
type = ctxt->ctxtType;
11758
type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11759
11760
/*
11761
* Check for illegal attributes.
11762
*/
11763
attr = node->properties;
11764
while (attr != NULL) {
11765
if (attr->ns == NULL) {
11766
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11767
(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11768
xmlSchemaPIllegalAttrErr(ctxt,
11769
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11770
}
11771
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11772
xmlSchemaPIllegalAttrErr(ctxt,
11773
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11774
}
11775
attr = attr->next;
11776
}
11777
11778
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11779
11780
/*
11781
* Attribute "base" - mandatory.
11782
*/
11783
if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11784
"base", &(type->baseNs), &(type->base)) == 0) &&
11785
(type->base == NULL)) {
11786
xmlSchemaPMissingAttrErr(ctxt,
11787
XML_SCHEMAP_S4S_ATTR_MISSING,
11788
NULL, node, "base", NULL);
11789
}
11790
/*
11791
* And now for the children...
11792
*/
11793
child = node->children;
11794
if (IS_SCHEMA(child, "annotation")) {
11795
/*
11796
* Add the annotation to the type ancestor.
11797
*/
11798
xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11799
xmlSchemaParseAnnotation(ctxt, child, 1));
11800
child = child->next;
11801
}
11802
if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11803
/*
11804
* Corresponds to <complexType><complexContent><extension>... and:
11805
*
11806
* Model groups <all>, <choice>, <sequence> and <group>.
11807
*/
11808
if (IS_SCHEMA(child, "all")) {
11809
type->subtypes = (xmlSchemaTypePtr)
11810
xmlSchemaParseModelGroup(ctxt, schema,
11811
child, XML_SCHEMA_TYPE_ALL, 1);
11812
child = child->next;
11813
} else if (IS_SCHEMA(child, "choice")) {
11814
type->subtypes = (xmlSchemaTypePtr)
11815
xmlSchemaParseModelGroup(ctxt, schema,
11816
child, XML_SCHEMA_TYPE_CHOICE, 1);
11817
child = child->next;
11818
} else if (IS_SCHEMA(child, "sequence")) {
11819
type->subtypes = (xmlSchemaTypePtr)
11820
xmlSchemaParseModelGroup(ctxt, schema,
11821
child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11822
child = child->next;
11823
} else if (IS_SCHEMA(child, "group")) {
11824
type->subtypes = (xmlSchemaTypePtr)
11825
xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11826
/*
11827
* Note that the reference will be resolved in
11828
* xmlSchemaResolveTypeReferences();
11829
*/
11830
child = child->next;
11831
}
11832
}
11833
if (child != NULL) {
11834
/*
11835
* Attribute uses/declarations.
11836
*/
11837
if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11838
(xmlSchemaItemListPtr *) &(type->attrUses),
11839
XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11840
return(NULL);
11841
/*
11842
* Attribute wildcard.
11843
*/
11844
if (IS_SCHEMA(child, "anyAttribute")) {
11845
ctxt->ctxtType->attributeWildcard =
11846
xmlSchemaParseAnyAttribute(ctxt, schema, child);
11847
child = child->next;
11848
}
11849
}
11850
if (child != NULL) {
11851
if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11852
/* Complex content extension. */
11853
xmlSchemaPContentErr(ctxt,
11854
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11855
NULL, node, child, NULL,
11856
"(annotation?, ((group | all | choice | sequence)?, "
11857
"((attribute | attributeGroup)*, anyAttribute?)))");
11858
} else {
11859
/* Simple content extension. */
11860
xmlSchemaPContentErr(ctxt,
11861
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11862
NULL, node, child, NULL,
11863
"(annotation?, ((attribute | attributeGroup)*, "
11864
"anyAttribute?))");
11865
}
11866
}
11867
return (NULL);
11868
}
11869
11870
/**
11871
* xmlSchemaParseSimpleContent:
11872
* @ctxt: a schema validation context
11873
* @schema: the schema being built
11874
* @node: a subtree containing XML Schema information
11875
*
11876
* parse a XML schema SimpleContent definition
11877
* *WARNING* this interface is highly subject to change
11878
*
11879
* Returns the type definition or NULL in case of error
11880
*/
11881
static int
11882
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11883
xmlSchemaPtr schema, xmlNodePtr node,
11884
int *hasRestrictionOrExtension)
11885
{
11886
xmlSchemaTypePtr type;
11887
xmlNodePtr child = NULL;
11888
xmlAttrPtr attr;
11889
11890
if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11891
(hasRestrictionOrExtension == NULL))
11892
return (-1);
11893
*hasRestrictionOrExtension = 0;
11894
/* Not a component, don't create it. */
11895
type = ctxt->ctxtType;
11896
type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11897
/*
11898
* Check for illegal attributes.
11899
*/
11900
attr = node->properties;
11901
while (attr != NULL) {
11902
if (attr->ns == NULL) {
11903
if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11904
xmlSchemaPIllegalAttrErr(ctxt,
11905
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11906
}
11907
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11908
xmlSchemaPIllegalAttrErr(ctxt,
11909
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11910
}
11911
attr = attr->next;
11912
}
11913
11914
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
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 complex type ancestor.
11923
*/
11924
xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11925
xmlSchemaParseAnnotation(ctxt, child, 1));
11926
child = child->next;
11927
}
11928
if (child == NULL) {
11929
xmlSchemaPContentErr(ctxt,
11930
XML_SCHEMAP_S4S_ELEM_MISSING,
11931
NULL, node, NULL, NULL,
11932
"(annotation?, (restriction | extension))");
11933
}
11934
if (child == NULL) {
11935
xmlSchemaPContentErr(ctxt,
11936
XML_SCHEMAP_S4S_ELEM_MISSING,
11937
NULL, node, NULL, NULL,
11938
"(annotation?, (restriction | extension))");
11939
}
11940
if (IS_SCHEMA(child, "restriction")) {
11941
xmlSchemaParseRestriction(ctxt, schema, child,
11942
XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11943
(*hasRestrictionOrExtension) = 1;
11944
child = child->next;
11945
} else if (IS_SCHEMA(child, "extension")) {
11946
xmlSchemaParseExtension(ctxt, schema, child,
11947
XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11948
(*hasRestrictionOrExtension) = 1;
11949
child = child->next;
11950
}
11951
if (child != NULL) {
11952
xmlSchemaPContentErr(ctxt,
11953
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11954
NULL, node, child, NULL,
11955
"(annotation?, (restriction | extension))");
11956
}
11957
return (0);
11958
}
11959
11960
/**
11961
* xmlSchemaParseComplexContent:
11962
* @ctxt: a schema validation context
11963
* @schema: the schema being built
11964
* @node: a subtree containing XML Schema information
11965
*
11966
* parse a XML schema ComplexContent definition
11967
* *WARNING* this interface is highly subject to change
11968
*
11969
* Returns the type definition or NULL in case of error
11970
*/
11971
static int
11972
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11973
xmlSchemaPtr schema, xmlNodePtr node,
11974
int *hasRestrictionOrExtension)
11975
{
11976
xmlSchemaTypePtr type;
11977
xmlNodePtr child = NULL;
11978
xmlAttrPtr attr;
11979
11980
if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11981
(hasRestrictionOrExtension == NULL))
11982
return (-1);
11983
*hasRestrictionOrExtension = 0;
11984
/* Not a component, don't create it. */
11985
type = ctxt->ctxtType;
11986
/*
11987
* Check for illegal attributes.
11988
*/
11989
attr = node->properties;
11990
while (attr != NULL) {
11991
if (attr->ns == NULL) {
11992
if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11993
(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
11994
{
11995
xmlSchemaPIllegalAttrErr(ctxt,
11996
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11997
}
11998
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11999
xmlSchemaPIllegalAttrErr(ctxt,
12000
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12001
}
12002
attr = attr->next;
12003
}
12004
12005
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12006
12007
/*
12008
* Set the 'mixed' on the complex type ancestor.
12009
*/
12010
if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
12011
if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12012
type->flags |= XML_SCHEMAS_TYPE_MIXED;
12013
}
12014
child = node->children;
12015
if (IS_SCHEMA(child, "annotation")) {
12016
/*
12017
* Add the annotation to the complex type ancestor.
12018
*/
12019
xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12020
xmlSchemaParseAnnotation(ctxt, child, 1));
12021
child = child->next;
12022
}
12023
if (child == NULL) {
12024
xmlSchemaPContentErr(ctxt,
12025
XML_SCHEMAP_S4S_ELEM_MISSING,
12026
NULL, node, NULL,
12027
NULL, "(annotation?, (restriction | extension))");
12028
}
12029
if (child == NULL) {
12030
xmlSchemaPContentErr(ctxt,
12031
XML_SCHEMAP_S4S_ELEM_MISSING,
12032
NULL, node, NULL,
12033
NULL, "(annotation?, (restriction | extension))");
12034
}
12035
if (IS_SCHEMA(child, "restriction")) {
12036
xmlSchemaParseRestriction(ctxt, schema, child,
12037
XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12038
(*hasRestrictionOrExtension) = 1;
12039
child = child->next;
12040
} else if (IS_SCHEMA(child, "extension")) {
12041
xmlSchemaParseExtension(ctxt, schema, child,
12042
XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12043
(*hasRestrictionOrExtension) = 1;
12044
child = child->next;
12045
}
12046
if (child != NULL) {
12047
xmlSchemaPContentErr(ctxt,
12048
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12049
NULL, node, child,
12050
NULL, "(annotation?, (restriction | extension))");
12051
}
12052
return (0);
12053
}
12054
12055
/**
12056
* xmlSchemaParseComplexType:
12057
* @ctxt: a schema validation context
12058
* @schema: the schema being built
12059
* @node: a subtree containing XML Schema information
12060
*
12061
* parse a XML schema Complex Type definition
12062
* *WARNING* this interface is highly subject to change
12063
*
12064
* Returns the type definition or NULL in case of error
12065
*/
12066
static xmlSchemaTypePtr
12067
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12068
xmlNodePtr node, int topLevel)
12069
{
12070
xmlSchemaTypePtr type, ctxtType;
12071
xmlNodePtr child = NULL;
12072
const xmlChar *name = NULL;
12073
xmlAttrPtr attr;
12074
const xmlChar *attrValue;
12075
#ifdef ENABLE_NAMED_LOCALS
12076
char buf[40];
12077
#endif
12078
int final = 0, block = 0, hasRestrictionOrExtension = 0;
12079
12080
12081
if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12082
return (NULL);
12083
12084
ctxtType = ctxt->ctxtType;
12085
12086
if (topLevel) {
12087
attr = xmlSchemaGetPropNode(node, "name");
12088
if (attr == NULL) {
12089
xmlSchemaPMissingAttrErr(ctxt,
12090
XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12091
return (NULL);
12092
} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12093
xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12094
return (NULL);
12095
}
12096
}
12097
12098
if (topLevel == 0) {
12099
/*
12100
* Parse as local complex type definition.
12101
*/
12102
#ifdef ENABLE_NAMED_LOCALS
12103
snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12104
type = xmlSchemaAddType(ctxt, schema,
12105
XML_SCHEMA_TYPE_COMPLEX,
12106
xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12107
ctxt->targetNamespace, node, 0);
12108
#else
12109
type = xmlSchemaAddType(ctxt, schema,
12110
XML_SCHEMA_TYPE_COMPLEX,
12111
NULL, ctxt->targetNamespace, node, 0);
12112
#endif
12113
if (type == NULL)
12114
return (NULL);
12115
name = type->name;
12116
type->node = node;
12117
type->type = XML_SCHEMA_TYPE_COMPLEX;
12118
/*
12119
* TODO: We need the target namespace.
12120
*/
12121
} else {
12122
/*
12123
* Parse as global complex type definition.
12124
*/
12125
type = xmlSchemaAddType(ctxt, schema,
12126
XML_SCHEMA_TYPE_COMPLEX,
12127
name, ctxt->targetNamespace, node, 1);
12128
if (type == NULL)
12129
return (NULL);
12130
type->node = node;
12131
type->type = XML_SCHEMA_TYPE_COMPLEX;
12132
type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12133
}
12134
type->targetNamespace = ctxt->targetNamespace;
12135
/*
12136
* Handle attributes.
12137
*/
12138
attr = node->properties;
12139
while (attr != NULL) {
12140
if (attr->ns == NULL) {
12141
if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12142
/*
12143
* Attribute "id".
12144
*/
12145
xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12146
} else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12147
/*
12148
* Attribute "mixed".
12149
*/
12150
if (xmlSchemaPGetBoolNodeValue(ctxt,
12151
NULL, (xmlNodePtr) attr))
12152
type->flags |= XML_SCHEMAS_TYPE_MIXED;
12153
} else if (topLevel) {
12154
/*
12155
* Attributes of global complex type definitions.
12156
*/
12157
if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12158
/* Pass. */
12159
} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12160
/*
12161
* Attribute "abstract".
12162
*/
12163
if (xmlSchemaPGetBoolNodeValue(ctxt,
12164
NULL, (xmlNodePtr) attr))
12165
type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12166
} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12167
/*
12168
* Attribute "final".
12169
*/
12170
attrValue = xmlSchemaGetNodeContent(ctxt,
12171
(xmlNodePtr) attr);
12172
if (xmlSchemaPValAttrBlockFinal(attrValue,
12173
&(type->flags),
12174
-1,
12175
XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12176
XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12177
-1, -1, -1) != 0)
12178
{
12179
xmlSchemaPSimpleTypeErr(ctxt,
12180
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12181
NULL, (xmlNodePtr) attr, NULL,
12182
"(#all | List of (extension | restriction))",
12183
attrValue, NULL, NULL, NULL);
12184
} else
12185
final = 1;
12186
} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12187
/*
12188
* Attribute "block".
12189
*/
12190
attrValue = xmlSchemaGetNodeContent(ctxt,
12191
(xmlNodePtr) attr);
12192
if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12193
-1,
12194
XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12195
XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12196
-1, -1, -1) != 0) {
12197
xmlSchemaPSimpleTypeErr(ctxt,
12198
XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12199
NULL, (xmlNodePtr) attr, NULL,
12200
"(#all | List of (extension | restriction)) ",
12201
attrValue, NULL, NULL, NULL);
12202
} else
12203
block = 1;
12204
} else {
12205
xmlSchemaPIllegalAttrErr(ctxt,
12206
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12207
}
12208
} else {
12209
xmlSchemaPIllegalAttrErr(ctxt,
12210
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12211
}
12212
} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12213
xmlSchemaPIllegalAttrErr(ctxt,
12214
XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12215
}
12216
attr = attr->next;
12217
}
12218
if (! block) {
12219
/*
12220
* Apply default "block" values.
12221
*/
12222
if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12223
type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12224
if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12225
type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12226
}
12227
if (! final) {
12228
/*
12229
* Apply default "block" values.
12230
*/
12231
if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12232
type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12233
if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12234
type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12235
}
12236
/*
12237
* And now for the children...
12238
*/
12239
child = node->children;
12240
if (IS_SCHEMA(child, "annotation")) {
12241
type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12242
child = child->next;
12243
}
12244
ctxt->ctxtType = type;
12245
if (IS_SCHEMA(child, "simpleContent")) {
12246
/*
12247
* <complexType><simpleContent>...
12248
* 3.4.3 : 2.2
12249
* Specifying mixed='true' when the <simpleContent>
12250
* alternative is chosen has no effect
12251
*/
12252
if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12253
type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12254
xmlSchemaParseSimpleContent(ctxt, schema, child,
12255
&hasRestrictionOrExtension);
12256
child = child->next;
12257
} else if (IS_SCHEMA(child, "complexContent")) {
12258
/*
12259
* <complexType><complexContent>...
12260
*/
12261
type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12262
xmlSchemaParseComplexContent(ctxt, schema, child,
12263
&hasRestrictionOrExtension);
12264
child = child->next;
12265
} else {
12266
/*
12267
* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12268
*
12269
* SPEC
12270
* "...the third alternative (neither <simpleContent> nor
12271
* <complexContent>) is chosen. This case is understood as shorthand
12272
* for complex content restricting the `ur-type definition`, and the
12273
* details of the mappings should be modified as necessary.
12274
*/
12275
type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12276
type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12277
/*
12278
* Parse model groups.
12279
*/
12280
if (IS_SCHEMA(child, "all")) {
12281
type->subtypes = (xmlSchemaTypePtr)
12282
xmlSchemaParseModelGroup(ctxt, schema, child,
12283
XML_SCHEMA_TYPE_ALL, 1);
12284
child = child->next;
12285
} else if (IS_SCHEMA(child, "choice")) {
12286
type->subtypes = (xmlSchemaTypePtr)
12287
xmlSchemaParseModelGroup(ctxt, schema, child,
12288
XML_SCHEMA_TYPE_CHOICE, 1);
12289
child = child->next;
12290
} else if (IS_SCHEMA(child, "sequence")) {
12291
type->subtypes = (xmlSchemaTypePtr)
12292
xmlSchemaParseModelGroup(ctxt, schema, child,
12293
XML_SCHEMA_TYPE_SEQUENCE, 1);
12294
child = child->next;
12295
} else if (IS_SCHEMA(child, "group")) {
12296
type->subtypes = (xmlSchemaTypePtr)
12297
xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12298
/*
12299
* Note that the reference will be resolved in
12300
* xmlSchemaResolveTypeReferences();
12301
*/
12302
child = child->next;
12303
}
12304
/*
12305
* Parse attribute decls/refs.
12306
*/
12307
if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12308
(xmlSchemaItemListPtr *) &(type->attrUses),
12309
XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12310
return(NULL);
12311
/*
12312
* Parse attribute wildcard.
12313
*/
12314
if (IS_SCHEMA(child, "anyAttribute")) {
12315
type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12316
child = child->next;
12317
}
12318
}
12319
if (child != NULL) {
12320
xmlSchemaPContentErr(ctxt,
12321
XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12322
NULL, node, child,
12323
NULL, "(annotation?, (simpleContent | complexContent | "
12324
"((group | all | choice | sequence)?, ((attribute | "
12325
"attributeGroup)*, anyAttribute?))))");
12326
}
12327
/*
12328
* REDEFINE: SPEC src-redefine (5)
12329
*/
12330
if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12331
xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12332
NULL, node, "This is a redefinition, thus the "
12333
"<complexType> must have a <restriction> or <extension> "
12334
"grand-child", NULL);
12335
}
12336
ctxt->ctxtType = ctxtType;
12337
return (type);
12338
}
12339
12340
/************************************************************************
12341
* *
12342
* Validating using Schemas *
12343
* *
12344
************************************************************************/
12345
12346
/************************************************************************
12347
* *
12348
* Reading/Writing Schemas *
12349
* *
12350
************************************************************************/
12351
12352
#if 0 /* Will be enabled if it is clear what options are needed. */
12353
/**
12354
* xmlSchemaParserCtxtSetOptions:
12355
* @ctxt: a schema parser context
12356
* @options: a combination of xmlSchemaParserOption
12357
*
12358
* Sets the options to be used during the parse.
12359
*
12360
* Returns 0 in case of success, -1 in case of an
12361
* API error.
12362
*/
12363
static int
12364
xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12365
int options)
12366
12367
{
12368
int i;
12369
12370
if (ctxt == NULL)
12371
return (-1);
12372
/*
12373
* WARNING: Change the start value if adding to the
12374
* xmlSchemaParseOption.
12375
*/
12376
for (i = 1; i < (int) sizeof(int) * 8; i++) {
12377
if (options & 1<<i) {
12378
return (-1);
12379
}
12380
}
12381
ctxt->options = options;
12382
return (0);
12383
}
12384
12385
/**
12386
* xmlSchemaValidCtxtGetOptions:
12387
* @ctxt: a schema parser context
12388
*
12389
* Returns the option combination of the parser context.
12390
*/
12391
static int
12392
xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12393
12394
{
12395
if (ctxt == NULL)
12396
return (-1);
12397
else
12398
return (ctxt->options);
12399
}
12400
#endif
12401
12402
/**
12403
* xmlSchemaNewParserCtxt:
12404
* @URL: the location of the schema
12405
*
12406
* Create an XML Schemas parse context for that file/resource expected
12407
* to contain an XML Schemas file.
12408
*
12409
* Returns the parser context or NULL in case of error
12410
*/
12411
xmlSchemaParserCtxtPtr
12412
xmlSchemaNewParserCtxt(const char *URL)
12413
{
12414
xmlSchemaParserCtxtPtr ret;
12415
12416
if (URL == NULL)
12417
return (NULL);
12418
12419
ret = xmlSchemaParserCtxtCreate();
12420
if (ret == NULL)
12421
return(NULL);
12422
ret->dict = xmlDictCreate();
12423
ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12424
return (ret);
12425
}
12426
12427
/**
12428
* xmlSchemaNewMemParserCtxt:
12429
* @buffer: a pointer to a char array containing the schemas
12430
* @size: the size of the array
12431
*
12432
* Create an XML Schemas parse context for that memory buffer expected
12433
* to contain an XML Schemas file.
12434
*
12435
* Returns the parser context or NULL in case of error
12436
*/
12437
xmlSchemaParserCtxtPtr
12438
xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12439
{
12440
xmlSchemaParserCtxtPtr ret;
12441
12442
if ((buffer == NULL) || (size <= 0))
12443
return (NULL);
12444
ret = xmlSchemaParserCtxtCreate();
12445
if (ret == NULL)
12446
return(NULL);
12447
ret->buffer = buffer;
12448
ret->size = size;
12449
ret->dict = xmlDictCreate();
12450
return (ret);
12451
}
12452
12453
/**
12454
* xmlSchemaNewDocParserCtxt:
12455
* @doc: a preparsed document tree
12456
*
12457
* Create an XML Schemas parse context for that document.
12458
* NB. The document may be modified during the parsing process.
12459
*
12460
* Returns the parser context or NULL in case of error
12461
*/
12462
xmlSchemaParserCtxtPtr
12463
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12464
{
12465
xmlSchemaParserCtxtPtr ret;
12466
12467
if (doc == NULL)
12468
return (NULL);
12469
ret = xmlSchemaParserCtxtCreate();
12470
if (ret == NULL)
12471
return(NULL);
12472
ret->doc = doc;
12473
ret->dict = xmlDictCreate();
12474
/* The application has responsibility for the document */
12475
ret->preserve = 1;
12476
12477
return (ret);
12478
}
12479
12480
/**
12481
* xmlSchemaFreeParserCtxt:
12482
* @ctxt: the schema parser context
12483
*
12484
* Free the resources associated to the schema parser context
12485
*/
12486
void
12487
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12488
{
12489
if (ctxt == NULL)
12490
return;
12491
if (ctxt->doc != NULL && !ctxt->preserve)
12492
xmlFreeDoc(ctxt->doc);
12493
if (ctxt->vctxt != NULL) {
12494
xmlSchemaFreeValidCtxt(ctxt->vctxt);
12495
}
12496
if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12497
xmlSchemaConstructionCtxtFree(ctxt->constructor);
12498
ctxt->constructor = NULL;
12499
ctxt->ownsConstructor = 0;
12500
}
12501
if (ctxt->attrProhibs != NULL)
12502
xmlSchemaItemListFree(ctxt->attrProhibs);
12503
xmlDictFree(ctxt->dict);
12504
xmlFree(ctxt);
12505
}
12506
12507
/************************************************************************
12508
* *
12509
* Building the content models *
12510
* *
12511
************************************************************************/
12512
12513
/**
12514
* xmlSchemaBuildContentModelForSubstGroup:
12515
*
12516
* Returns 1 if nillable, 0 otherwise
12517
*/
12518
static int
12519
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12520
xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12521
{
12522
xmlAutomataStatePtr start, tmp;
12523
xmlSchemaElementPtr elemDecl, member;
12524
xmlSchemaSubstGroupPtr substGroup;
12525
int i;
12526
int ret = 0;
12527
12528
elemDecl = (xmlSchemaElementPtr) particle->children;
12529
/*
12530
* Wrap the substitution group with a CHOICE.
12531
*/
12532
start = pctxt->state;
12533
if (end == NULL)
12534
end = xmlAutomataNewState(pctxt->am);
12535
substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12536
if (substGroup == NULL) {
12537
xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12538
XML_SCHEMAP_INTERNAL,
12539
"Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12540
"declaration is marked having a subst. group but none "
12541
"available.\n", elemDecl->name, NULL);
12542
return(0);
12543
}
12544
if (counter >= 0) {
12545
/*
12546
* NOTE that we put the declaration in, even if it's abstract.
12547
* However, an error will be raised during *validation* if an element
12548
* information item shall be validated against an abstract element
12549
* declaration.
12550
*/
12551
tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12552
xmlAutomataNewTransition2(pctxt->am, tmp, end,
12553
elemDecl->name, elemDecl->targetNamespace, elemDecl);
12554
/*
12555
* Add subst. group members.
12556
*/
12557
for (i = 0; i < substGroup->members->nbItems; i++) {
12558
member = (xmlSchemaElementPtr) substGroup->members->items[i];
12559
xmlAutomataNewTransition2(pctxt->am, tmp, end,
12560
member->name, member->targetNamespace, member);
12561
}
12562
} else if (particle->maxOccurs == 1) {
12563
/*
12564
* NOTE that we put the declaration in, even if it's abstract,
12565
*/
12566
xmlAutomataNewEpsilon(pctxt->am,
12567
xmlAutomataNewTransition2(pctxt->am,
12568
start, NULL,
12569
elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12570
/*
12571
* Add subst. group members.
12572
*/
12573
for (i = 0; i < substGroup->members->nbItems; i++) {
12574
member = (xmlSchemaElementPtr) substGroup->members->items[i];
12575
/*
12576
* NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12577
* was incorrectly used instead of xmlAutomataNewTransition2()
12578
* (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12579
* section in xmlSchemaBuildAContentModel() ).
12580
* TODO: Check if xmlAutomataNewOnceTrans2() was instead
12581
* intended for the above "counter" section originally. I.e.,
12582
* check xs:all with subst-groups.
12583
*
12584
* tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12585
* member->name, member->targetNamespace,
12586
* 1, 1, member);
12587
*/
12588
tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12589
member->name, member->targetNamespace, member);
12590
xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12591
}
12592
} else {
12593
xmlAutomataStatePtr hop;
12594
int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12595
UNBOUNDED : particle->maxOccurs - 1;
12596
int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12597
12598
counter =
12599
xmlAutomataNewCounter(pctxt->am, minOccurs,
12600
maxOccurs);
12601
hop = xmlAutomataNewState(pctxt->am);
12602
12603
xmlAutomataNewEpsilon(pctxt->am,
12604
xmlAutomataNewTransition2(pctxt->am,
12605
start, NULL,
12606
elemDecl->name, elemDecl->targetNamespace, elemDecl),
12607
hop);
12608
/*
12609
* Add subst. group members.
12610
*/
12611
for (i = 0; i < substGroup->members->nbItems; i++) {
12612
member = (xmlSchemaElementPtr) substGroup->members->items[i];
12613
xmlAutomataNewEpsilon(pctxt->am,
12614
xmlAutomataNewTransition2(pctxt->am,
12615
start, NULL,
12616
member->name, member->targetNamespace, member),
12617
hop);
12618
}
12619
xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12620
xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12621
}
12622
if (particle->minOccurs == 0) {
12623
xmlAutomataNewEpsilon(pctxt->am, start, end);
12624
ret = 1;
12625
}
12626
pctxt->state = end;
12627
return(ret);
12628
}
12629
12630
/**
12631
* xmlSchemaBuildContentModelForElement:
12632
*
12633
* Returns 1 if nillable, 0 otherwise
12634
*/
12635
static int
12636
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12637
xmlSchemaParticlePtr particle)
12638
{
12639
int ret = 0;
12640
12641
if (((xmlSchemaElementPtr) particle->children)->flags &
12642
XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12643
/*
12644
* Substitution groups.
12645
*/
12646
ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12647
} else {
12648
xmlSchemaElementPtr elemDecl;
12649
xmlAutomataStatePtr start;
12650
12651
elemDecl = (xmlSchemaElementPtr) particle->children;
12652
12653
if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12654
return(0);
12655
if (particle->maxOccurs == 1) {
12656
start = ctxt->state;
12657
ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12658
elemDecl->name, elemDecl->targetNamespace, elemDecl);
12659
} else if ((particle->maxOccurs >= UNBOUNDED) &&
12660
(particle->minOccurs < 2)) {
12661
/* Special case. */
12662
start = ctxt->state;
12663
ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12664
elemDecl->name, elemDecl->targetNamespace, elemDecl);
12665
ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12666
elemDecl->name, elemDecl->targetNamespace, elemDecl);
12667
} else {
12668
int counter;
12669
int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12670
UNBOUNDED : particle->maxOccurs - 1;
12671
int minOccurs = particle->minOccurs < 1 ?
12672
0 : particle->minOccurs - 1;
12673
12674
start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12675
counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12676
ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12677
elemDecl->name, elemDecl->targetNamespace, elemDecl);
12678
xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12679
ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12680
NULL, counter);
12681
}
12682
if (particle->minOccurs == 0) {
12683
xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12684
ret = 1;
12685
}
12686
}
12687
return(ret);
12688
}
12689
12690
/**
12691
* xmlSchemaBuildAContentModel:
12692
* @ctxt: the schema parser context
12693
* @particle: the particle component
12694
* @name: the complex type's name whose content is being built
12695
*
12696
* Create the automaton for the {content type} of a complex type.
12697
*
12698
* Returns 1 if the content is nillable, 0 otherwise
12699
*/
12700
static int
12701
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12702
xmlSchemaParticlePtr particle)
12703
{
12704
int ret = 0, tmp2;
12705
12706
if (particle == NULL) {
12707
PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12708
return(1);
12709
}
12710
if (particle->children == NULL) {
12711
/*
12712
* Just return in this case. A missing "term" of the particle
12713
* might arise due to an invalid "term" component.
12714
*/
12715
return(1);
12716
}
12717
12718
switch (particle->children->type) {
12719
case XML_SCHEMA_TYPE_ANY: {
12720
xmlAutomataStatePtr start, end;
12721
xmlSchemaWildcardPtr wild;
12722
xmlSchemaWildcardNsPtr ns;
12723
12724
wild = (xmlSchemaWildcardPtr) particle->children;
12725
12726
start = pctxt->state;
12727
end = xmlAutomataNewState(pctxt->am);
12728
12729
if (particle->maxOccurs == 1) {
12730
if (wild->any == 1) {
12731
/*
12732
* We need to add both transitions:
12733
*
12734
* 1. the {"*", "*"} for elements in a namespace.
12735
*/
12736
pctxt->state =
12737
xmlAutomataNewTransition2(pctxt->am,
12738
start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12739
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12740
/*
12741
* 2. the {"*"} for elements in no namespace.
12742
*/
12743
pctxt->state =
12744
xmlAutomataNewTransition2(pctxt->am,
12745
start, NULL, BAD_CAST "*", NULL, wild);
12746
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12747
12748
} else if (wild->nsSet != NULL) {
12749
ns = wild->nsSet;
12750
do {
12751
pctxt->state = start;
12752
pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12753
pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12754
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12755
ns = ns->next;
12756
} while (ns != NULL);
12757
12758
} else if (wild->negNsSet != NULL) {
12759
pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12760
start, end, BAD_CAST "*", wild->negNsSet->value,
12761
wild);
12762
}
12763
} else {
12764
int counter;
12765
xmlAutomataStatePtr hop;
12766
int maxOccurs =
12767
particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12768
particle->maxOccurs - 1;
12769
int minOccurs =
12770
particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12771
12772
counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12773
hop = xmlAutomataNewState(pctxt->am);
12774
if (wild->any == 1) {
12775
pctxt->state =
12776
xmlAutomataNewTransition2(pctxt->am,
12777
start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12778
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12779
pctxt->state =
12780
xmlAutomataNewTransition2(pctxt->am,
12781
start, NULL, BAD_CAST "*", NULL, wild);
12782
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12783
} else if (wild->nsSet != NULL) {
12784
ns = wild->nsSet;
12785
do {
12786
pctxt->state =
12787
xmlAutomataNewTransition2(pctxt->am,
12788
start, NULL, BAD_CAST "*", ns->value, wild);
12789
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12790
ns = ns->next;
12791
} while (ns != NULL);
12792
12793
} else if (wild->negNsSet != NULL) {
12794
pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12795
start, hop, BAD_CAST "*", wild->negNsSet->value,
12796
wild);
12797
}
12798
xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12799
xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12800
}
12801
if (particle->minOccurs == 0) {
12802
xmlAutomataNewEpsilon(pctxt->am, start, end);
12803
ret = 1;
12804
}
12805
pctxt->state = end;
12806
break;
12807
}
12808
case XML_SCHEMA_TYPE_ELEMENT:
12809
ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12810
break;
12811
case XML_SCHEMA_TYPE_SEQUENCE:{
12812
xmlSchemaTreeItemPtr sub;
12813
12814
ret = 1;
12815
/*
12816
* If max and min occurrences are default (1) then
12817
* simply iterate over the particles of the <sequence>.
12818
*/
12819
if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12820
sub = particle->children->children;
12821
12822
while (sub != NULL) {
12823
tmp2 = xmlSchemaBuildAContentModel(pctxt,
12824
(xmlSchemaParticlePtr) sub);
12825
if (tmp2 != 1) ret = 0;
12826
sub = sub->next;
12827
}
12828
} else {
12829
xmlAutomataStatePtr oldstate = pctxt->state;
12830
12831
if (particle->maxOccurs >= UNBOUNDED) {
12832
if (particle->minOccurs > 1) {
12833
xmlAutomataStatePtr tmp;
12834
int counter;
12835
12836
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12837
oldstate, NULL);
12838
oldstate = pctxt->state;
12839
12840
counter = xmlAutomataNewCounter(pctxt->am,
12841
particle->minOccurs - 1, UNBOUNDED);
12842
12843
sub = particle->children->children;
12844
while (sub != NULL) {
12845
tmp2 = xmlSchemaBuildAContentModel(pctxt,
12846
(xmlSchemaParticlePtr) sub);
12847
if (tmp2 != 1) ret = 0;
12848
sub = sub->next;
12849
}
12850
tmp = pctxt->state;
12851
xmlAutomataNewCountedTrans(pctxt->am, tmp,
12852
oldstate, counter);
12853
pctxt->state =
12854
xmlAutomataNewCounterTrans(pctxt->am, tmp,
12855
NULL, counter);
12856
if (ret == 1)
12857
xmlAutomataNewEpsilon(pctxt->am,
12858
oldstate, pctxt->state);
12859
12860
} else {
12861
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12862
oldstate, NULL);
12863
oldstate = pctxt->state;
12864
12865
sub = particle->children->children;
12866
while (sub != NULL) {
12867
tmp2 = xmlSchemaBuildAContentModel(pctxt,
12868
(xmlSchemaParticlePtr) sub);
12869
if (tmp2 != 1) ret = 0;
12870
sub = sub->next;
12871
}
12872
xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12873
oldstate);
12874
/*
12875
* epsilon needed to block previous trans from
12876
* being allowed to enter back from another
12877
* construct
12878
*/
12879
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12880
pctxt->state, NULL);
12881
if (particle->minOccurs == 0) {
12882
xmlAutomataNewEpsilon(pctxt->am,
12883
oldstate, pctxt->state);
12884
ret = 1;
12885
}
12886
}
12887
} else if ((particle->maxOccurs > 1)
12888
|| (particle->minOccurs > 1)) {
12889
xmlAutomataStatePtr tmp;
12890
int counter;
12891
12892
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12893
oldstate, NULL);
12894
oldstate = pctxt->state;
12895
12896
counter = xmlAutomataNewCounter(pctxt->am,
12897
particle->minOccurs - 1,
12898
particle->maxOccurs - 1);
12899
12900
sub = particle->children->children;
12901
while (sub != NULL) {
12902
tmp2 = xmlSchemaBuildAContentModel(pctxt,
12903
(xmlSchemaParticlePtr) sub);
12904
if (tmp2 != 1) ret = 0;
12905
sub = sub->next;
12906
}
12907
tmp = pctxt->state;
12908
xmlAutomataNewCountedTrans(pctxt->am,
12909
tmp, oldstate, counter);
12910
pctxt->state =
12911
xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12912
counter);
12913
if ((particle->minOccurs == 0) || (ret == 1)) {
12914
xmlAutomataNewEpsilon(pctxt->am,
12915
oldstate, pctxt->state);
12916
ret = 1;
12917
}
12918
} else {
12919
sub = particle->children->children;
12920
while (sub != NULL) {
12921
tmp2 = xmlSchemaBuildAContentModel(pctxt,
12922
(xmlSchemaParticlePtr) sub);
12923
if (tmp2 != 1) ret = 0;
12924
sub = sub->next;
12925
}
12926
12927
/*
12928
* epsilon needed to block previous trans from
12929
* being allowed to enter back from another
12930
* construct
12931
*/
12932
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12933
pctxt->state, NULL);
12934
12935
if (particle->minOccurs == 0) {
12936
xmlAutomataNewEpsilon(pctxt->am, oldstate,
12937
pctxt->state);
12938
ret = 1;
12939
}
12940
}
12941
}
12942
break;
12943
}
12944
case XML_SCHEMA_TYPE_CHOICE:{
12945
xmlSchemaTreeItemPtr sub;
12946
xmlAutomataStatePtr start, end;
12947
12948
ret = 0;
12949
start = pctxt->state;
12950
end = xmlAutomataNewState(pctxt->am);
12951
12952
/*
12953
* iterate over the subtypes and remerge the end with an
12954
* epsilon transition
12955
*/
12956
if (particle->maxOccurs == 1) {
12957
sub = particle->children->children;
12958
while (sub != NULL) {
12959
pctxt->state = start;
12960
tmp2 = xmlSchemaBuildAContentModel(pctxt,
12961
(xmlSchemaParticlePtr) sub);
12962
if (tmp2 == 1) ret = 1;
12963
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12964
sub = sub->next;
12965
}
12966
} else {
12967
int counter;
12968
xmlAutomataStatePtr hop, base;
12969
int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12970
UNBOUNDED : particle->maxOccurs - 1;
12971
int minOccurs =
12972
particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12973
12974
/*
12975
* use a counter to keep track of the number of transitions
12976
* which went through the choice.
12977
*/
12978
counter =
12979
xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12980
hop = xmlAutomataNewState(pctxt->am);
12981
base = xmlAutomataNewState(pctxt->am);
12982
12983
sub = particle->children->children;
12984
while (sub != NULL) {
12985
pctxt->state = base;
12986
tmp2 = xmlSchemaBuildAContentModel(pctxt,
12987
(xmlSchemaParticlePtr) sub);
12988
if (tmp2 == 1) ret = 1;
12989
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12990
sub = sub->next;
12991
}
12992
xmlAutomataNewEpsilon(pctxt->am, start, base);
12993
xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12994
xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12995
if (ret == 1)
12996
xmlAutomataNewEpsilon(pctxt->am, base, end);
12997
}
12998
if (particle->minOccurs == 0) {
12999
xmlAutomataNewEpsilon(pctxt->am, start, end);
13000
ret = 1;
13001
}
13002
pctxt->state = end;
13003
break;
13004
}
13005
case XML_SCHEMA_TYPE_ALL:{
13006
xmlAutomataStatePtr start, tmp;
13007
xmlSchemaParticlePtr sub;
13008
xmlSchemaElementPtr elemDecl;
13009
13010
ret = 1;
13011
13012
sub = (xmlSchemaParticlePtr) particle->children->children;
13013
if (sub == NULL)
13014
break;
13015
13016
ret = 0;
13017
13018
start = pctxt->state;
13019
tmp = xmlAutomataNewState(pctxt->am);
13020
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13021
pctxt->state = tmp;
13022
while (sub != NULL) {
13023
pctxt->state = tmp;
13024
13025
elemDecl = (xmlSchemaElementPtr) sub->children;
13026
if (elemDecl == NULL) {
13027
PERROR_INT("xmlSchemaBuildAContentModel",
13028
"<element> particle has no term");
13029
return(ret);
13030
};
13031
/*
13032
* NOTE: The {max occurs} of all the particles in the
13033
* {particles} of the group must be 0 or 1; this is
13034
* already ensured during the parse of the content of
13035
* <all>.
13036
*/
13037
if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13038
int counter;
13039
13040
/*
13041
* This is an abstract group, we need to share
13042
* the same counter for all the element transitions
13043
* derived from the group
13044
*/
13045
counter = xmlAutomataNewCounter(pctxt->am,
13046
sub->minOccurs, sub->maxOccurs);
13047
xmlSchemaBuildContentModelForSubstGroup(pctxt,
13048
sub, counter, pctxt->state);
13049
} else {
13050
if ((sub->minOccurs == 1) &&
13051
(sub->maxOccurs == 1)) {
13052
xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13053
pctxt->state,
13054
elemDecl->name,
13055
elemDecl->targetNamespace,
13056
1, 1, elemDecl);
13057
} else if ((sub->minOccurs == 0) &&
13058
(sub->maxOccurs == 1)) {
13059
13060
xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13061
pctxt->state,
13062
elemDecl->name,
13063
elemDecl->targetNamespace,
13064
0,
13065
1,
13066
elemDecl);
13067
}
13068
}
13069
sub = (xmlSchemaParticlePtr) sub->next;
13070
}
13071
pctxt->state =
13072
xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13073
if (particle->minOccurs == 0) {
13074
xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13075
ret = 1;
13076
}
13077
break;
13078
}
13079
case XML_SCHEMA_TYPE_GROUP:
13080
/*
13081
* If we hit a model group definition, then this means that
13082
* it was empty, thus was not substituted for the containing
13083
* model group. Just do nothing in this case.
13084
* TODO: But the group should be substituted and not occur at
13085
* all in the content model at this point. Fix this.
13086
*/
13087
ret = 1;
13088
break;
13089
default:
13090
xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13091
"xmlSchemaBuildAContentModel",
13092
"found unexpected term of type '%s' in content model",
13093
WXS_ITEM_TYPE_NAME(particle->children), NULL);
13094
return(ret);
13095
}
13096
return(ret);
13097
}
13098
13099
/**
13100
* xmlSchemaBuildContentModel:
13101
* @ctxt: the schema parser context
13102
* @type: the complex type definition
13103
* @name: the element name
13104
*
13105
* Builds the content model of the complex type.
13106
*/
13107
static void
13108
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13109
xmlSchemaParserCtxtPtr ctxt)
13110
{
13111
if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13112
(type->contModel != NULL) ||
13113
((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13114
(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13115
return;
13116
13117
ctxt->am = NULL;
13118
ctxt->am = xmlNewAutomata();
13119
if (ctxt->am == NULL) {
13120
xmlGenericError(xmlGenericErrorContext,
13121
"Cannot create automata for complex type %s\n", type->name);
13122
return;
13123
}
13124
ctxt->state = xmlAutomataGetInitState(ctxt->am);
13125
/*
13126
* Build the automaton.
13127
*/
13128
xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13129
xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13130
type->contModel = xmlAutomataCompile(ctxt->am);
13131
if (type->contModel == NULL) {
13132
xmlSchemaPCustomErr(ctxt,
13133
XML_SCHEMAP_INTERNAL,
13134
WXS_BASIC_CAST type, type->node,
13135
"Failed to compile the content model", NULL);
13136
#if 0 /* disabled in Wine */
13137
} else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13138
xmlSchemaPCustomErr(ctxt,
13139
XML_SCHEMAP_NOT_DETERMINISTIC,
13140
/* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13141
WXS_BASIC_CAST type, type->node,
13142
"The content model is not determinist", NULL);
13143
#endif
13144
} else {
13145
}
13146
ctxt->state = NULL;
13147
xmlFreeAutomata(ctxt->am);
13148
ctxt->am = NULL;
13149
}
13150
13151
/**
13152
* xmlSchemaResolveElementReferences:
13153
* @elem: the schema element context
13154
* @ctxt: the schema parser context
13155
*
13156
* Resolves the references of an element declaration
13157
* or particle, which has an element declaration as it's
13158
* term.
13159
*/
13160
static void
13161
xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13162
xmlSchemaParserCtxtPtr ctxt)
13163
{
13164
if ((ctxt == NULL) || (elemDecl == NULL) ||
13165
((elemDecl != NULL) &&
13166
(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13167
return;
13168
elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13169
13170
if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13171
xmlSchemaTypePtr type;
13172
13173
/* (type definition) ... otherwise the type definition `resolved`
13174
* to by the `actual value` of the type [attribute] ...
13175
*/
13176
type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13177
elemDecl->namedTypeNs);
13178
if (type == NULL) {
13179
xmlSchemaPResCompAttrErr(ctxt,
13180
XML_SCHEMAP_SRC_RESOLVE,
13181
WXS_BASIC_CAST elemDecl, elemDecl->node,
13182
"type", elemDecl->namedType, elemDecl->namedTypeNs,
13183
XML_SCHEMA_TYPE_BASIC, "type definition");
13184
} else
13185
elemDecl->subtypes = type;
13186
}
13187
if (elemDecl->substGroup != NULL) {
13188
xmlSchemaElementPtr substHead;
13189
13190
/*
13191
* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13192
* substitutionGroup?
13193
*/
13194
substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13195
elemDecl->substGroupNs);
13196
if (substHead == NULL) {
13197
xmlSchemaPResCompAttrErr(ctxt,
13198
XML_SCHEMAP_SRC_RESOLVE,
13199
WXS_BASIC_CAST elemDecl, NULL,
13200
"substitutionGroup", elemDecl->substGroup,
13201
elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13202
} else {
13203
xmlSchemaResolveElementReferences(substHead, ctxt);
13204
/*
13205
* Set the "substitution group affiliation".
13206
* NOTE that now we use the "refDecl" field for this.
13207
*/
13208
WXS_SUBST_HEAD(elemDecl) = substHead;
13209
/*
13210
* The type definitions is set to:
13211
* SPEC "...the {type definition} of the element
13212
* declaration `resolved` to by the `actual value`
13213
* of the substitutionGroup [attribute], if present"
13214
*/
13215
if (elemDecl->subtypes == NULL) {
13216
if (substHead->subtypes == NULL) {
13217
/*
13218
* This can happen with self-referencing substitution
13219
* groups. The cycle will be detected later, but we have
13220
* to set subtypes to avoid null-pointer dereferences.
13221
*/
13222
elemDecl->subtypes = xmlSchemaGetBuiltInType(
13223
XML_SCHEMAS_ANYTYPE);
13224
} else {
13225
elemDecl->subtypes = substHead->subtypes;
13226
}
13227
}
13228
}
13229
}
13230
/*
13231
* SPEC "The definition of anyType serves as the default type definition
13232
* for element declarations whose XML representation does not specify one."
13233
*/
13234
if ((elemDecl->subtypes == NULL) &&
13235
(elemDecl->namedType == NULL) &&
13236
(elemDecl->substGroup == NULL))
13237
elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13238
}
13239
13240
/**
13241
* xmlSchemaResolveUnionMemberTypes:
13242
* @ctxt: the schema parser context
13243
* @type: the schema simple type definition
13244
*
13245
* Checks and builds the "member type definitions" property of the union
13246
* simple type. This handles part (1), part (2) is done in
13247
* xmlSchemaFinishMemberTypeDefinitionsProperty()
13248
*
13249
* Returns -1 in case of an internal error, 0 otherwise.
13250
*/
13251
static int
13252
xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13253
xmlSchemaTypePtr type)
13254
{
13255
13256
xmlSchemaTypeLinkPtr link, lastLink, newLink;
13257
xmlSchemaTypePtr memberType;
13258
13259
/*
13260
* SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13261
* define the explicit members as the type definitions `resolved`
13262
* to by the items in the `actual value` of the memberTypes [attribute],
13263
* if any, followed by the type definitions corresponding to the
13264
* <simpleType>s among the [children] of <union>, if any."
13265
*/
13266
/*
13267
* Resolve references.
13268
*/
13269
link = type->memberTypes;
13270
lastLink = NULL;
13271
while (link != NULL) {
13272
const xmlChar *name, *nsName;
13273
13274
name = ((xmlSchemaQNameRefPtr) link->type)->name;
13275
nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13276
13277
memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13278
if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13279
xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13280
WXS_BASIC_CAST type, type->node, "memberTypes",
13281
name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13282
/*
13283
* Remove the member type link.
13284
*/
13285
if (lastLink == NULL)
13286
type->memberTypes = link->next;
13287
else
13288
lastLink->next = link->next;
13289
newLink = link;
13290
link = link->next;
13291
xmlFree(newLink);
13292
} else {
13293
link->type = memberType;
13294
lastLink = link;
13295
link = link->next;
13296
}
13297
}
13298
/*
13299
* Add local simple types,
13300
*/
13301
memberType = type->subtypes;
13302
while (memberType != NULL) {
13303
link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13304
if (link == NULL) {
13305
xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13306
return (-1);
13307
}
13308
link->type = memberType;
13309
link->next = NULL;
13310
if (lastLink == NULL)
13311
type->memberTypes = link;
13312
else
13313
lastLink->next = link;
13314
lastLink = link;
13315
memberType = memberType->next;
13316
}
13317
return (0);
13318
}
13319
13320
/**
13321
* xmlSchemaIsDerivedFromBuiltInType:
13322
* @ctxt: the schema parser context
13323
* @type: the type definition
13324
* @valType: the value type
13325
*
13326
*
13327
* Returns 1 if the type has the given value type, or
13328
* is derived from such a type.
13329
*/
13330
static int
13331
xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13332
{
13333
if (type == NULL)
13334
return (0);
13335
if (WXS_IS_COMPLEX(type))
13336
return (0);
13337
if (type->type == XML_SCHEMA_TYPE_BASIC) {
13338
if (type->builtInType == valType)
13339
return(1);
13340
if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13341
(type->builtInType == XML_SCHEMAS_ANYTYPE))
13342
return (0);
13343
return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13344
}
13345
return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13346
}
13347
13348
#if 0
13349
/**
13350
* xmlSchemaIsDerivedFromBuiltInType:
13351
* @ctxt: the schema parser context
13352
* @type: the type definition
13353
* @valType: the value type
13354
*
13355
*
13356
* Returns 1 if the type has the given value type, or
13357
* is derived from such a type.
13358
*/
13359
static int
13360
xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13361
{
13362
if (type == NULL)
13363
return (0);
13364
if (WXS_IS_COMPLEX(type))
13365
return (0);
13366
if (type->type == XML_SCHEMA_TYPE_BASIC) {
13367
if (type->builtInType == valType)
13368
return(1);
13369
return (0);
13370
} else
13371
return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13372
13373
return (0);
13374
}
13375
13376
static xmlSchemaTypePtr
13377
xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13378
{
13379
if (type == NULL)
13380
return (NULL);
13381
if (WXS_IS_COMPLEX(type))
13382
return (NULL);
13383
if (type->type == XML_SCHEMA_TYPE_BASIC)
13384
return(type);
13385
return(xmlSchemaQueryBuiltInType(type->subtypes));
13386
}
13387
#endif
13388
13389
/**
13390
* xmlSchemaGetPrimitiveType:
13391
* @type: the simpleType definition
13392
*
13393
* Returns the primitive type of the given type or
13394
* NULL in case of error.
13395
*/
13396
static xmlSchemaTypePtr
13397
xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13398
{
13399
13400
while (type != NULL) {
13401
/*
13402
* Note that anySimpleType is actually not a primitive type
13403
* but we need that here.
13404
*/
13405
if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13406
(type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13407
return (type);
13408
type = type->baseType;
13409
}
13410
13411
return (NULL);
13412
}
13413
13414
#if 0
13415
/**
13416
* xmlSchemaGetBuiltInTypeAncestor:
13417
* @type: the simpleType definition
13418
*
13419
* Returns the primitive type of the given type or
13420
* NULL in case of error.
13421
*/
13422
static xmlSchemaTypePtr
13423
xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13424
{
13425
if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13426
return (0);
13427
while (type != NULL) {
13428
if (type->type == XML_SCHEMA_TYPE_BASIC)
13429
return (type);
13430
type = type->baseType;
13431
}
13432
13433
return (NULL);
13434
}
13435
#endif
13436
13437
/**
13438
* xmlSchemaCloneWildcardNsConstraints:
13439
* @ctxt: the schema parser context
13440
* @dest: the destination wildcard
13441
* @source: the source wildcard
13442
*
13443
* Clones the namespace constraints of source
13444
* and assigns them to dest.
13445
* Returns -1 on internal error, 0 otherwise.
13446
*/
13447
static int
13448
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13449
xmlSchemaWildcardPtr dest,
13450
xmlSchemaWildcardPtr source)
13451
{
13452
xmlSchemaWildcardNsPtr cur, tmp, last;
13453
13454
if ((source == NULL) || (dest == NULL))
13455
return(-1);
13456
dest->any = source->any;
13457
cur = source->nsSet;
13458
last = NULL;
13459
while (cur != NULL) {
13460
tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13461
if (tmp == NULL)
13462
return(-1);
13463
tmp->value = cur->value;
13464
if (last == NULL)
13465
dest->nsSet = tmp;
13466
else
13467
last->next = tmp;
13468
last = tmp;
13469
cur = cur->next;
13470
}
13471
if (dest->negNsSet != NULL)
13472
xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13473
if (source->negNsSet != NULL) {
13474
dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13475
if (dest->negNsSet == NULL)
13476
return(-1);
13477
dest->negNsSet->value = source->negNsSet->value;
13478
} else
13479
dest->negNsSet = NULL;
13480
return(0);
13481
}
13482
13483
/**
13484
* xmlSchemaUnionWildcards:
13485
* @ctxt: the schema parser context
13486
* @completeWild: the first wildcard
13487
* @curWild: the second wildcard
13488
*
13489
* Unions the namespace constraints of the given wildcards.
13490
* @completeWild will hold the resulting union.
13491
* Returns a positive error code on failure, -1 in case of an
13492
* internal error, 0 otherwise.
13493
*/
13494
static int
13495
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13496
xmlSchemaWildcardPtr completeWild,
13497
xmlSchemaWildcardPtr curWild)
13498
{
13499
xmlSchemaWildcardNsPtr cur, curB, tmp;
13500
13501
/*
13502
* 1 If O1 and O2 are the same value, then that value must be the
13503
* value.
13504
*/
13505
if ((completeWild->any == curWild->any) &&
13506
((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13507
((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13508
13509
if ((completeWild->negNsSet == NULL) ||
13510
(completeWild->negNsSet->value == curWild->negNsSet->value)) {
13511
13512
if (completeWild->nsSet != NULL) {
13513
int found = 0;
13514
13515
/*
13516
* Check equality of sets.
13517
*/
13518
cur = completeWild->nsSet;
13519
while (cur != NULL) {
13520
found = 0;
13521
curB = curWild->nsSet;
13522
while (curB != NULL) {
13523
if (cur->value == curB->value) {
13524
found = 1;
13525
break;
13526
}
13527
curB = curB->next;
13528
}
13529
if (!found)
13530
break;
13531
cur = cur->next;
13532
}
13533
if (found)
13534
return(0);
13535
} else
13536
return(0);
13537
}
13538
}
13539
/*
13540
* 2 If either O1 or O2 is any, then any must be the value
13541
*/
13542
if (completeWild->any != curWild->any) {
13543
if (completeWild->any == 0) {
13544
completeWild->any = 1;
13545
if (completeWild->nsSet != NULL) {
13546
xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13547
completeWild->nsSet = NULL;
13548
}
13549
if (completeWild->negNsSet != NULL) {
13550
xmlFree(completeWild->negNsSet);
13551
completeWild->negNsSet = NULL;
13552
}
13553
}
13554
return (0);
13555
}
13556
/*
13557
* 3 If both O1 and O2 are sets of (namespace names or `absent`),
13558
* then the union of those sets must be the value.
13559
*/
13560
if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13561
int found;
13562
xmlSchemaWildcardNsPtr start;
13563
13564
cur = curWild->nsSet;
13565
start = completeWild->nsSet;
13566
while (cur != NULL) {
13567
found = 0;
13568
curB = start;
13569
while (curB != NULL) {
13570
if (cur->value == curB->value) {
13571
found = 1;
13572
break;
13573
}
13574
curB = curB->next;
13575
}
13576
if (!found) {
13577
tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13578
if (tmp == NULL)
13579
return (-1);
13580
tmp->value = cur->value;
13581
tmp->next = completeWild->nsSet;
13582
completeWild->nsSet = tmp;
13583
}
13584
cur = cur->next;
13585
}
13586
13587
return(0);
13588
}
13589
/*
13590
* 4 If the two are negations of different values (namespace names
13591
* or `absent`), then a pair of not and `absent` must be the value.
13592
*/
13593
if ((completeWild->negNsSet != NULL) &&
13594
(curWild->negNsSet != NULL) &&
13595
(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13596
completeWild->negNsSet->value = NULL;
13597
13598
return(0);
13599
}
13600
/*
13601
* 5.
13602
*/
13603
if (((completeWild->negNsSet != NULL) &&
13604
(completeWild->negNsSet->value != NULL) &&
13605
(curWild->nsSet != NULL)) ||
13606
((curWild->negNsSet != NULL) &&
13607
(curWild->negNsSet->value != NULL) &&
13608
(completeWild->nsSet != NULL))) {
13609
13610
int nsFound, absentFound = 0;
13611
13612
if (completeWild->nsSet != NULL) {
13613
cur = completeWild->nsSet;
13614
curB = curWild->negNsSet;
13615
} else {
13616
cur = curWild->nsSet;
13617
curB = completeWild->negNsSet;
13618
}
13619
nsFound = 0;
13620
while (cur != NULL) {
13621
if (cur->value == NULL)
13622
absentFound = 1;
13623
else if (cur->value == curB->value)
13624
nsFound = 1;
13625
if (nsFound && absentFound)
13626
break;
13627
cur = cur->next;
13628
}
13629
13630
if (nsFound && absentFound) {
13631
/*
13632
* 5.1 If the set S includes both the negated namespace
13633
* name and `absent`, then any must be the value.
13634
*/
13635
completeWild->any = 1;
13636
if (completeWild->nsSet != NULL) {
13637
xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13638
completeWild->nsSet = NULL;
13639
}
13640
if (completeWild->negNsSet != NULL) {
13641
xmlFree(completeWild->negNsSet);
13642
completeWild->negNsSet = NULL;
13643
}
13644
} else if (nsFound && (!absentFound)) {
13645
/*
13646
* 5.2 If the set S includes the negated namespace name
13647
* but not `absent`, then a pair of not and `absent` must
13648
* be the value.
13649
*/
13650
if (completeWild->nsSet != NULL) {
13651
xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13652
completeWild->nsSet = NULL;
13653
}
13654
if (completeWild->negNsSet == NULL) {
13655
completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13656
if (completeWild->negNsSet == NULL)
13657
return (-1);
13658
}
13659
completeWild->negNsSet->value = NULL;
13660
} else if ((!nsFound) && absentFound) {
13661
/*
13662
* 5.3 If the set S includes `absent` but not the negated
13663
* namespace name, then the union is not expressible.
13664
*/
13665
xmlSchemaPErr(ctxt, completeWild->node,
13666
XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13667
"The union of the wildcard is not expressible.\n",
13668
NULL, NULL);
13669
return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13670
} else if ((!nsFound) && (!absentFound)) {
13671
/*
13672
* 5.4 If the set S does not include either the negated namespace
13673
* name or `absent`, then whichever of O1 or O2 is a pair of not
13674
* and a namespace name must be the value.
13675
*/
13676
if (completeWild->negNsSet == NULL) {
13677
if (completeWild->nsSet != NULL) {
13678
xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13679
completeWild->nsSet = NULL;
13680
}
13681
completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13682
if (completeWild->negNsSet == NULL)
13683
return (-1);
13684
completeWild->negNsSet->value = curWild->negNsSet->value;
13685
}
13686
}
13687
return (0);
13688
}
13689
/*
13690
* 6.
13691
*/
13692
if (((completeWild->negNsSet != NULL) &&
13693
(completeWild->negNsSet->value == NULL) &&
13694
(curWild->nsSet != NULL)) ||
13695
((curWild->negNsSet != NULL) &&
13696
(curWild->negNsSet->value == NULL) &&
13697
(completeWild->nsSet != NULL))) {
13698
13699
if (completeWild->nsSet != NULL) {
13700
cur = completeWild->nsSet;
13701
} else {
13702
cur = curWild->nsSet;
13703
}
13704
while (cur != NULL) {
13705
if (cur->value == NULL) {
13706
/*
13707
* 6.1 If the set S includes `absent`, then any must be the
13708
* value.
13709
*/
13710
completeWild->any = 1;
13711
if (completeWild->nsSet != NULL) {
13712
xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13713
completeWild->nsSet = NULL;
13714
}
13715
if (completeWild->negNsSet != NULL) {
13716
xmlFree(completeWild->negNsSet);
13717
completeWild->negNsSet = NULL;
13718
}
13719
return (0);
13720
}
13721
cur = cur->next;
13722
}
13723
if (completeWild->negNsSet == NULL) {
13724
/*
13725
* 6.2 If the set S does not include `absent`, then a pair of not
13726
* and `absent` must be the value.
13727
*/
13728
if (completeWild->nsSet != NULL) {
13729
xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13730
completeWild->nsSet = NULL;
13731
}
13732
completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13733
if (completeWild->negNsSet == NULL)
13734
return (-1);
13735
completeWild->negNsSet->value = NULL;
13736
}
13737
return (0);
13738
}
13739
return (0);
13740
13741
}
13742
13743
/**
13744
* xmlSchemaIntersectWildcards:
13745
* @ctxt: the schema parser context
13746
* @completeWild: the first wildcard
13747
* @curWild: the second wildcard
13748
*
13749
* Intersects the namespace constraints of the given wildcards.
13750
* @completeWild will hold the resulting intersection.
13751
* Returns a positive error code on failure, -1 in case of an
13752
* internal error, 0 otherwise.
13753
*/
13754
static int
13755
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13756
xmlSchemaWildcardPtr completeWild,
13757
xmlSchemaWildcardPtr curWild)
13758
{
13759
xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
13760
13761
/*
13762
* 1 If O1 and O2 are the same value, then that value must be the
13763
* value.
13764
*/
13765
if ((completeWild->any == curWild->any) &&
13766
((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13767
((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13768
13769
if ((completeWild->negNsSet == NULL) ||
13770
(completeWild->negNsSet->value == curWild->negNsSet->value)) {
13771
13772
if (completeWild->nsSet != NULL) {
13773
int found = 0;
13774
13775
/*
13776
* Check equality of sets.
13777
*/
13778
cur = completeWild->nsSet;
13779
while (cur != NULL) {
13780
found = 0;
13781
curB = curWild->nsSet;
13782
while (curB != NULL) {
13783
if (cur->value == curB->value) {
13784
found = 1;
13785
break;
13786
}
13787
curB = curB->next;
13788
}
13789
if (!found)
13790
break;
13791
cur = cur->next;
13792
}
13793
if (found)
13794
return(0);
13795
} else
13796
return(0);
13797
}
13798
}
13799
/*
13800
* 2 If either O1 or O2 is any, then the other must be the value.
13801
*/
13802
if ((completeWild->any != curWild->any) && (completeWild->any)) {
13803
if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13804
return(-1);
13805
return(0);
13806
}
13807
/*
13808
* 3 If either O1 or O2 is a pair of not and a value (a namespace
13809
* name or `absent`) and the other is a set of (namespace names or
13810
* `absent`), then that set, minus the negated value if it was in
13811
* the set, minus `absent` if it was in the set, must be the value.
13812
*/
13813
if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13814
((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13815
const xmlChar *neg;
13816
13817
if (completeWild->nsSet == NULL) {
13818
neg = completeWild->negNsSet->value;
13819
if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13820
return(-1);
13821
} else
13822
neg = curWild->negNsSet->value;
13823
/*
13824
* Remove absent and negated.
13825
*/
13826
prev = NULL;
13827
cur = completeWild->nsSet;
13828
while (cur != NULL) {
13829
if (cur->value == NULL) {
13830
if (prev == NULL)
13831
completeWild->nsSet = cur->next;
13832
else
13833
prev->next = cur->next;
13834
xmlFree(cur);
13835
break;
13836
}
13837
prev = cur;
13838
cur = cur->next;
13839
}
13840
if (neg != NULL) {
13841
prev = NULL;
13842
cur = completeWild->nsSet;
13843
while (cur != NULL) {
13844
if (cur->value == neg) {
13845
if (prev == NULL)
13846
completeWild->nsSet = cur->next;
13847
else
13848
prev->next = cur->next;
13849
xmlFree(cur);
13850
break;
13851
}
13852
prev = cur;
13853
cur = cur->next;
13854
}
13855
}
13856
13857
return(0);
13858
}
13859
/*
13860
* 4 If both O1 and O2 are sets of (namespace names or `absent`),
13861
* then the intersection of those sets must be the value.
13862
*/
13863
if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13864
int found;
13865
13866
cur = completeWild->nsSet;
13867
prev = NULL;
13868
while (cur != NULL) {
13869
found = 0;
13870
curB = curWild->nsSet;
13871
while (curB != NULL) {
13872
if (cur->value == curB->value) {
13873
found = 1;
13874
break;
13875
}
13876
curB = curB->next;
13877
}
13878
if (!found) {
13879
if (prev == NULL)
13880
completeWild->nsSet = cur->next;
13881
else
13882
prev->next = cur->next;
13883
tmp = cur->next;
13884
xmlFree(cur);
13885
cur = tmp;
13886
continue;
13887
}
13888
prev = cur;
13889
cur = cur->next;
13890
}
13891
13892
return(0);
13893
}
13894
/* 5 If the two are negations of different namespace names,
13895
* then the intersection is not expressible
13896
*/
13897
if ((completeWild->negNsSet != NULL) &&
13898
(curWild->negNsSet != NULL) &&
13899
(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13900
(completeWild->negNsSet->value != NULL) &&
13901
(curWild->negNsSet->value != NULL)) {
13902
13903
xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13904
"The intersection of the wildcard is not expressible.\n",
13905
NULL, NULL);
13906
return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13907
}
13908
/*
13909
* 6 If the one is a negation of a namespace name and the other
13910
* is a negation of `absent`, then the one which is the negation
13911
* of a namespace name must be the value.
13912
*/
13913
if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13914
(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13915
(completeWild->negNsSet->value == NULL)) {
13916
completeWild->negNsSet->value = curWild->negNsSet->value;
13917
}
13918
return(0);
13919
}
13920
13921
/**
13922
* xmlSchemaIsWildcardNsConstraintSubset:
13923
* @ctxt: the schema parser context
13924
* @sub: the first wildcard
13925
* @super: the second wildcard
13926
*
13927
* Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13928
*
13929
* Returns 0 if the namespace constraint of @sub is an intensional
13930
* subset of @super, 1 otherwise.
13931
*/
13932
static int
13933
xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13934
xmlSchemaWildcardPtr super)
13935
{
13936
/*
13937
* 1 super must be any.
13938
*/
13939
if (super->any)
13940
return (0);
13941
/*
13942
* 2.1 sub must be a pair of not and a namespace name or `absent`.
13943
* 2.2 super must be a pair of not and the same value.
13944
*/
13945
if ((sub->negNsSet != NULL) &&
13946
(super->negNsSet != NULL) &&
13947
(sub->negNsSet->value == super->negNsSet->value))
13948
return (0);
13949
/*
13950
* 3.1 sub must be a set whose members are either namespace names or `absent`.
13951
*/
13952
if (sub->nsSet != NULL) {
13953
/*
13954
* 3.2.1 super must be the same set or a superset thereof.
13955
*/
13956
if (super->nsSet != NULL) {
13957
xmlSchemaWildcardNsPtr cur, curB;
13958
int found = 0;
13959
13960
cur = sub->nsSet;
13961
while (cur != NULL) {
13962
found = 0;
13963
curB = super->nsSet;
13964
while (curB != NULL) {
13965
if (cur->value == curB->value) {
13966
found = 1;
13967
break;
13968
}
13969
curB = curB->next;
13970
}
13971
if (!found)
13972
return (1);
13973
cur = cur->next;
13974
}
13975
if (found)
13976
return (0);
13977
} else if (super->negNsSet != NULL) {
13978
xmlSchemaWildcardNsPtr cur;
13979
/*
13980
* 3.2.2 super must be a pair of not and a namespace name or
13981
* `absent` and that value must not be in sub's set.
13982
*/
13983
cur = sub->nsSet;
13984
while (cur != NULL) {
13985
if (cur->value == super->negNsSet->value)
13986
return (1);
13987
cur = cur->next;
13988
}
13989
return (0);
13990
}
13991
}
13992
return (1);
13993
}
13994
13995
static int
13996
xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13997
int *fixed,
13998
const xmlChar **value,
13999
xmlSchemaValPtr *val)
14000
{
14001
*fixed = 0;
14002
*value = NULL;
14003
if (val != 0)
14004
*val = NULL;
14005
14006
if (attruse->defValue != NULL) {
14007
*value = attruse->defValue;
14008
if (val != NULL)
14009
*val = attruse->defVal;
14010
if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14011
*fixed = 1;
14012
return(1);
14013
} else if ((attruse->attrDecl != NULL) &&
14014
(attruse->attrDecl->defValue != NULL)) {
14015
*value = attruse->attrDecl->defValue;
14016
if (val != NULL)
14017
*val = attruse->attrDecl->defVal;
14018
if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14019
*fixed = 1;
14020
return(1);
14021
}
14022
return(0);
14023
}
14024
/**
14025
* xmlSchemaCheckCVCWildcardNamespace:
14026
* @wild: the wildcard
14027
* @ns: the namespace
14028
*
14029
* Validation Rule: Wildcard allows Namespace Name
14030
* (cvc-wildcard-namespace)
14031
*
14032
* Returns 0 if the given namespace matches the wildcard,
14033
* 1 otherwise and -1 on API errors.
14034
*/
14035
static int
14036
xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14037
const xmlChar* ns)
14038
{
14039
if (wild == NULL)
14040
return(-1);
14041
14042
if (wild->any)
14043
return(0);
14044
else if (wild->nsSet != NULL) {
14045
xmlSchemaWildcardNsPtr cur;
14046
14047
cur = wild->nsSet;
14048
while (cur != NULL) {
14049
if (xmlStrEqual(cur->value, ns))
14050
return(0);
14051
cur = cur->next;
14052
}
14053
} else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14054
(!xmlStrEqual(wild->negNsSet->value, ns)))
14055
return(0);
14056
14057
return(1);
14058
}
14059
14060
#define XML_SCHEMA_ACTION_DERIVE 0
14061
#define XML_SCHEMA_ACTION_REDEFINE 1
14062
14063
#define WXS_ACTION_STR(a) \
14064
((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14065
14066
/*
14067
* Schema Component Constraint:
14068
* Derivation Valid (Restriction, Complex)
14069
* derivation-ok-restriction (2) - (4)
14070
*
14071
* ATTENTION:
14072
* In XML Schema 1.1 this will be:
14073
* Validation Rule:
14074
* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14075
*
14076
*/
14077
static int
14078
xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14079
int action,
14080
xmlSchemaBasicItemPtr item,
14081
xmlSchemaBasicItemPtr baseItem,
14082
xmlSchemaItemListPtr uses,
14083
xmlSchemaItemListPtr baseUses,
14084
xmlSchemaWildcardPtr wild,
14085
xmlSchemaWildcardPtr baseWild)
14086
{
14087
xmlSchemaAttributeUsePtr cur = NULL, bcur;
14088
int i, j, found; /* err = 0; */
14089
const xmlChar *bEffValue;
14090
int effFixed;
14091
14092
if (uses != NULL) {
14093
for (i = 0; i < uses->nbItems; i++) {
14094
cur = uses->items[i];
14095
found = 0;
14096
if (baseUses == NULL)
14097
goto not_found;
14098
for (j = 0; j < baseUses->nbItems; j++) {
14099
bcur = baseUses->items[j];
14100
if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14101
WXS_ATTRUSE_DECL_NAME(bcur)) &&
14102
(WXS_ATTRUSE_DECL_TNS(cur) ==
14103
WXS_ATTRUSE_DECL_TNS(bcur)))
14104
{
14105
/*
14106
* (2.1) "If there is an attribute use in the {attribute
14107
* uses} of the {base type definition} (call this B) whose
14108
* {attribute declaration} has the same {name} and {target
14109
* namespace}, then all of the following must be true:"
14110
*/
14111
found = 1;
14112
14113
if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14114
(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14115
{
14116
xmlChar *str = NULL;
14117
/*
14118
* (2.1.1) "one of the following must be true:"
14119
* (2.1.1.1) "B's {required} is false."
14120
* (2.1.1.2) "R's {required} is true."
14121
*/
14122
xmlSchemaPAttrUseErr4(pctxt,
14123
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14124
WXS_ITEM_NODE(item), item, cur,
14125
"The 'optional' attribute use is inconsistent "
14126
"with the corresponding 'required' attribute use of "
14127
"the %s %s",
14128
WXS_ACTION_STR(action),
14129
xmlSchemaGetComponentDesignation(&str, baseItem),
14130
NULL, NULL);
14131
FREE_AND_NULL(str);
14132
/* err = pctxt->err; */
14133
} else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14134
WXS_ATTRUSE_TYPEDEF(cur),
14135
WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14136
{
14137
xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14138
14139
/*
14140
* SPEC (2.1.2) "R's {attribute declaration}'s
14141
* {type definition} must be validly derived from
14142
* B's {type definition} given the empty set as
14143
* defined in Type Derivation OK (Simple) ($3.14.6)."
14144
*/
14145
xmlSchemaPAttrUseErr4(pctxt,
14146
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14147
WXS_ITEM_NODE(item), item, cur,
14148
"The attribute declaration's %s "
14149
"is not validly derived from "
14150
"the corresponding %s of the "
14151
"attribute declaration in the %s %s",
14152
xmlSchemaGetComponentDesignation(&strA,
14153
WXS_ATTRUSE_TYPEDEF(cur)),
14154
xmlSchemaGetComponentDesignation(&strB,
14155
WXS_ATTRUSE_TYPEDEF(bcur)),
14156
WXS_ACTION_STR(action),
14157
xmlSchemaGetComponentDesignation(&strC, baseItem));
14158
/* xmlSchemaGetComponentDesignation(&str, baseItem), */
14159
FREE_AND_NULL(strA);
14160
FREE_AND_NULL(strB);
14161
FREE_AND_NULL(strC);
14162
/* err = pctxt->err; */
14163
} else {
14164
/*
14165
* 2.1.3 [Definition:] Let the effective value
14166
* constraint of an attribute use be its {value
14167
* constraint}, if present, otherwise its {attribute
14168
* declaration}'s {value constraint} .
14169
*/
14170
xmlSchemaGetEffectiveValueConstraint(bcur,
14171
&effFixed, &bEffValue, NULL);
14172
/*
14173
* 2.1.3 ... one of the following must be true
14174
*
14175
* 2.1.3.1 B's `effective value constraint` is
14176
* `absent` or default.
14177
*/
14178
if ((bEffValue != NULL) &&
14179
(effFixed == 1)) {
14180
const xmlChar *rEffValue = NULL;
14181
14182
xmlSchemaGetEffectiveValueConstraint(bcur,
14183
&effFixed, &rEffValue, NULL);
14184
/*
14185
* 2.1.3.2 R's `effective value constraint` is
14186
* fixed with the same string as B's.
14187
* MAYBE TODO: Compare the computed values.
14188
* Hmm, it says "same string" so
14189
* string-equality might really be sufficient.
14190
*/
14191
if ((effFixed == 0) ||
14192
(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14193
{
14194
xmlChar *str = NULL;
14195
14196
xmlSchemaPAttrUseErr4(pctxt,
14197
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14198
WXS_ITEM_NODE(item), item, cur,
14199
"The effective value constraint of the "
14200
"attribute use is inconsistent with "
14201
"its correspondent in the %s %s",
14202
WXS_ACTION_STR(action),
14203
xmlSchemaGetComponentDesignation(&str,
14204
baseItem),
14205
NULL, NULL);
14206
FREE_AND_NULL(str);
14207
/* err = pctxt->err; */
14208
}
14209
}
14210
}
14211
break;
14212
}
14213
}
14214
not_found:
14215
if (!found) {
14216
/*
14217
* (2.2) "otherwise the {base type definition} must have an
14218
* {attribute wildcard} and the {target namespace} of the
14219
* R's {attribute declaration} must be `valid` with respect
14220
* to that wildcard, as defined in Wildcard allows Namespace
14221
* Name ($3.10.4)."
14222
*/
14223
if ((baseWild == NULL) ||
14224
(xmlSchemaCheckCVCWildcardNamespace(baseWild,
14225
(WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14226
{
14227
xmlChar *str = NULL;
14228
14229
xmlSchemaPAttrUseErr4(pctxt,
14230
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14231
WXS_ITEM_NODE(item), item, cur,
14232
"Neither a matching attribute use, "
14233
"nor a matching wildcard exists in the %s %s",
14234
WXS_ACTION_STR(action),
14235
xmlSchemaGetComponentDesignation(&str, baseItem),
14236
NULL, NULL);
14237
FREE_AND_NULL(str);
14238
/* err = pctxt->err; */
14239
}
14240
}
14241
}
14242
}
14243
/*
14244
* SPEC derivation-ok-restriction (3):
14245
* (3) "For each attribute use in the {attribute uses} of the {base type
14246
* definition} whose {required} is true, there must be an attribute
14247
* use with an {attribute declaration} with the same {name} and
14248
* {target namespace} as its {attribute declaration} in the {attribute
14249
* uses} of the complex type definition itself whose {required} is true.
14250
*/
14251
if (baseUses != NULL) {
14252
for (j = 0; j < baseUses->nbItems; j++) {
14253
bcur = baseUses->items[j];
14254
if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14255
continue;
14256
found = 0;
14257
if (uses != NULL) {
14258
for (i = 0; i < uses->nbItems; i++) {
14259
cur = uses->items[i];
14260
if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14261
WXS_ATTRUSE_DECL_NAME(bcur)) &&
14262
(WXS_ATTRUSE_DECL_TNS(cur) ==
14263
WXS_ATTRUSE_DECL_TNS(bcur))) {
14264
found = 1;
14265
break;
14266
}
14267
}
14268
}
14269
if (!found) {
14270
xmlChar *strA = NULL, *strB = NULL;
14271
14272
xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14273
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14274
NULL, item,
14275
"A matching attribute use for the "
14276
"'required' %s of the %s %s is missing",
14277
xmlSchemaGetComponentDesignation(&strA, bcur),
14278
WXS_ACTION_STR(action),
14279
xmlSchemaGetComponentDesignation(&strB, baseItem),
14280
NULL);
14281
FREE_AND_NULL(strA);
14282
FREE_AND_NULL(strB);
14283
}
14284
}
14285
}
14286
/*
14287
* derivation-ok-restriction (4)
14288
*/
14289
if (wild != NULL) {
14290
/*
14291
* (4) "If there is an {attribute wildcard}, all of the
14292
* following must be true:"
14293
*/
14294
if (baseWild == NULL) {
14295
xmlChar *str = NULL;
14296
14297
/*
14298
* (4.1) "The {base type definition} must also have one."
14299
*/
14300
xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14301
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14302
NULL, item,
14303
"The %s has an attribute wildcard, "
14304
"but the %s %s '%s' does not have one",
14305
WXS_ITEM_TYPE_NAME(item),
14306
WXS_ACTION_STR(action),
14307
WXS_ITEM_TYPE_NAME(baseItem),
14308
xmlSchemaGetComponentQName(&str, baseItem));
14309
FREE_AND_NULL(str);
14310
return(pctxt->err);
14311
} else if ((baseWild->any == 0) &&
14312
xmlSchemaCheckCOSNSSubset(wild, baseWild))
14313
{
14314
xmlChar *str = NULL;
14315
/*
14316
* (4.2) "The complex type definition's {attribute wildcard}'s
14317
* {namespace constraint} must be a subset of the {base type
14318
* definition}'s {attribute wildcard}'s {namespace constraint},
14319
* as defined by Wildcard Subset ($3.10.6)."
14320
*/
14321
xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14322
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14323
NULL, item,
14324
"The attribute wildcard is not a valid "
14325
"subset of the wildcard in the %s %s '%s'",
14326
WXS_ACTION_STR(action),
14327
WXS_ITEM_TYPE_NAME(baseItem),
14328
xmlSchemaGetComponentQName(&str, baseItem),
14329
NULL);
14330
FREE_AND_NULL(str);
14331
return(pctxt->err);
14332
}
14333
/* 4.3 Unless the {base type definition} is the `ur-type
14334
* definition`, the complex type definition's {attribute
14335
* wildcard}'s {process contents} must be identical to or
14336
* stronger than the {base type definition}'s {attribute
14337
* wildcard}'s {process contents}, where strict is stronger
14338
* than lax is stronger than skip.
14339
*/
14340
if ((! WXS_IS_ANYTYPE(baseItem)) &&
14341
(wild->processContents < baseWild->processContents)) {
14342
xmlChar *str = NULL;
14343
xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14344
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14345
NULL, baseItem,
14346
"The {process contents} of the attribute wildcard is "
14347
"weaker than the one in the %s %s '%s'",
14348
WXS_ACTION_STR(action),
14349
WXS_ITEM_TYPE_NAME(baseItem),
14350
xmlSchemaGetComponentQName(&str, baseItem),
14351
NULL);
14352
FREE_AND_NULL(str)
14353
return(pctxt->err);
14354
}
14355
}
14356
return(0);
14357
}
14358
14359
14360
static int
14361
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14362
xmlSchemaBasicItemPtr item,
14363
xmlSchemaWildcardPtr *completeWild,
14364
xmlSchemaItemListPtr list,
14365
xmlSchemaItemListPtr prohibs);
14366
/**
14367
* xmlSchemaFixupTypeAttributeUses:
14368
* @ctxt: the schema parser context
14369
* @type: the complex type definition
14370
*
14371
*
14372
* Builds the wildcard and the attribute uses on the given complex type.
14373
* Returns -1 if an internal error occurs, 0 otherwise.
14374
*
14375
* ATTENTION TODO: Experimentally this uses pointer comparisons for
14376
* strings, so recheck this if we start to hardcode some schemata, since
14377
* they might not be in the same dict.
14378
* NOTE: It is allowed to "extend" the xs:anyType type.
14379
*/
14380
static int
14381
xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14382
xmlSchemaTypePtr type)
14383
{
14384
xmlSchemaTypePtr baseType = NULL;
14385
xmlSchemaAttributeUsePtr use;
14386
xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14387
14388
if (type->baseType == NULL) {
14389
PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14390
"no base type");
14391
return (-1);
14392
}
14393
baseType = type->baseType;
14394
if (WXS_IS_TYPE_NOT_FIXED(baseType))
14395
if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14396
return(-1);
14397
14398
uses = type->attrUses;
14399
baseUses = baseType->attrUses;
14400
/*
14401
* Expand attribute group references. And build the 'complete'
14402
* wildcard, i.e. intersect multiple wildcards.
14403
* Move attribute prohibitions into a separate list.
14404
*/
14405
if (uses != NULL) {
14406
if (WXS_IS_RESTRICTION(type)) {
14407
/*
14408
* This one will transfer all attr. prohibitions
14409
* into pctxt->attrProhibs.
14410
*/
14411
if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14412
WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14413
pctxt->attrProhibs) == -1)
14414
{
14415
PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14416
"failed to expand attributes");
14417
return(-1);
14418
}
14419
if (pctxt->attrProhibs->nbItems != 0)
14420
prohibs = pctxt->attrProhibs;
14421
} else {
14422
if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14423
WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14424
NULL) == -1)
14425
{
14426
PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14427
"failed to expand attributes");
14428
return(-1);
14429
}
14430
}
14431
}
14432
/*
14433
* Inherit the attribute uses of the base type.
14434
*/
14435
if (baseUses != NULL) {
14436
int i, j;
14437
xmlSchemaAttributeUseProhibPtr pro;
14438
14439
if (WXS_IS_RESTRICTION(type)) {
14440
int usesCount;
14441
xmlSchemaAttributeUsePtr tmp;
14442
14443
if (uses != NULL)
14444
usesCount = uses->nbItems;
14445
else
14446
usesCount = 0;
14447
14448
/* Restriction. */
14449
for (i = 0; i < baseUses->nbItems; i++) {
14450
use = baseUses->items[i];
14451
if (prohibs) {
14452
/*
14453
* Filter out prohibited uses.
14454
*/
14455
for (j = 0; j < prohibs->nbItems; j++) {
14456
pro = prohibs->items[j];
14457
if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14458
(WXS_ATTRUSE_DECL_TNS(use) ==
14459
pro->targetNamespace))
14460
{
14461
goto inherit_next;
14462
}
14463
}
14464
}
14465
if (usesCount) {
14466
/*
14467
* Filter out existing uses.
14468
*/
14469
for (j = 0; j < usesCount; j++) {
14470
tmp = uses->items[j];
14471
if ((WXS_ATTRUSE_DECL_NAME(use) ==
14472
WXS_ATTRUSE_DECL_NAME(tmp)) &&
14473
(WXS_ATTRUSE_DECL_TNS(use) ==
14474
WXS_ATTRUSE_DECL_TNS(tmp)))
14475
{
14476
goto inherit_next;
14477
}
14478
}
14479
}
14480
if (uses == NULL) {
14481
type->attrUses = xmlSchemaItemListCreate();
14482
if (type->attrUses == NULL)
14483
goto exit_failure;
14484
uses = type->attrUses;
14485
}
14486
xmlSchemaItemListAddSize(uses, 2, use);
14487
inherit_next: {}
14488
}
14489
} else {
14490
/* Extension. */
14491
for (i = 0; i < baseUses->nbItems; i++) {
14492
use = baseUses->items[i];
14493
if (uses == NULL) {
14494
type->attrUses = xmlSchemaItemListCreate();
14495
if (type->attrUses == NULL)
14496
goto exit_failure;
14497
uses = type->attrUses;
14498
}
14499
xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14500
}
14501
}
14502
}
14503
/*
14504
* Shrink attr. uses.
14505
*/
14506
if (uses) {
14507
if (uses->nbItems == 0) {
14508
xmlSchemaItemListFree(uses);
14509
type->attrUses = NULL;
14510
}
14511
/*
14512
* TODO: We could shrink the size of the array
14513
* to fit the actual number of items.
14514
*/
14515
}
14516
/*
14517
* Compute the complete wildcard.
14518
*/
14519
if (WXS_IS_EXTENSION(type)) {
14520
if (baseType->attributeWildcard != NULL) {
14521
/*
14522
* (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14523
* the appropriate case among the following:"
14524
*/
14525
if (type->attributeWildcard != NULL) {
14526
/*
14527
* Union the complete wildcard with the base wildcard.
14528
* SPEC {attribute wildcard}
14529
* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14530
* and {annotation} are those of the `complete wildcard`,
14531
* and whose {namespace constraint} is the intensional union
14532
* of the {namespace constraint} of the `complete wildcard`
14533
* and of the `base wildcard`, as defined in Attribute
14534
* Wildcard Union ($3.10.6)."
14535
*/
14536
if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14537
baseType->attributeWildcard) == -1)
14538
goto exit_failure;
14539
} else {
14540
/*
14541
* (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14542
* then the `base wildcard`."
14543
*/
14544
type->attributeWildcard = baseType->attributeWildcard;
14545
}
14546
} else {
14547
/*
14548
* (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14549
* `complete wildcard`"
14550
* NOOP
14551
*/
14552
}
14553
} else {
14554
/*
14555
* SPEC {attribute wildcard}
14556
* (3.1) "If the <restriction> alternative is chosen, then the
14557
* `complete wildcard`;"
14558
* NOOP
14559
*/
14560
}
14561
14562
return (0);
14563
14564
exit_failure:
14565
return(-1);
14566
}
14567
14568
/**
14569
* xmlSchemaTypeFinalContains:
14570
* @schema: the schema
14571
* @type: the type definition
14572
* @final: the final
14573
*
14574
* Evaluates if a type definition contains the given "final".
14575
* This does take "finalDefault" into account as well.
14576
*
14577
* Returns 1 if the type does contain the given "final",
14578
* 0 otherwise.
14579
*/
14580
static int
14581
xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14582
{
14583
if (type == NULL)
14584
return (0);
14585
if (type->flags & final)
14586
return (1);
14587
else
14588
return (0);
14589
}
14590
14591
/**
14592
* xmlSchemaGetUnionSimpleTypeMemberTypes:
14593
* @type: the Union Simple Type
14594
*
14595
* Returns a list of member types of @type if existing,
14596
* returns NULL otherwise.
14597
*/
14598
static xmlSchemaTypeLinkPtr
14599
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14600
{
14601
while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14602
if (type->memberTypes != NULL)
14603
return (type->memberTypes);
14604
else
14605
type = type->baseType;
14606
}
14607
return (NULL);
14608
}
14609
14610
#if 0
14611
/**
14612
* xmlSchemaGetParticleTotalRangeMin:
14613
* @particle: the particle
14614
*
14615
* Schema Component Constraint: Effective Total Range
14616
* (all and sequence) + (choice)
14617
*
14618
* Returns the minimum Effective Total Range.
14619
*/
14620
static int
14621
xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14622
{
14623
if ((particle->children == NULL) ||
14624
(particle->minOccurs == 0))
14625
return (0);
14626
if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14627
int min = -1, cur;
14628
xmlSchemaParticlePtr part =
14629
(xmlSchemaParticlePtr) particle->children->children;
14630
14631
if (part == NULL)
14632
return (0);
14633
while (part != NULL) {
14634
if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14635
(part->children->type == XML_SCHEMA_TYPE_ANY))
14636
cur = part->minOccurs;
14637
else
14638
cur = xmlSchemaGetParticleTotalRangeMin(part);
14639
if (cur == 0)
14640
return (0);
14641
if ((min > cur) || (min == -1))
14642
min = cur;
14643
part = (xmlSchemaParticlePtr) part->next;
14644
}
14645
return (particle->minOccurs * min);
14646
} else {
14647
/* <all> and <sequence> */
14648
int sum = 0;
14649
xmlSchemaParticlePtr part =
14650
(xmlSchemaParticlePtr) particle->children->children;
14651
14652
if (part == NULL)
14653
return (0);
14654
do {
14655
if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14656
(part->children->type == XML_SCHEMA_TYPE_ANY))
14657
sum += part->minOccurs;
14658
else
14659
sum += xmlSchemaGetParticleTotalRangeMin(part);
14660
part = (xmlSchemaParticlePtr) part->next;
14661
} while (part != NULL);
14662
return (particle->minOccurs * sum);
14663
}
14664
}
14665
14666
/**
14667
* xmlSchemaGetParticleTotalRangeMax:
14668
* @particle: the particle
14669
*
14670
* Schema Component Constraint: Effective Total Range
14671
* (all and sequence) + (choice)
14672
*
14673
* Returns the maximum Effective Total Range.
14674
*/
14675
static int
14676
xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14677
{
14678
if ((particle->children == NULL) ||
14679
(particle->children->children == NULL))
14680
return (0);
14681
if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14682
int max = -1, cur;
14683
xmlSchemaParticlePtr part =
14684
(xmlSchemaParticlePtr) particle->children->children;
14685
14686
for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14687
if (part->children == NULL)
14688
continue;
14689
if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14690
(part->children->type == XML_SCHEMA_TYPE_ANY))
14691
cur = part->maxOccurs;
14692
else
14693
cur = xmlSchemaGetParticleTotalRangeMax(part);
14694
if (cur == UNBOUNDED)
14695
return (UNBOUNDED);
14696
if ((max < cur) || (max == -1))
14697
max = cur;
14698
}
14699
/* TODO: Handle overflows? */
14700
return (particle->maxOccurs * max);
14701
} else {
14702
/* <all> and <sequence> */
14703
int sum = 0, cur;
14704
xmlSchemaParticlePtr part =
14705
(xmlSchemaParticlePtr) particle->children->children;
14706
14707
for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14708
if (part->children == NULL)
14709
continue;
14710
if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14711
(part->children->type == XML_SCHEMA_TYPE_ANY))
14712
cur = part->maxOccurs;
14713
else
14714
cur = xmlSchemaGetParticleTotalRangeMax(part);
14715
if (cur == UNBOUNDED)
14716
return (UNBOUNDED);
14717
if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14718
return (UNBOUNDED);
14719
sum += cur;
14720
}
14721
/* TODO: Handle overflows? */
14722
return (particle->maxOccurs * sum);
14723
}
14724
}
14725
#endif
14726
14727
/**
14728
* xmlSchemaGetParticleEmptiable:
14729
* @particle: the particle
14730
*
14731
* Returns 1 if emptiable, 0 otherwise.
14732
*/
14733
static int
14734
xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
14735
{
14736
xmlSchemaParticlePtr part;
14737
int emptiable;
14738
14739
if ((particle->children == NULL) || (particle->minOccurs == 0))
14740
return (1);
14741
14742
part = (xmlSchemaParticlePtr) particle->children->children;
14743
if (part == NULL)
14744
return (1);
14745
14746
while (part != NULL) {
14747
if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14748
(part->children->type == XML_SCHEMA_TYPE_ANY))
14749
emptiable = (part->minOccurs == 0);
14750
else
14751
emptiable = xmlSchemaGetParticleEmptiable(part);
14752
if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14753
if (emptiable)
14754
return (1);
14755
} else {
14756
/* <all> and <sequence> */
14757
if (!emptiable)
14758
return (0);
14759
}
14760
part = (xmlSchemaParticlePtr) part->next;
14761
}
14762
14763
if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
14764
return (0);
14765
else
14766
return (1);
14767
}
14768
14769
/**
14770
* xmlSchemaIsParticleEmptiable:
14771
* @particle: the particle
14772
*
14773
* Schema Component Constraint: Particle Emptiable
14774
* Checks whether the given particle is emptiable.
14775
*
14776
* Returns 1 if emptiable, 0 otherwise.
14777
*/
14778
static int
14779
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14780
{
14781
/*
14782
* SPEC (1) "Its {min occurs} is 0."
14783
*/
14784
if ((particle == NULL) || (particle->minOccurs == 0) ||
14785
(particle->children == NULL))
14786
return (1);
14787
/*
14788
* SPEC (2) "Its {term} is a group and the minimum part of the
14789
* effective total range of that group, [...] is 0."
14790
*/
14791
if (WXS_IS_MODEL_GROUP(particle->children))
14792
return (xmlSchemaGetParticleEmptiable(particle));
14793
return (0);
14794
}
14795
14796
/**
14797
* xmlSchemaCheckCOSSTDerivedOK:
14798
* @actxt: a context
14799
* @type: the derived simple type definition
14800
* @baseType: the base type definition
14801
* @subset: the subset of ('restriction', etc.)
14802
*
14803
* Schema Component Constraint:
14804
* Type Derivation OK (Simple) (cos-st-derived-OK)
14805
*
14806
* Checks whether @type can be validly
14807
* derived from @baseType.
14808
*
14809
* Returns 0 on success, an positive error code otherwise.
14810
*/
14811
static int
14812
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14813
xmlSchemaTypePtr type,
14814
xmlSchemaTypePtr baseType,
14815
int subset)
14816
{
14817
/*
14818
* 1 They are the same type definition.
14819
* TODO: The identity check might have to be more complex than this.
14820
*/
14821
if (type == baseType)
14822
return (0);
14823
/*
14824
* 2.1 restriction is not in the subset, or in the {final}
14825
* of its own {base type definition};
14826
*
14827
* NOTE that this will be used also via "xsi:type".
14828
*
14829
* TODO: Revise this, it looks strange. How can the "type"
14830
* not be fixed or *in* fixing?
14831
*/
14832
if (WXS_IS_TYPE_NOT_FIXED(type))
14833
if (xmlSchemaTypeFixup(type, actxt) == -1)
14834
return(-1);
14835
if (WXS_IS_TYPE_NOT_FIXED(baseType))
14836
if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14837
return(-1);
14838
if ((subset & SUBSET_RESTRICTION) ||
14839
(xmlSchemaTypeFinalContains(type->baseType,
14840
XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14841
return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14842
}
14843
/* 2.2 */
14844
if (type->baseType == baseType) {
14845
/*
14846
* 2.2.1 D's `base type definition` is B.
14847
*/
14848
return (0);
14849
}
14850
/*
14851
* 2.2.2 D's `base type definition` is not the `ur-type definition`
14852
* and is validly derived from B given the subset, as defined by this
14853
* constraint.
14854
*/
14855
if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14856
(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14857
baseType, subset) == 0)) {
14858
return (0);
14859
}
14860
/*
14861
* 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14862
* definition`.
14863
*/
14864
if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14865
(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14866
return (0);
14867
}
14868
/*
14869
* 2.2.4 B's {variety} is union and D is validly derived from a type
14870
* definition in B's {member type definitions} given the subset, as
14871
* defined by this constraint.
14872
*
14873
* NOTE: This seems not to involve built-in types, since there is no
14874
* built-in Union Simple Type.
14875
*/
14876
if (WXS_IS_UNION(baseType)) {
14877
xmlSchemaTypeLinkPtr cur;
14878
14879
cur = baseType->memberTypes;
14880
while (cur != NULL) {
14881
if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14882
if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14883
return(-1);
14884
if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14885
type, cur->type, subset) == 0)
14886
{
14887
/*
14888
* It just has to be validly derived from at least one
14889
* member-type.
14890
*/
14891
return (0);
14892
}
14893
cur = cur->next;
14894
}
14895
}
14896
return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14897
}
14898
14899
/**
14900
* xmlSchemaCheckTypeDefCircularInternal:
14901
* @pctxt: the schema parser context
14902
* @ctxtType: the type definition
14903
* @ancestor: an ancestor of @ctxtType
14904
*
14905
* Checks st-props-correct (2) + ct-props-correct (3).
14906
* Circular type definitions are not allowed.
14907
*
14908
* Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14909
* circular, 0 otherwise.
14910
*/
14911
static int
14912
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14913
xmlSchemaTypePtr ctxtType,
14914
xmlSchemaTypePtr ancestor)
14915
{
14916
int ret;
14917
14918
if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14919
return (0);
14920
14921
if (ctxtType == ancestor) {
14922
xmlSchemaPCustomErr(pctxt,
14923
XML_SCHEMAP_ST_PROPS_CORRECT_2,
14924
WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14925
"The definition is circular", NULL);
14926
return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14927
}
14928
if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14929
/*
14930
* Avoid infinite recursion on circular types not yet checked.
14931
*/
14932
return (0);
14933
}
14934
ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14935
ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14936
ancestor->baseType);
14937
ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14938
return (ret);
14939
}
14940
14941
/**
14942
* xmlSchemaCheckTypeDefCircular:
14943
* @item: the complex/simple type definition
14944
* @ctxt: the parser context
14945
* @name: the name
14946
*
14947
* Checks for circular type definitions.
14948
*/
14949
static void
14950
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14951
xmlSchemaParserCtxtPtr ctxt)
14952
{
14953
if ((item == NULL) ||
14954
(item->type == XML_SCHEMA_TYPE_BASIC) ||
14955
(item->baseType == NULL))
14956
return;
14957
xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14958
item->baseType);
14959
}
14960
14961
/*
14962
* Simple Type Definition Representation OK (src-simple-type) 4
14963
*
14964
* "4 Circular union type definition is disallowed. That is, if the
14965
* <union> alternative is chosen, there must not be any entries in the
14966
* memberTypes [attribute] at any depth which resolve to the component
14967
* corresponding to the <simpleType>."
14968
*
14969
* Note that this should work on the *representation* of a component,
14970
* thus assumes any union types in the member types not being yet
14971
* substituted. At this stage we need the variety of the types
14972
* to be already computed.
14973
*/
14974
static int
14975
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14976
xmlSchemaTypePtr ctxType,
14977
xmlSchemaTypeLinkPtr members)
14978
{
14979
xmlSchemaTypeLinkPtr member;
14980
xmlSchemaTypePtr memberType;
14981
14982
member = members;
14983
while (member != NULL) {
14984
memberType = member->type;
14985
while ((memberType != NULL) &&
14986
(memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14987
if (memberType == ctxType) {
14988
xmlSchemaPCustomErr(pctxt,
14989
XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14990
WXS_BASIC_CAST ctxType, NULL,
14991
"The union type definition is circular", NULL);
14992
return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14993
}
14994
if ((WXS_IS_UNION(memberType)) &&
14995
((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14996
{
14997
int res;
14998
memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14999
res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15000
ctxType,
15001
xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15002
memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15003
if (res != 0)
15004
return(res);
15005
}
15006
memberType = memberType->baseType;
15007
}
15008
member = member->next;
15009
}
15010
return(0);
15011
}
15012
15013
static int
15014
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15015
xmlSchemaTypePtr type)
15016
{
15017
if (! WXS_IS_UNION(type))
15018
return(0);
15019
return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15020
type->memberTypes));
15021
}
15022
15023
/**
15024
* xmlSchemaResolveTypeReferences:
15025
* @item: the complex/simple type definition
15026
* @ctxt: the parser context
15027
* @name: the name
15028
*
15029
* Resolves type definition references
15030
*/
15031
static void
15032
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15033
xmlSchemaParserCtxtPtr ctxt)
15034
{
15035
if (typeDef == NULL)
15036
return;
15037
15038
/*
15039
* Resolve the base type.
15040
*/
15041
if (typeDef->baseType == NULL) {
15042
typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15043
typeDef->base, typeDef->baseNs);
15044
if (typeDef->baseType == NULL) {
15045
xmlSchemaPResCompAttrErr(ctxt,
15046
XML_SCHEMAP_SRC_RESOLVE,
15047
WXS_BASIC_CAST typeDef, typeDef->node,
15048
"base", typeDef->base, typeDef->baseNs,
15049
XML_SCHEMA_TYPE_SIMPLE, NULL);
15050
return;
15051
}
15052
}
15053
if (WXS_IS_SIMPLE(typeDef)) {
15054
if (WXS_IS_UNION(typeDef)) {
15055
/*
15056
* Resolve the memberTypes.
15057
*/
15058
xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15059
return;
15060
} else if (WXS_IS_LIST(typeDef)) {
15061
/*
15062
* Resolve the itemType.
15063
*/
15064
if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15065
15066
typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15067
typeDef->base, typeDef->baseNs);
15068
15069
if ((typeDef->subtypes == NULL) ||
15070
(! WXS_IS_SIMPLE(typeDef->subtypes)))
15071
{
15072
typeDef->subtypes = NULL;
15073
xmlSchemaPResCompAttrErr(ctxt,
15074
XML_SCHEMAP_SRC_RESOLVE,
15075
WXS_BASIC_CAST typeDef, typeDef->node,
15076
"itemType", typeDef->base, typeDef->baseNs,
15077
XML_SCHEMA_TYPE_SIMPLE, NULL);
15078
}
15079
}
15080
return;
15081
}
15082
}
15083
/*
15084
* The ball of letters below means, that if we have a particle
15085
* which has a QName-helper component as its {term}, we want
15086
* to resolve it...
15087
*/
15088
else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15089
((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15090
XML_SCHEMA_TYPE_PARTICLE) &&
15091
(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15092
((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15093
XML_SCHEMA_EXTRA_QNAMEREF))
15094
{
15095
xmlSchemaQNameRefPtr ref =
15096
WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15097
xmlSchemaModelGroupDefPtr groupDef;
15098
15099
/*
15100
* URGENT TODO: Test this.
15101
*/
15102
WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15103
/*
15104
* Resolve the MG definition reference.
15105
*/
15106
groupDef =
15107
WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15108
ref->itemType, ref->name, ref->targetNamespace);
15109
if (groupDef == NULL) {
15110
xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15111
NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15112
"ref", ref->name, ref->targetNamespace, ref->itemType,
15113
NULL);
15114
/* Remove the particle. */
15115
WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15116
} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15117
/* Remove the particle. */
15118
WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15119
else {
15120
/*
15121
* Assign the MG definition's {model group} to the
15122
* particle's {term}.
15123
*/
15124
WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15125
15126
if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15127
/*
15128
* SPEC cos-all-limited (1.2)
15129
* "1.2 the {term} property of a particle with
15130
* {max occurs}=1 which is part of a pair which constitutes
15131
* the {content type} of a complex type definition."
15132
*/
15133
if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15134
xmlSchemaCustomErr(ACTXT_CAST ctxt,
15135
/* TODO: error code */
15136
XML_SCHEMAP_COS_ALL_LIMITED,
15137
WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15138
"The particle's {max occurs} must be 1, since the "
15139
"reference resolves to an 'all' model group",
15140
NULL, NULL);
15141
}
15142
}
15143
}
15144
}
15145
}
15146
15147
15148
15149
/**
15150
* xmlSchemaCheckSTPropsCorrect:
15151
* @ctxt: the schema parser context
15152
* @type: the simple type definition
15153
*
15154
* Checks st-props-correct.
15155
*
15156
* Returns 0 if the properties are correct,
15157
* if not, a positive error code and -1 on internal
15158
* errors.
15159
*/
15160
static int
15161
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15162
xmlSchemaTypePtr type)
15163
{
15164
xmlSchemaTypePtr baseType = type->baseType;
15165
xmlChar *str = NULL;
15166
15167
/* STATE: error funcs converted. */
15168
/*
15169
* Schema Component Constraint: Simple Type Definition Properties Correct
15170
*
15171
* NOTE: This is somehow redundant, since we actually built a simple type
15172
* to have all the needed information; this acts as an self test.
15173
*/
15174
/* Base type: If the datatype has been `derived` by `restriction`
15175
* then the Simple Type Definition component from which it is `derived`,
15176
* otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15177
*/
15178
if (baseType == NULL) {
15179
/*
15180
* TODO: Think about: "modulo the impact of Missing
15181
* Sub-components ($5.3)."
15182
*/
15183
xmlSchemaPCustomErr(ctxt,
15184
XML_SCHEMAP_ST_PROPS_CORRECT_1,
15185
WXS_BASIC_CAST type, NULL,
15186
"No base type existent", NULL);
15187
return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15188
15189
}
15190
if (! WXS_IS_SIMPLE(baseType)) {
15191
xmlSchemaPCustomErr(ctxt,
15192
XML_SCHEMAP_ST_PROPS_CORRECT_1,
15193
WXS_BASIC_CAST type, NULL,
15194
"The base type '%s' is not a simple type",
15195
xmlSchemaGetComponentQName(&str, baseType));
15196
FREE_AND_NULL(str)
15197
return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15198
}
15199
if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15200
(WXS_IS_RESTRICTION(type) == 0) &&
15201
((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15202
(baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15203
xmlSchemaPCustomErr(ctxt,
15204
XML_SCHEMAP_ST_PROPS_CORRECT_1,
15205
WXS_BASIC_CAST type, NULL,
15206
"A type, derived by list or union, must have "
15207
"the simple ur-type definition as base type, not '%s'",
15208
xmlSchemaGetComponentQName(&str, baseType));
15209
FREE_AND_NULL(str)
15210
return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15211
}
15212
/*
15213
* Variety: One of {atomic, list, union}.
15214
*/
15215
if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15216
(! WXS_IS_LIST(type))) {
15217
xmlSchemaPCustomErr(ctxt,
15218
XML_SCHEMAP_ST_PROPS_CORRECT_1,
15219
WXS_BASIC_CAST type, NULL,
15220
"The variety is absent", NULL);
15221
return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15222
}
15223
/* TODO: Finish this. Hmm, is this finished? */
15224
15225
/*
15226
* 3 The {final} of the {base type definition} must not contain restriction.
15227
*/
15228
if (xmlSchemaTypeFinalContains(baseType,
15229
XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15230
xmlSchemaPCustomErr(ctxt,
15231
XML_SCHEMAP_ST_PROPS_CORRECT_3,
15232
WXS_BASIC_CAST type, NULL,
15233
"The 'final' of its base type '%s' must not contain "
15234
"'restriction'",
15235
xmlSchemaGetComponentQName(&str, baseType));
15236
FREE_AND_NULL(str)
15237
return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15238
}
15239
15240
/*
15241
* 2 All simple type definitions must be derived ultimately from the `simple
15242
* ur-type definition` (so circular definitions are disallowed). That is, it
15243
* must be possible to reach a built-in primitive datatype or the `simple
15244
* ur-type definition` by repeatedly following the {base type definition}.
15245
*
15246
* NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15247
*/
15248
return (0);
15249
}
15250
15251
/**
15252
* xmlSchemaCheckCOSSTRestricts:
15253
* @ctxt: the schema parser context
15254
* @type: the simple type definition
15255
*
15256
* Schema Component Constraint:
15257
* Derivation Valid (Restriction, Simple) (cos-st-restricts)
15258
15259
* Checks if the given @type (simpleType) is derived validly by restriction.
15260
* STATUS:
15261
*
15262
* Returns -1 on internal errors, 0 if the type is validly derived,
15263
* a positive error code otherwise.
15264
*/
15265
static int
15266
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15267
xmlSchemaTypePtr type)
15268
{
15269
xmlChar *str = NULL;
15270
15271
if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15272
PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15273
"given type is not a user-derived simpleType");
15274
return (-1);
15275
}
15276
15277
if (WXS_IS_ATOMIC(type)) {
15278
xmlSchemaTypePtr primitive;
15279
/*
15280
* 1.1 The {base type definition} must be an atomic simple
15281
* type definition or a built-in primitive datatype.
15282
*/
15283
if (! WXS_IS_ATOMIC(type->baseType)) {
15284
xmlSchemaPCustomErr(pctxt,
15285
XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15286
WXS_BASIC_CAST type, NULL,
15287
"The base type '%s' is not an atomic simple type",
15288
xmlSchemaGetComponentQName(&str, type->baseType));
15289
FREE_AND_NULL(str)
15290
return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15291
}
15292
/* 1.2 The {final} of the {base type definition} must not contain
15293
* restriction.
15294
*/
15295
/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15296
if (xmlSchemaTypeFinalContains(type->baseType,
15297
XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15298
xmlSchemaPCustomErr(pctxt,
15299
XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15300
WXS_BASIC_CAST type, NULL,
15301
"The final of its base type '%s' must not contain 'restriction'",
15302
xmlSchemaGetComponentQName(&str, type->baseType));
15303
FREE_AND_NULL(str)
15304
return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15305
}
15306
15307
/*
15308
* 1.3.1 DF must be an allowed constraining facet for the {primitive
15309
* type definition}, as specified in the appropriate subsection of 3.2
15310
* Primitive datatypes.
15311
*/
15312
if (type->facets != NULL) {
15313
xmlSchemaFacetPtr facet;
15314
int ok = 1;
15315
15316
primitive = xmlSchemaGetPrimitiveType(type);
15317
if (primitive == NULL) {
15318
PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15319
"failed to get primitive type");
15320
return (-1);
15321
}
15322
facet = type->facets;
15323
do {
15324
if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15325
ok = 0;
15326
xmlSchemaPIllegalFacetAtomicErr(pctxt,
15327
XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15328
type, primitive, facet);
15329
}
15330
facet = facet->next;
15331
} while (facet != NULL);
15332
if (ok == 0)
15333
return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15334
}
15335
/*
15336
* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15337
* of the {base type definition} (call this BF),then the DF's {value}
15338
* must be a valid restriction of BF's {value} as defined in
15339
* [XML Schemas: Datatypes]."
15340
*
15341
* NOTE (1.3.2) Facet derivation constraints are currently handled in
15342
* xmlSchemaDeriveAndValidateFacets()
15343
*/
15344
} else if (WXS_IS_LIST(type)) {
15345
xmlSchemaTypePtr itemType = NULL;
15346
15347
itemType = type->subtypes;
15348
if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15349
PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15350
"failed to evaluate the item type");
15351
return (-1);
15352
}
15353
if (WXS_IS_TYPE_NOT_FIXED(itemType))
15354
xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15355
/*
15356
* 2.1 The {item type definition} must have a {variety} of atomic or
15357
* union (in which case all the {member type definitions}
15358
* must be atomic).
15359
*/
15360
if ((! WXS_IS_ATOMIC(itemType)) &&
15361
(! WXS_IS_UNION(itemType))) {
15362
xmlSchemaPCustomErr(pctxt,
15363
XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15364
WXS_BASIC_CAST type, NULL,
15365
"The item type '%s' does not have a variety of atomic or union",
15366
xmlSchemaGetComponentQName(&str, itemType));
15367
FREE_AND_NULL(str)
15368
return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15369
} else if (WXS_IS_UNION(itemType)) {
15370
xmlSchemaTypeLinkPtr member;
15371
15372
member = itemType->memberTypes;
15373
while (member != NULL) {
15374
if (! WXS_IS_ATOMIC(member->type)) {
15375
xmlSchemaPCustomErr(pctxt,
15376
XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15377
WXS_BASIC_CAST type, NULL,
15378
"The item type is a union type, but the "
15379
"member type '%s' of this item type is not atomic",
15380
xmlSchemaGetComponentQName(&str, member->type));
15381
FREE_AND_NULL(str)
15382
return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15383
}
15384
member = member->next;
15385
}
15386
}
15387
15388
if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15389
xmlSchemaFacetPtr facet;
15390
/*
15391
* This is the case if we have: <simpleType><list ..
15392
*/
15393
/*
15394
* 2.3.1
15395
* 2.3.1.1 The {final} of the {item type definition} must not
15396
* contain list.
15397
*/
15398
if (xmlSchemaTypeFinalContains(itemType,
15399
XML_SCHEMAS_TYPE_FINAL_LIST)) {
15400
xmlSchemaPCustomErr(pctxt,
15401
XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15402
WXS_BASIC_CAST type, NULL,
15403
"The final of its item type '%s' must not contain 'list'",
15404
xmlSchemaGetComponentQName(&str, itemType));
15405
FREE_AND_NULL(str)
15406
return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15407
}
15408
/*
15409
* 2.3.1.2 The {facets} must only contain the whiteSpace
15410
* facet component.
15411
* OPTIMIZE TODO: the S4S already disallows any facet
15412
* to be specified.
15413
*/
15414
if (type->facets != NULL) {
15415
facet = type->facets;
15416
do {
15417
if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15418
xmlSchemaPIllegalFacetListUnionErr(pctxt,
15419
XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15420
type, facet);
15421
return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15422
}
15423
facet = facet->next;
15424
} while (facet != NULL);
15425
}
15426
/*
15427
* MAYBE TODO: (Hmm, not really) Datatypes states:
15428
* A `list` datatype can be `derived` from an `atomic` datatype
15429
* whose `lexical space` allows space (such as string or anyURI)or
15430
* a `union` datatype any of whose {member type definitions}'s
15431
* `lexical space` allows space.
15432
*/
15433
} else {
15434
/*
15435
* This is the case if we have: <simpleType><restriction ...
15436
* I.e. the variety of "list" is inherited.
15437
*/
15438
/*
15439
* 2.3.2
15440
* 2.3.2.1 The {base type definition} must have a {variety} of list.
15441
*/
15442
if (! WXS_IS_LIST(type->baseType)) {
15443
xmlSchemaPCustomErr(pctxt,
15444
XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15445
WXS_BASIC_CAST type, NULL,
15446
"The base type '%s' must be a list type",
15447
xmlSchemaGetComponentQName(&str, type->baseType));
15448
FREE_AND_NULL(str)
15449
return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15450
}
15451
/*
15452
* 2.3.2.2 The {final} of the {base type definition} must not
15453
* contain restriction.
15454
*/
15455
if (xmlSchemaTypeFinalContains(type->baseType,
15456
XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15457
xmlSchemaPCustomErr(pctxt,
15458
XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15459
WXS_BASIC_CAST type, NULL,
15460
"The 'final' of the base type '%s' must not contain 'restriction'",
15461
xmlSchemaGetComponentQName(&str, type->baseType));
15462
FREE_AND_NULL(str)
15463
return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15464
}
15465
/*
15466
* 2.3.2.3 The {item type definition} must be validly derived
15467
* from the {base type definition}'s {item type definition} given
15468
* the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15469
*/
15470
{
15471
xmlSchemaTypePtr baseItemType;
15472
15473
baseItemType = type->baseType->subtypes;
15474
if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15475
PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15476
"failed to eval the item type of a base type");
15477
return (-1);
15478
}
15479
if ((itemType != baseItemType) &&
15480
(xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15481
baseItemType, 0) != 0)) {
15482
xmlChar *strBIT = NULL, *strBT = NULL;
15483
xmlSchemaPCustomErrExt(pctxt,
15484
XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15485
WXS_BASIC_CAST type, NULL,
15486
"The item type '%s' is not validly derived from "
15487
"the item type '%s' of the base type '%s'",
15488
xmlSchemaGetComponentQName(&str, itemType),
15489
xmlSchemaGetComponentQName(&strBIT, baseItemType),
15490
xmlSchemaGetComponentQName(&strBT, type->baseType));
15491
15492
FREE_AND_NULL(str)
15493
FREE_AND_NULL(strBIT)
15494
FREE_AND_NULL(strBT)
15495
return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15496
}
15497
}
15498
15499
if (type->facets != NULL) {
15500
xmlSchemaFacetPtr facet;
15501
int ok = 1;
15502
/*
15503
* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15504
* and enumeration facet components are allowed among the {facets}.
15505
*/
15506
facet = type->facets;
15507
do {
15508
switch (facet->type) {
15509
case XML_SCHEMA_FACET_LENGTH:
15510
case XML_SCHEMA_FACET_MINLENGTH:
15511
case XML_SCHEMA_FACET_MAXLENGTH:
15512
case XML_SCHEMA_FACET_WHITESPACE:
15513
/*
15514
* TODO: 2.5.1.2 List datatypes
15515
* The value of `whiteSpace` is fixed to the value collapse.
15516
*/
15517
case XML_SCHEMA_FACET_PATTERN:
15518
case XML_SCHEMA_FACET_ENUMERATION:
15519
break;
15520
default: {
15521
xmlSchemaPIllegalFacetListUnionErr(pctxt,
15522
XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15523
type, facet);
15524
/*
15525
* We could return, but it's nicer to report all
15526
* invalid facets.
15527
*/
15528
ok = 0;
15529
}
15530
}
15531
facet = facet->next;
15532
} while (facet != NULL);
15533
if (ok == 0)
15534
return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15535
/*
15536
* SPEC (2.3.2.5) (same as 1.3.2)
15537
*
15538
* NOTE (2.3.2.5) This is currently done in
15539
* xmlSchemaDeriveAndValidateFacets()
15540
*/
15541
}
15542
}
15543
} else if (WXS_IS_UNION(type)) {
15544
/*
15545
* 3.1 The {member type definitions} must all have {variety} of
15546
* atomic or list.
15547
*/
15548
xmlSchemaTypeLinkPtr member;
15549
15550
member = type->memberTypes;
15551
while (member != NULL) {
15552
if (WXS_IS_TYPE_NOT_FIXED(member->type))
15553
xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15554
15555
if ((! WXS_IS_ATOMIC(member->type)) &&
15556
(! WXS_IS_LIST(member->type))) {
15557
xmlSchemaPCustomErr(pctxt,
15558
XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15559
WXS_BASIC_CAST type, NULL,
15560
"The member type '%s' is neither an atomic, nor a list type",
15561
xmlSchemaGetComponentQName(&str, member->type));
15562
FREE_AND_NULL(str)
15563
return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15564
}
15565
member = member->next;
15566
}
15567
/*
15568
* 3.3.1 If the {base type definition} is the `simple ur-type
15569
* definition`
15570
*/
15571
if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15572
/*
15573
* 3.3.1.1 All of the {member type definitions} must have a
15574
* {final} which does not contain union.
15575
*/
15576
member = type->memberTypes;
15577
while (member != NULL) {
15578
if (xmlSchemaTypeFinalContains(member->type,
15579
XML_SCHEMAS_TYPE_FINAL_UNION)) {
15580
xmlSchemaPCustomErr(pctxt,
15581
XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15582
WXS_BASIC_CAST type, NULL,
15583
"The 'final' of member type '%s' contains 'union'",
15584
xmlSchemaGetComponentQName(&str, member->type));
15585
FREE_AND_NULL(str)
15586
return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15587
}
15588
member = member->next;
15589
}
15590
/*
15591
* 3.3.1.2 The {facets} must be empty.
15592
*/
15593
if (type->facetSet != NULL) {
15594
xmlSchemaPCustomErr(pctxt,
15595
XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15596
WXS_BASIC_CAST type, NULL,
15597
"No facets allowed", NULL);
15598
return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15599
}
15600
} else {
15601
/*
15602
* 3.3.2.1 The {base type definition} must have a {variety} of union.
15603
* I.e. the variety of "list" is inherited.
15604
*/
15605
if (! WXS_IS_UNION(type->baseType)) {
15606
xmlSchemaPCustomErr(pctxt,
15607
XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15608
WXS_BASIC_CAST type, NULL,
15609
"The base type '%s' is not a union type",
15610
xmlSchemaGetComponentQName(&str, type->baseType));
15611
FREE_AND_NULL(str)
15612
return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15613
}
15614
/*
15615
* 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15616
*/
15617
if (xmlSchemaTypeFinalContains(type->baseType,
15618
XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15619
xmlSchemaPCustomErr(pctxt,
15620
XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15621
WXS_BASIC_CAST type, NULL,
15622
"The 'final' of its base type '%s' must not contain 'restriction'",
15623
xmlSchemaGetComponentQName(&str, type->baseType));
15624
FREE_AND_NULL(str)
15625
return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15626
}
15627
/*
15628
* 3.3.2.3 The {member type definitions}, in order, must be validly
15629
* derived from the corresponding type definitions in the {base
15630
* type definition}'s {member type definitions} given the empty set,
15631
* as defined in Type Derivation OK (Simple) ($3.14.6).
15632
*/
15633
{
15634
xmlSchemaTypeLinkPtr baseMember;
15635
15636
/*
15637
* OPTIMIZE: if the type is restricting, it has no local defined
15638
* member types and inherits the member types of the base type;
15639
* thus a check for equality can be skipped.
15640
*/
15641
/*
15642
* Even worse: I cannot see a scenario where a restricting
15643
* union simple type can have other member types as the member
15644
* types of it's base type. This check seems not necessary with
15645
* respect to the derivation process in libxml2.
15646
* But necessary if constructing types with an API.
15647
*/
15648
if (type->memberTypes != NULL) {
15649
member = type->memberTypes;
15650
baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15651
if ((member == NULL) && (baseMember != NULL)) {
15652
PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15653
"different number of member types in base");
15654
}
15655
while (member != NULL) {
15656
if (baseMember == NULL) {
15657
PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15658
"different number of member types in base");
15659
} else if ((member->type != baseMember->type) &&
15660
(xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15661
member->type, baseMember->type, 0) != 0)) {
15662
xmlChar *strBMT = NULL, *strBT = NULL;
15663
15664
xmlSchemaPCustomErrExt(pctxt,
15665
XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15666
WXS_BASIC_CAST type, NULL,
15667
"The member type %s is not validly "
15668
"derived from its corresponding member "
15669
"type %s of the base type %s",
15670
xmlSchemaGetComponentQName(&str, member->type),
15671
xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15672
xmlSchemaGetComponentQName(&strBT, type->baseType));
15673
FREE_AND_NULL(str)
15674
FREE_AND_NULL(strBMT)
15675
FREE_AND_NULL(strBT)
15676
return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15677
}
15678
member = member->next;
15679
if (baseMember != NULL)
15680
baseMember = baseMember->next;
15681
}
15682
}
15683
}
15684
/*
15685
* 3.3.2.4 Only pattern and enumeration facet components are
15686
* allowed among the {facets}.
15687
*/
15688
if (type->facets != NULL) {
15689
xmlSchemaFacetPtr facet;
15690
int ok = 1;
15691
15692
facet = type->facets;
15693
do {
15694
if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15695
(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15696
xmlSchemaPIllegalFacetListUnionErr(pctxt,
15697
XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15698
type, facet);
15699
ok = 0;
15700
}
15701
facet = facet->next;
15702
} while (facet != NULL);
15703
if (ok == 0)
15704
return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15705
15706
}
15707
/*
15708
* SPEC (3.3.2.5) (same as 1.3.2)
15709
*
15710
* NOTE (3.3.2.5) This is currently done in
15711
* xmlSchemaDeriveAndValidateFacets()
15712
*/
15713
}
15714
}
15715
15716
return (0);
15717
}
15718
15719
/**
15720
* xmlSchemaCheckSRCSimpleType:
15721
* @ctxt: the schema parser context
15722
* @type: the simple type definition
15723
*
15724
* Checks crc-simple-type constraints.
15725
*
15726
* Returns 0 if the constraints are satisfied,
15727
* if not a positive error code and -1 on internal
15728
* errors.
15729
*/
15730
#if 0
15731
static int
15732
xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15733
xmlSchemaTypePtr type)
15734
{
15735
/*
15736
* src-simple-type.1 The corresponding simple type definition, if any,
15737
* must satisfy the conditions set out in Constraints on Simple Type
15738
* Definition Schema Components ($3.14.6).
15739
*/
15740
if (WXS_IS_RESTRICTION(type)) {
15741
/*
15742
* src-simple-type.2 "If the <restriction> alternative is chosen,
15743
* either it must have a base [attribute] or a <simpleType> among its
15744
* [children], but not both."
15745
* NOTE: This is checked in the parse function of <restriction>.
15746
*/
15747
/*
15748
*
15749
*/
15750
} else if (WXS_IS_LIST(type)) {
15751
/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15752
* an itemType [attribute] or a <simpleType> among its [children],
15753
* but not both."
15754
*
15755
* NOTE: This is checked in the parse function of <list>.
15756
*/
15757
} else if (WXS_IS_UNION(type)) {
15758
/*
15759
* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15760
*/
15761
}
15762
return (0);
15763
}
15764
#endif
15765
15766
static int
15767
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15768
{
15769
if (ctxt->vctxt == NULL) {
15770
ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15771
if (ctxt->vctxt == NULL) {
15772
xmlSchemaPErr(ctxt, NULL,
15773
XML_SCHEMAP_INTERNAL,
15774
"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15775
"failed to create a temp. validation context.\n",
15776
NULL, NULL);
15777
return (-1);
15778
}
15779
/* TODO: Pass user data. */
15780
xmlSchemaSetValidErrors(ctxt->vctxt,
15781
ctxt->error, ctxt->warning, ctxt->errCtxt);
15782
xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15783
ctxt->serror, ctxt->errCtxt);
15784
}
15785
return (0);
15786
}
15787
15788
static int
15789
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15790
xmlNodePtr node,
15791
xmlSchemaTypePtr type,
15792
const xmlChar *value,
15793
xmlSchemaValPtr *retVal,
15794
int fireErrors,
15795
int normalize,
15796
int isNormalized);
15797
15798
/**
15799
* xmlSchemaParseCheckCOSValidDefault:
15800
* @pctxt: the schema parser context
15801
* @type: the simple type definition
15802
* @value: the default value
15803
* @node: an optional node (the holder of the value)
15804
*
15805
* Schema Component Constraint: Element Default Valid (Immediate)
15806
* (cos-valid-default)
15807
* This will be used by the parser only. For the validator there's
15808
* an other version.
15809
*
15810
* Returns 0 if the constraints are satisfied,
15811
* if not, a positive error code and -1 on internal
15812
* errors.
15813
*/
15814
static int
15815
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15816
xmlNodePtr node,
15817
xmlSchemaTypePtr type,
15818
const xmlChar *value,
15819
xmlSchemaValPtr *val)
15820
{
15821
int ret = 0;
15822
15823
/*
15824
* cos-valid-default:
15825
* Schema Component Constraint: Element Default Valid (Immediate)
15826
* For a string to be a valid default with respect to a type
15827
* definition the appropriate case among the following must be true:
15828
*/
15829
if WXS_IS_COMPLEX(type) {
15830
/*
15831
* Complex type.
15832
*
15833
* SPEC (2.1) "its {content type} must be a simple type definition
15834
* or mixed."
15835
* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15836
* type}'s particle must be `emptiable` as defined by
15837
* Particle Emptiable ($3.9.6)."
15838
*/
15839
if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15840
((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15841
/* NOTE that this covers (2.2.2) as well. */
15842
xmlSchemaPCustomErr(pctxt,
15843
XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15844
WXS_BASIC_CAST type, type->node,
15845
"For a string to be a valid default, the type definition "
15846
"must be a simple type or a complex type with mixed content "
15847
"and a particle emptiable", NULL);
15848
return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15849
}
15850
}
15851
/*
15852
* 1 If the type definition is a simple type definition, then the string
15853
* must be `valid` with respect to that definition as defined by String
15854
* Valid ($3.14.4).
15855
*
15856
* AND
15857
*
15858
* 2.2.1 If the {content type} is a simple type definition, then the
15859
* string must be `valid` with respect to that simple type definition
15860
* as defined by String Valid ($3.14.4).
15861
*/
15862
if (WXS_IS_SIMPLE(type))
15863
ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15864
type, value, val, 1, 1, 0);
15865
else if (WXS_HAS_SIMPLE_CONTENT(type))
15866
ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15867
type->contentTypeDef, value, val, 1, 1, 0);
15868
else
15869
return (ret);
15870
15871
if (ret < 0) {
15872
PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15873
"calling xmlSchemaVCheckCVCSimpleType()");
15874
}
15875
15876
return (ret);
15877
}
15878
15879
/**
15880
* xmlSchemaCheckCTPropsCorrect:
15881
* @ctxt: the schema parser context
15882
* @type: the complex type definition
15883
*
15884
*.(4.6) Constraints on Complex Type Definition Schema Components
15885
* Schema Component Constraint:
15886
* Complex Type Definition Properties Correct (ct-props-correct)
15887
* STATUS: (seems) complete
15888
*
15889
* Returns 0 if the constraints are satisfied, a positive
15890
* error code if not and -1 if an internal error occurred.
15891
*/
15892
static int
15893
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15894
xmlSchemaTypePtr type)
15895
{
15896
/*
15897
* TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15898
*
15899
* SPEC (1) "The values of the properties of a complex type definition must
15900
* be as described in the property tableau in The Complex Type Definition
15901
* Schema Component ($3.4.1), modulo the impact of Missing
15902
* Sub-components ($5.3)."
15903
*/
15904
if ((type->baseType != NULL) &&
15905
(WXS_IS_SIMPLE(type->baseType)) &&
15906
(WXS_IS_EXTENSION(type) == 0)) {
15907
/*
15908
* SPEC (2) "If the {base type definition} is a simple type definition,
15909
* the {derivation method} must be extension."
15910
*/
15911
xmlSchemaCustomErr(ACTXT_CAST pctxt,
15912
XML_SCHEMAP_SRC_CT_1,
15913
NULL, WXS_BASIC_CAST type,
15914
"If the base type is a simple type, the derivation method must be "
15915
"'extension'", NULL, NULL);
15916
return (XML_SCHEMAP_SRC_CT_1);
15917
}
15918
/*
15919
* SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15920
* definition`. That is, it must be possible to reach the `ur-type
15921
* definition` by repeatedly following the {base type definition}."
15922
*
15923
* NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15924
*/
15925
/*
15926
* NOTE that (4) and (5) need the following:
15927
* - attribute uses need to be already inherited (apply attr. prohibitions)
15928
* - attribute group references need to be expanded already
15929
* - simple types need to be typefixed already
15930
*/
15931
if (type->attrUses &&
15932
(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15933
{
15934
xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15935
xmlSchemaAttributeUsePtr use, tmp;
15936
int i, j, hasId = 0;
15937
15938
for (i = uses->nbItems -1; i >= 0; i--) {
15939
use = uses->items[i];
15940
15941
/*
15942
* SPEC ct-props-correct
15943
* (4) "Two distinct attribute declarations in the
15944
* {attribute uses} must not have identical {name}s and
15945
* {target namespace}s."
15946
*/
15947
if (i > 0) {
15948
for (j = i -1; j >= 0; j--) {
15949
tmp = uses->items[j];
15950
if ((WXS_ATTRUSE_DECL_NAME(use) ==
15951
WXS_ATTRUSE_DECL_NAME(tmp)) &&
15952
(WXS_ATTRUSE_DECL_TNS(use) ==
15953
WXS_ATTRUSE_DECL_TNS(tmp)))
15954
{
15955
xmlChar *str = NULL;
15956
15957
xmlSchemaCustomErr(ACTXT_CAST pctxt,
15958
XML_SCHEMAP_AG_PROPS_CORRECT,
15959
NULL, WXS_BASIC_CAST type,
15960
"Duplicate %s",
15961
xmlSchemaGetComponentDesignation(&str, use),
15962
NULL);
15963
FREE_AND_NULL(str);
15964
/*
15965
* Remove the duplicate.
15966
*/
15967
if (xmlSchemaItemListRemove(uses, i) == -1)
15968
goto exit_failure;
15969
goto next_use;
15970
}
15971
}
15972
}
15973
/*
15974
* SPEC ct-props-correct
15975
* (5) "Two distinct attribute declarations in the
15976
* {attribute uses} must not have {type definition}s which
15977
* are or are derived from ID."
15978
*/
15979
if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15980
if (xmlSchemaIsDerivedFromBuiltInType(
15981
WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15982
{
15983
if (hasId) {
15984
xmlChar *str = NULL;
15985
15986
xmlSchemaCustomErr(ACTXT_CAST pctxt,
15987
XML_SCHEMAP_AG_PROPS_CORRECT,
15988
NULL, WXS_BASIC_CAST type,
15989
"There must not exist more than one attribute "
15990
"declaration of type 'xs:ID' "
15991
"(or derived from 'xs:ID'). The %s violates this "
15992
"constraint",
15993
xmlSchemaGetComponentDesignation(&str, use),
15994
NULL);
15995
FREE_AND_NULL(str);
15996
if (xmlSchemaItemListRemove(uses, i) == -1)
15997
goto exit_failure;
15998
}
15999
16000
hasId = 1;
16001
}
16002
}
16003
next_use: {}
16004
}
16005
}
16006
return (0);
16007
exit_failure:
16008
return(-1);
16009
}
16010
16011
static int
16012
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16013
xmlSchemaTypePtr typeB)
16014
{
16015
/*
16016
* TODO: This should implement component-identity
16017
* in the future.
16018
*/
16019
if ((typeA == NULL) || (typeB == NULL))
16020
return (0);
16021
return (typeA == typeB);
16022
}
16023
16024
/**
16025
* xmlSchemaCheckCOSCTDerivedOK:
16026
* @ctxt: the schema parser context
16027
* @type: the to-be derived complex type definition
16028
* @baseType: the base complex type definition
16029
* @set: the given set
16030
*
16031
* Schema Component Constraint:
16032
* Type Derivation OK (Complex) (cos-ct-derived-ok)
16033
*
16034
* STATUS: completed
16035
*
16036
* Returns 0 if the constraints are satisfied, or 1
16037
* if not.
16038
*/
16039
static int
16040
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16041
xmlSchemaTypePtr type,
16042
xmlSchemaTypePtr baseType,
16043
int set)
16044
{
16045
int equal = xmlSchemaAreEqualTypes(type, baseType);
16046
/* TODO: Error codes. */
16047
/*
16048
* SPEC "For a complex type definition (call it D, for derived)
16049
* to be validly derived from a type definition (call this
16050
* B, for base) given a subset of {extension, restriction}
16051
* all of the following must be true:"
16052
*/
16053
if (! equal) {
16054
/*
16055
* SPEC (1) "If B and D are not the same type definition, then the
16056
* {derivation method} of D must not be in the subset."
16057
*/
16058
if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16059
((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16060
return (1);
16061
} else {
16062
/*
16063
* SPEC (2.1) "B and D must be the same type definition."
16064
*/
16065
return (0);
16066
}
16067
/*
16068
* SPEC (2.2) "B must be D's {base type definition}."
16069
*/
16070
if (type->baseType == baseType)
16071
return (0);
16072
/*
16073
* SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16074
* definition`."
16075
*/
16076
if (WXS_IS_ANYTYPE(type->baseType))
16077
return (1);
16078
16079
if (WXS_IS_COMPLEX(type->baseType)) {
16080
/*
16081
* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16082
* must be validly derived from B given the subset as defined by this
16083
* constraint."
16084
*/
16085
return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16086
baseType, set));
16087
} else {
16088
/*
16089
* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16090
* must be validly derived from B given the subset as defined in Type
16091
* Derivation OK (Simple) ($3.14.6).
16092
*/
16093
return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16094
baseType, set));
16095
}
16096
}
16097
16098
/**
16099
* xmlSchemaCheckCOSDerivedOK:
16100
* @type: the derived simple type definition
16101
* @baseType: the base type definition
16102
*
16103
* Calls:
16104
* Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16105
*
16106
* Checks whether @type can be validly derived from @baseType.
16107
*
16108
* Returns 0 on success, an positive error code otherwise.
16109
*/
16110
static int
16111
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16112
xmlSchemaTypePtr type,
16113
xmlSchemaTypePtr baseType,
16114
int set)
16115
{
16116
if (WXS_IS_SIMPLE(type))
16117
return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16118
else
16119
return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16120
}
16121
16122
/**
16123
* xmlSchemaCheckCOSCTExtends:
16124
* @ctxt: the schema parser context
16125
* @type: the complex type definition
16126
*
16127
* (3.4.6) Constraints on Complex Type Definition Schema Components
16128
* Schema Component Constraint:
16129
* Derivation Valid (Extension) (cos-ct-extends)
16130
*
16131
* STATUS:
16132
* missing:
16133
* (1.5)
16134
* (1.4.3.2.2.2) "Particle Valid (Extension)"
16135
*
16136
* Returns 0 if the constraints are satisfied, a positive
16137
* error code if not and -1 if an internal error occurred.
16138
*/
16139
static int
16140
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16141
xmlSchemaTypePtr type)
16142
{
16143
xmlSchemaTypePtr base = type->baseType;
16144
/*
16145
* TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16146
* temporarily only.
16147
*/
16148
/*
16149
* SPEC (1) "If the {base type definition} is a complex type definition,
16150
* then all of the following must be true:"
16151
*/
16152
if (WXS_IS_COMPLEX(base)) {
16153
/*
16154
* SPEC (1.1) "The {final} of the {base type definition} must not
16155
* contain extension."
16156
*/
16157
if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16158
xmlSchemaPCustomErr(ctxt,
16159
XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16160
WXS_BASIC_CAST type, NULL,
16161
"The 'final' of the base type definition "
16162
"contains 'extension'", NULL);
16163
return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16164
}
16165
16166
/*
16167
* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16168
* since they are automatically satisfied through the
16169
* inheriting mechanism.
16170
* Note that even if redefining components, the inheriting mechanism
16171
* is used.
16172
*/
16173
#if 0
16174
/*
16175
* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16176
* uses}
16177
* of the complex type definition itself, that is, for every attribute
16178
* use in the {attribute uses} of the {base type definition}, there
16179
* must be an attribute use in the {attribute uses} of the complex
16180
* type definition itself whose {attribute declaration} has the same
16181
* {name}, {target namespace} and {type definition} as its attribute
16182
* declaration"
16183
*/
16184
if (base->attrUses != NULL) {
16185
int i, j, found;
16186
xmlSchemaAttributeUsePtr use, buse;
16187
16188
for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16189
buse = (WXS_LIST_CAST base->attrUses)->items[i];
16190
found = 0;
16191
if (type->attrUses != NULL) {
16192
use = (WXS_LIST_CAST type->attrUses)->items[j];
16193
for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16194
{
16195
if ((WXS_ATTRUSE_DECL_NAME(use) ==
16196
WXS_ATTRUSE_DECL_NAME(buse)) &&
16197
(WXS_ATTRUSE_DECL_TNS(use) ==
16198
WXS_ATTRUSE_DECL_TNS(buse)) &&
16199
(WXS_ATTRUSE_TYPEDEF(use) ==
16200
WXS_ATTRUSE_TYPEDEF(buse))
16201
{
16202
found = 1;
16203
break;
16204
}
16205
}
16206
}
16207
if (! found) {
16208
xmlChar *str = NULL;
16209
16210
xmlSchemaCustomErr(ACTXT_CAST ctxt,
16211
XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16212
NULL, WXS_BASIC_CAST type,
16213
/*
16214
* TODO: The report does not indicate that also the
16215
* type needs to be the same.
16216
*/
16217
"This type is missing a matching correspondent "
16218
"for its {base type}'s %s in its {attribute uses}",
16219
xmlSchemaGetComponentDesignation(&str,
16220
buse->children),
16221
NULL);
16222
FREE_AND_NULL(str)
16223
}
16224
}
16225
}
16226
/*
16227
* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16228
* definition must also have one, and the base type definition's
16229
* {attribute wildcard}'s {namespace constraint} must be a subset
16230
* of the complex type definition's {attribute wildcard}'s {namespace
16231
* constraint}, as defined by Wildcard Subset ($3.10.6)."
16232
*/
16233
16234
/*
16235
* MAYBE TODO: Enable if ever needed. But this will be needed only
16236
* if created the type via a schema construction API.
16237
*/
16238
if (base->attributeWildcard != NULL) {
16239
if (type->attributeWildcard == NULL) {
16240
xmlChar *str = NULL;
16241
16242
xmlSchemaCustomErr(ACTXT_CAST pctxt,
16243
XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16244
NULL, type,
16245
"The base %s has an attribute wildcard, "
16246
"but this type is missing an attribute wildcard",
16247
xmlSchemaGetComponentDesignation(&str, base));
16248
FREE_AND_NULL(str)
16249
16250
} else if (xmlSchemaCheckCOSNSSubset(
16251
base->attributeWildcard, type->attributeWildcard))
16252
{
16253
xmlChar *str = NULL;
16254
16255
xmlSchemaCustomErr(ACTXT_CAST pctxt,
16256
XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16257
NULL, type,
16258
"The attribute wildcard is not a valid "
16259
"superset of the one in the base %s",
16260
xmlSchemaGetComponentDesignation(&str, base));
16261
FREE_AND_NULL(str)
16262
}
16263
}
16264
#endif
16265
/*
16266
* SPEC (1.4) "One of the following must be true:"
16267
*/
16268
if ((type->contentTypeDef != NULL) &&
16269
(type->contentTypeDef == base->contentTypeDef)) {
16270
/*
16271
* SPEC (1.4.1) "The {content type} of the {base type definition}
16272
* and the {content type} of the complex type definition itself
16273
* must be the same simple type definition"
16274
* PASS
16275
*/
16276
} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16277
(base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16278
/*
16279
* SPEC (1.4.2) "The {content type} of both the {base type
16280
* definition} and the complex type definition itself must
16281
* be empty."
16282
* PASS
16283
*/
16284
} else {
16285
/*
16286
* SPEC (1.4.3) "All of the following must be true:"
16287
*/
16288
if (type->subtypes == NULL) {
16289
/*
16290
* SPEC 1.4.3.1 The {content type} of the complex type
16291
* definition itself must specify a particle.
16292
*/
16293
xmlSchemaPCustomErr(ctxt,
16294
XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16295
WXS_BASIC_CAST type, NULL,
16296
"The content type must specify a particle", NULL);
16297
return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16298
}
16299
/*
16300
* SPEC (1.4.3.2) "One of the following must be true:"
16301
*/
16302
if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16303
/*
16304
* SPEC (1.4.3.2.1) "The {content type} of the {base type
16305
* definition} must be empty.
16306
* PASS
16307
*/
16308
} else {
16309
/*
16310
* SPEC (1.4.3.2.2) "All of the following must be true:"
16311
*/
16312
if ((type->contentType != base->contentType) ||
16313
((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16314
(type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16315
/*
16316
* SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16317
* or both must be element-only."
16318
*/
16319
xmlSchemaPCustomErr(ctxt,
16320
XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16321
WXS_BASIC_CAST type, NULL,
16322
"The content type of both, the type and its base "
16323
"type, must either 'mixed' or 'element-only'", NULL);
16324
return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16325
}
16326
/*
16327
* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16328
* complex type definition must be a `valid extension`
16329
* of the {base type definition}'s particle, as defined
16330
* in Particle Valid (Extension) ($3.9.6)."
16331
*
16332
* NOTE that we won't check "Particle Valid (Extension)",
16333
* since it is ensured by the derivation process in
16334
* xmlSchemaTypeFixup(). We need to implement this when heading
16335
* for a construction API
16336
* TODO: !! This is needed to be checked if redefining a type !!
16337
*/
16338
}
16339
/*
16340
* URGENT TODO (1.5)
16341
*/
16342
}
16343
} else {
16344
/*
16345
* SPEC (2) "If the {base type definition} is a simple type definition,
16346
* then all of the following must be true:"
16347
*/
16348
if (type->contentTypeDef != base) {
16349
/*
16350
* SPEC (2.1) "The {content type} must be the same simple type
16351
* definition."
16352
*/
16353
xmlSchemaPCustomErr(ctxt,
16354
XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16355
WXS_BASIC_CAST type, NULL,
16356
"The content type must be the simple base type", NULL);
16357
return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16358
}
16359
if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16360
/*
16361
* SPEC (2.2) "The {final} of the {base type definition} must not
16362
* contain extension"
16363
* NOTE that this is the same as (1.1).
16364
*/
16365
xmlSchemaPCustomErr(ctxt,
16366
XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16367
WXS_BASIC_CAST type, NULL,
16368
"The 'final' of the base type definition "
16369
"contains 'extension'", NULL);
16370
return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16371
}
16372
}
16373
return (0);
16374
}
16375
16376
/**
16377
* xmlSchemaCheckDerivationOKRestriction:
16378
* @ctxt: the schema parser context
16379
* @type: the complex type definition
16380
*
16381
* (3.4.6) Constraints on Complex Type Definition Schema Components
16382
* Schema Component Constraint:
16383
* Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16384
*
16385
* STATUS:
16386
* missing:
16387
* (5.4.2) ???
16388
*
16389
* ATTENTION:
16390
* In XML Schema 1.1 this will be:
16391
* Validation Rule: Checking complex type subsumption
16392
*
16393
* Returns 0 if the constraints are satisfied, a positive
16394
* error code if not and -1 if an internal error occurred.
16395
*/
16396
static int
16397
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16398
xmlSchemaTypePtr type)
16399
{
16400
xmlSchemaTypePtr base;
16401
16402
/*
16403
* TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16404
* temporarily only.
16405
*/
16406
base = type->baseType;
16407
if (! WXS_IS_COMPLEX(base)) {
16408
xmlSchemaCustomErr(ACTXT_CAST ctxt,
16409
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16410
type->node, WXS_BASIC_CAST type,
16411
"The base type must be a complex type", NULL, NULL);
16412
return(ctxt->err);
16413
}
16414
if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16415
/*
16416
* SPEC (1) "The {base type definition} must be a complex type
16417
* definition whose {final} does not contain restriction."
16418
*/
16419
xmlSchemaCustomErr(ACTXT_CAST ctxt,
16420
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16421
type->node, WXS_BASIC_CAST type,
16422
"The 'final' of the base type definition "
16423
"contains 'restriction'", NULL, NULL);
16424
return (ctxt->err);
16425
}
16426
/*
16427
* SPEC (2), (3) and (4)
16428
* Those are handled in a separate function, since the
16429
* same constraints are needed for redefinition of
16430
* attribute groups as well.
16431
*/
16432
if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16433
XML_SCHEMA_ACTION_DERIVE,
16434
WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16435
type->attrUses, base->attrUses,
16436
type->attributeWildcard,
16437
base->attributeWildcard) == -1)
16438
{
16439
return(-1);
16440
}
16441
/*
16442
* SPEC (5) "One of the following must be true:"
16443
*/
16444
if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16445
/*
16446
* SPEC (5.1) "The {base type definition} must be the
16447
* `ur-type definition`."
16448
* PASS
16449
*/
16450
} else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16451
(type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16452
/*
16453
* SPEC (5.2.1) "The {content type} of the complex type definition
16454
* must be a simple type definition"
16455
*
16456
* SPEC (5.2.2) "One of the following must be true:"
16457
*/
16458
if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16459
(base->contentType == XML_SCHEMA_CONTENT_BASIC))
16460
{
16461
int err;
16462
/*
16463
* SPEC (5.2.2.1) "The {content type} of the {base type
16464
* definition} must be a simple type definition from which
16465
* the {content type} is validly derived given the empty
16466
* set as defined in Type Derivation OK (Simple) ($3.14.6)."
16467
*
16468
* ATTENTION TODO: This seems not needed if the type implicitly
16469
* derived from the base type.
16470
*
16471
*/
16472
err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16473
type->contentTypeDef, base->contentTypeDef, 0);
16474
if (err != 0) {
16475
xmlChar *strA = NULL, *strB = NULL;
16476
16477
if (err == -1)
16478
return(-1);
16479
xmlSchemaCustomErr(ACTXT_CAST ctxt,
16480
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16481
NULL, WXS_BASIC_CAST type,
16482
"The {content type} %s is not validly derived from the "
16483
"base type's {content type} %s",
16484
xmlSchemaGetComponentDesignation(&strA,
16485
type->contentTypeDef),
16486
xmlSchemaGetComponentDesignation(&strB,
16487
base->contentTypeDef));
16488
FREE_AND_NULL(strA);
16489
FREE_AND_NULL(strB);
16490
return(ctxt->err);
16491
}
16492
} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16493
(xmlSchemaIsParticleEmptiable(
16494
(xmlSchemaParticlePtr) base->subtypes))) {
16495
/*
16496
* SPEC (5.2.2.2) "The {base type definition} must be mixed
16497
* and have a particle which is `emptiable` as defined in
16498
* Particle Emptiable ($3.9.6)."
16499
* PASS
16500
*/
16501
} else {
16502
xmlSchemaPCustomErr(ctxt,
16503
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16504
WXS_BASIC_CAST type, NULL,
16505
"The content type of the base type must be either "
16506
"a simple type or 'mixed' and an emptiable particle", NULL);
16507
return (ctxt->err);
16508
}
16509
} else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16510
/*
16511
* SPEC (5.3.1) "The {content type} of the complex type itself must
16512
* be empty"
16513
*/
16514
if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16515
/*
16516
* SPEC (5.3.2.1) "The {content type} of the {base type
16517
* definition} must also be empty."
16518
* PASS
16519
*/
16520
} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16521
(base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16522
xmlSchemaIsParticleEmptiable(
16523
(xmlSchemaParticlePtr) base->subtypes)) {
16524
/*
16525
* SPEC (5.3.2.2) "The {content type} of the {base type
16526
* definition} must be elementOnly or mixed and have a particle
16527
* which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16528
* PASS
16529
*/
16530
} else {
16531
xmlSchemaPCustomErr(ctxt,
16532
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16533
WXS_BASIC_CAST type, NULL,
16534
"The content type of the base type must be either "
16535
"empty or 'mixed' (or 'elements-only') and an emptiable "
16536
"particle", NULL);
16537
return (ctxt->err);
16538
}
16539
} else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16540
WXS_HAS_MIXED_CONTENT(type)) {
16541
/*
16542
* SPEC (5.4.1.1) "The {content type} of the complex type definition
16543
* itself must be element-only"
16544
*/
16545
if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16546
/*
16547
* SPEC (5.4.1.2) "The {content type} of the complex type
16548
* definition itself and of the {base type definition} must be
16549
* mixed"
16550
*/
16551
xmlSchemaPCustomErr(ctxt,
16552
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16553
WXS_BASIC_CAST type, NULL,
16554
"If the content type is 'mixed', then the content type of the "
16555
"base type must also be 'mixed'", NULL);
16556
return (ctxt->err);
16557
}
16558
/*
16559
* SPEC (5.4.2) "The particle of the complex type definition itself
16560
* must be a `valid restriction` of the particle of the {content
16561
* type} of the {base type definition} as defined in Particle Valid
16562
* (Restriction) ($3.9.6).
16563
*
16564
* URGENT TODO: (5.4.2)
16565
*/
16566
} else {
16567
xmlSchemaPCustomErr(ctxt,
16568
XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16569
WXS_BASIC_CAST type, NULL,
16570
"The type is not a valid restriction of its base type", NULL);
16571
return (ctxt->err);
16572
}
16573
return (0);
16574
}
16575
16576
/**
16577
* xmlSchemaCheckCTComponent:
16578
* @ctxt: the schema parser context
16579
* @type: the complex type definition
16580
*
16581
* (3.4.6) Constraints on Complex Type Definition Schema Components
16582
*
16583
* Returns 0 if the constraints are satisfied, a positive
16584
* error code if not and -1 if an internal error occurred.
16585
*/
16586
static int
16587
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16588
xmlSchemaTypePtr type)
16589
{
16590
int ret;
16591
/*
16592
* Complex Type Definition Properties Correct
16593
*/
16594
ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16595
if (ret != 0)
16596
return (ret);
16597
if (WXS_IS_EXTENSION(type))
16598
ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16599
else
16600
ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16601
return (ret);
16602
}
16603
16604
/**
16605
* xmlSchemaCheckSRCCT:
16606
* @ctxt: the schema parser context
16607
* @type: the complex type definition
16608
*
16609
* (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16610
* Schema Representation Constraint:
16611
* Complex Type Definition Representation OK (src-ct)
16612
*
16613
* Returns 0 if the constraints are satisfied, a positive
16614
* error code if not and -1 if an internal error occurred.
16615
*/
16616
static int
16617
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16618
xmlSchemaTypePtr type)
16619
{
16620
xmlSchemaTypePtr base;
16621
int ret = 0;
16622
16623
/*
16624
* TODO: Adjust the error codes here, as I used
16625
* XML_SCHEMAP_SRC_CT_1 only yet.
16626
*/
16627
base = type->baseType;
16628
if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16629
/*
16630
* 1 If the <complexContent> alternative is chosen, the type definition
16631
* `resolved` to by the `actual value` of the base [attribute]
16632
* must be a complex type definition;
16633
*/
16634
if (! WXS_IS_COMPLEX(base)) {
16635
xmlChar *str = NULL;
16636
xmlSchemaPCustomErr(ctxt,
16637
XML_SCHEMAP_SRC_CT_1,
16638
WXS_BASIC_CAST type, type->node,
16639
"If using <complexContent>, the base type is expected to be "
16640
"a complex type. The base type '%s' is a simple type",
16641
xmlSchemaFormatQName(&str, base->targetNamespace,
16642
base->name));
16643
FREE_AND_NULL(str)
16644
return (XML_SCHEMAP_SRC_CT_1);
16645
}
16646
} else {
16647
/*
16648
* SPEC
16649
* 2 If the <simpleContent> alternative is chosen, all of the
16650
* following must be true:
16651
* 2.1 The type definition `resolved` to by the `actual value` of the
16652
* base [attribute] must be one of the following:
16653
*/
16654
if (WXS_IS_SIMPLE(base)) {
16655
if (WXS_IS_EXTENSION(type) == 0) {
16656
xmlChar *str = NULL;
16657
/*
16658
* 2.1.3 only if the <extension> alternative is also
16659
* chosen, a simple type definition.
16660
*/
16661
/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16662
xmlSchemaPCustomErr(ctxt,
16663
XML_SCHEMAP_SRC_CT_1,
16664
WXS_BASIC_CAST type, NULL,
16665
"If using <simpleContent> and <restriction>, the base "
16666
"type must be a complex type. The base type '%s' is "
16667
"a simple type",
16668
xmlSchemaFormatQName(&str, base->targetNamespace,
16669
base->name));
16670
FREE_AND_NULL(str)
16671
return (XML_SCHEMAP_SRC_CT_1);
16672
}
16673
} else {
16674
/* Base type is a complex type. */
16675
if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16676
(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16677
/*
16678
* 2.1.1 a complex type definition whose {content type} is a
16679
* simple type definition;
16680
* PASS
16681
*/
16682
if (base->contentTypeDef == NULL) {
16683
xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16684
WXS_BASIC_CAST type, NULL,
16685
"Internal error: xmlSchemaCheckSRCCT, "
16686
"'%s', base type has no content type",
16687
type->name);
16688
return (-1);
16689
}
16690
} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16691
(WXS_IS_RESTRICTION(type))) {
16692
16693
/*
16694
* 2.1.2 only if the <restriction> alternative is also
16695
* chosen, a complex type definition whose {content type}
16696
* is mixed and a particle emptiable.
16697
*/
16698
if (! xmlSchemaIsParticleEmptiable(
16699
(xmlSchemaParticlePtr) base->subtypes)) {
16700
ret = XML_SCHEMAP_SRC_CT_1;
16701
} else
16702
/*
16703
* Attention: at this point the <simpleType> child is in
16704
* ->contentTypeDef (put there during parsing).
16705
*/
16706
if (type->contentTypeDef == NULL) {
16707
xmlChar *str = NULL;
16708
/*
16709
* 2.2 If clause 2.1.2 above is satisfied, then there
16710
* must be a <simpleType> among the [children] of
16711
* <restriction>.
16712
*/
16713
/* TODO: Change error code to ..._SRC_CT_2_2. */
16714
xmlSchemaPCustomErr(ctxt,
16715
XML_SCHEMAP_SRC_CT_1,
16716
WXS_BASIC_CAST type, NULL,
16717
"A <simpleType> is expected among the children "
16718
"of <restriction>, if <simpleContent> is used and "
16719
"the base type '%s' is a complex type",
16720
xmlSchemaFormatQName(&str, base->targetNamespace,
16721
base->name));
16722
FREE_AND_NULL(str)
16723
return (XML_SCHEMAP_SRC_CT_1);
16724
}
16725
} else {
16726
ret = XML_SCHEMAP_SRC_CT_1;
16727
}
16728
}
16729
if (ret > 0) {
16730
xmlChar *str = NULL;
16731
if (WXS_IS_RESTRICTION(type)) {
16732
xmlSchemaPCustomErr(ctxt,
16733
XML_SCHEMAP_SRC_CT_1,
16734
WXS_BASIC_CAST type, NULL,
16735
"If <simpleContent> and <restriction> is used, the "
16736
"base type must be a simple type or a complex type with "
16737
"mixed content and particle emptiable. The base type "
16738
"'%s' is none of those",
16739
xmlSchemaFormatQName(&str, base->targetNamespace,
16740
base->name));
16741
} else {
16742
xmlSchemaPCustomErr(ctxt,
16743
XML_SCHEMAP_SRC_CT_1,
16744
WXS_BASIC_CAST type, NULL,
16745
"If <simpleContent> and <extension> is used, the "
16746
"base type must be a simple type. The base type '%s' "
16747
"is a complex type",
16748
xmlSchemaFormatQName(&str, base->targetNamespace,
16749
base->name));
16750
}
16751
FREE_AND_NULL(str)
16752
}
16753
}
16754
/*
16755
* SPEC (3) "The corresponding complex type definition component must
16756
* satisfy the conditions set out in Constraints on Complex Type
16757
* Definition Schema Components ($3.4.6);"
16758
* NOTE (3) will be done in xmlSchemaTypeFixup().
16759
*/
16760
/*
16761
* SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16762
* above for {attribute wildcard} is satisfied, the intensional
16763
* intersection must be expressible, as defined in Attribute Wildcard
16764
* Intersection ($3.10.6).
16765
* NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16766
*/
16767
return (ret);
16768
}
16769
16770
#ifdef ENABLE_PARTICLE_RESTRICTION
16771
/**
16772
* xmlSchemaCheckParticleRangeOK:
16773
* @ctxt: the schema parser context
16774
* @type: the complex type definition
16775
*
16776
* (3.9.6) Constraints on Particle Schema Components
16777
* Schema Component Constraint:
16778
* Occurrence Range OK (range-ok)
16779
*
16780
* STATUS: complete
16781
*
16782
* Returns 0 if the constraints are satisfied, a positive
16783
* error code if not and -1 if an internal error occurred.
16784
*/
16785
static int
16786
xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16787
int bmin, int bmax)
16788
{
16789
if (rmin < bmin)
16790
return (1);
16791
if ((bmax != UNBOUNDED) &&
16792
(rmax > bmax))
16793
return (1);
16794
return (0);
16795
}
16796
16797
/**
16798
* xmlSchemaCheckRCaseNameAndTypeOK:
16799
* @ctxt: the schema parser context
16800
* @r: the restricting element declaration particle
16801
* @b: the base element declaration particle
16802
*
16803
* (3.9.6) Constraints on Particle Schema Components
16804
* Schema Component Constraint:
16805
* Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16806
* (rcase-NameAndTypeOK)
16807
*
16808
* STATUS:
16809
* MISSING (3.2.3)
16810
* CLARIFY: (3.2.2)
16811
*
16812
* Returns 0 if the constraints are satisfied, a positive
16813
* error code if not and -1 if an internal error occurred.
16814
*/
16815
static int
16816
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16817
xmlSchemaParticlePtr r,
16818
xmlSchemaParticlePtr b)
16819
{
16820
xmlSchemaElementPtr elemR, elemB;
16821
16822
/* TODO: Error codes (rcase-NameAndTypeOK). */
16823
elemR = (xmlSchemaElementPtr) r->children;
16824
elemB = (xmlSchemaElementPtr) b->children;
16825
/*
16826
* SPEC (1) "The declarations' {name}s and {target namespace}s are
16827
* the same."
16828
*/
16829
if ((elemR != elemB) &&
16830
((! xmlStrEqual(elemR->name, elemB->name)) ||
16831
(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16832
return (1);
16833
/*
16834
* SPEC (2) "R's occurrence range is a valid restriction of B's
16835
* occurrence range as defined by Occurrence Range OK ($3.9.6)."
16836
*/
16837
if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16838
b->minOccurs, b->maxOccurs) != 0)
16839
return (1);
16840
/*
16841
* SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16842
* {scope} are global."
16843
*/
16844
if (elemR == elemB)
16845
return (0);
16846
/*
16847
* SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16848
*/
16849
if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16850
(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16851
return (1);
16852
/*
16853
* SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16854
* or is not fixed, or R's declaration's {value constraint} is fixed
16855
* with the same value."
16856
*/
16857
if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16858
((elemR->value == NULL) ||
16859
((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16860
/* TODO: Equality of the initial value or normalized or canonical? */
16861
(! xmlStrEqual(elemR->value, elemB->value))))
16862
return (1);
16863
/*
16864
* TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16865
* definitions} is a subset of B's declaration's {identity-constraint
16866
* definitions}, if any."
16867
*/
16868
if (elemB->idcs != NULL) {
16869
/* TODO */
16870
}
16871
/*
16872
* SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16873
* superset of B's declaration's {disallowed substitutions}."
16874
*/
16875
if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16876
((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16877
((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16878
((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16879
((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16880
((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16881
return (1);
16882
/*
16883
* SPEC (3.2.5) "R's {type definition} is validly derived given
16884
* {extension, list, union} from B's {type definition}"
16885
*
16886
* BADSPEC TODO: What's the point of adding "list" and "union" to the
16887
* set, if the corresponding constraints handle "restriction" and
16888
* "extension" only?
16889
*
16890
*/
16891
{
16892
int set = 0;
16893
16894
set |= SUBSET_EXTENSION;
16895
set |= SUBSET_LIST;
16896
set |= SUBSET_UNION;
16897
if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16898
elemB->subtypes, set) != 0)
16899
return (1);
16900
}
16901
return (0);
16902
}
16903
16904
/**
16905
* xmlSchemaCheckRCaseNSCompat:
16906
* @ctxt: the schema parser context
16907
* @r: the restricting element declaration particle
16908
* @b: the base wildcard particle
16909
*
16910
* (3.9.6) Constraints on Particle Schema Components
16911
* Schema Component Constraint:
16912
* Particle Derivation OK (Elt:Any -- NSCompat)
16913
* (rcase-NSCompat)
16914
*
16915
* STATUS: complete
16916
*
16917
* Returns 0 if the constraints are satisfied, a positive
16918
* error code if not and -1 if an internal error occurred.
16919
*/
16920
static int
16921
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16922
xmlSchemaParticlePtr r,
16923
xmlSchemaParticlePtr b)
16924
{
16925
/* TODO:Error codes (rcase-NSCompat). */
16926
/*
16927
* SPEC "For an element declaration particle to be a `valid restriction`
16928
* of a wildcard particle all of the following must be true:"
16929
*
16930
* SPEC (1) "The element declaration's {target namespace} is `valid`
16931
* with respect to the wildcard's {namespace constraint} as defined by
16932
* Wildcard allows Namespace Name ($3.10.4)."
16933
*/
16934
if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16935
((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16936
return (1);
16937
/*
16938
* SPEC (2) "R's occurrence range is a valid restriction of B's
16939
* occurrence range as defined by Occurrence Range OK ($3.9.6)."
16940
*/
16941
if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16942
b->minOccurs, b->maxOccurs) != 0)
16943
return (1);
16944
16945
return (0);
16946
}
16947
16948
/**
16949
* xmlSchemaCheckRCaseRecurseAsIfGroup:
16950
* @ctxt: the schema parser context
16951
* @r: the restricting element declaration particle
16952
* @b: the base model group particle
16953
*
16954
* (3.9.6) Constraints on Particle Schema Components
16955
* Schema Component Constraint:
16956
* Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16957
* (rcase-RecurseAsIfGroup)
16958
*
16959
* STATUS: TODO
16960
*
16961
* Returns 0 if the constraints are satisfied, a positive
16962
* error code if not and -1 if an internal error occurred.
16963
*/
16964
static int
16965
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16966
xmlSchemaParticlePtr r,
16967
xmlSchemaParticlePtr b)
16968
{
16969
/* TODO: Error codes (rcase-RecurseAsIfGroup). */
16970
TODO
16971
return (0);
16972
}
16973
16974
/**
16975
* xmlSchemaCheckRCaseNSSubset:
16976
* @ctxt: the schema parser context
16977
* @r: the restricting wildcard particle
16978
* @b: the base wildcard particle
16979
*
16980
* (3.9.6) Constraints on Particle Schema Components
16981
* Schema Component Constraint:
16982
* Particle Derivation OK (Any:Any -- NSSubset)
16983
* (rcase-NSSubset)
16984
*
16985
* STATUS: complete
16986
*
16987
* Returns 0 if the constraints are satisfied, a positive
16988
* error code if not and -1 if an internal error occurred.
16989
*/
16990
static int
16991
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16992
xmlSchemaParticlePtr r,
16993
xmlSchemaParticlePtr b,
16994
int isAnyTypeBase)
16995
{
16996
/* TODO: Error codes (rcase-NSSubset). */
16997
/*
16998
* SPEC (1) "R's occurrence range is a valid restriction of B's
16999
* occurrence range as defined by Occurrence Range OK ($3.9.6)."
17000
*/
17001
if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17002
b->minOccurs, b->maxOccurs))
17003
return (1);
17004
/*
17005
* SPEC (2) "R's {namespace constraint} must be an intensional subset
17006
* of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17007
*/
17008
if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17009
(xmlSchemaWildcardPtr) b->children))
17010
return (1);
17011
/*
17012
* SPEC (3) "Unless B is the content model wildcard of the `ur-type
17013
* definition`, R's {process contents} must be identical to or stronger
17014
* than B's {process contents}, where strict is stronger than lax is
17015
* stronger than skip."
17016
*/
17017
if (! isAnyTypeBase) {
17018
if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17019
((xmlSchemaWildcardPtr) b->children)->processContents)
17020
return (1);
17021
}
17022
17023
return (0);
17024
}
17025
17026
/**
17027
* xmlSchemaCheckCOSParticleRestrict:
17028
* @ctxt: the schema parser context
17029
* @type: the complex type definition
17030
*
17031
* (3.9.6) Constraints on Particle Schema Components
17032
* Schema Component Constraint:
17033
* Particle Valid (Restriction) (cos-particle-restrict)
17034
*
17035
* STATUS: TODO
17036
*
17037
* Returns 0 if the constraints are satisfied, a positive
17038
* error code if not and -1 if an internal error occurred.
17039
*/
17040
static int
17041
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17042
xmlSchemaParticlePtr r,
17043
xmlSchemaParticlePtr b)
17044
{
17045
int ret = 0;
17046
17047
/*part = WXS_TYPE_PARTICLE(type);
17048
basePart = WXS_TYPE_PARTICLE(base);
17049
*/
17050
17051
TODO
17052
17053
/*
17054
* SPEC (1) "They are the same particle."
17055
*/
17056
if (r == b)
17057
return (0);
17058
17059
17060
return (0);
17061
}
17062
17063
#if 0
17064
/**
17065
* xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17066
* @ctxt: the schema parser context
17067
* @r: the model group particle
17068
* @b: the base wildcard particle
17069
*
17070
* (3.9.6) Constraints on Particle Schema Components
17071
* Schema Component Constraint:
17072
* Particle Derivation OK (All/Choice/Sequence:Any --
17073
* NSRecurseCheckCardinality)
17074
* (rcase-NSRecurseCheckCardinality)
17075
*
17076
* STATUS: TODO: subst-groups
17077
*
17078
* Returns 0 if the constraints are satisfied, a positive
17079
* error code if not and -1 if an internal error occurred.
17080
*/
17081
static int
17082
xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17083
xmlSchemaParticlePtr r,
17084
xmlSchemaParticlePtr b)
17085
{
17086
xmlSchemaParticlePtr part;
17087
/* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17088
if ((r->children == NULL) || (r->children->children == NULL))
17089
return (-1);
17090
/*
17091
* SPEC "For a group particle to be a `valid restriction` of a
17092
* wildcard particle..."
17093
*
17094
* SPEC (1) "Every member of the {particles} of the group is a `valid
17095
* restriction` of the wildcard as defined by
17096
* Particle Valid (Restriction) ($3.9.6)."
17097
*/
17098
part = (xmlSchemaParticlePtr) r->children->children;
17099
do {
17100
if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17101
return (1);
17102
part = (xmlSchemaParticlePtr) part->next;
17103
} while (part != NULL);
17104
/*
17105
* SPEC (2) "The effective total range of the group [...] is a
17106
* valid restriction of B's occurrence range as defined by
17107
* Occurrence Range OK ($3.9.6)."
17108
*/
17109
if (xmlSchemaCheckParticleRangeOK(
17110
xmlSchemaGetParticleTotalRangeMin(r),
17111
xmlSchemaGetParticleTotalRangeMax(r),
17112
b->minOccurs, b->maxOccurs) != 0)
17113
return (1);
17114
return (0);
17115
}
17116
#endif
17117
17118
/**
17119
* xmlSchemaCheckRCaseRecurse:
17120
* @ctxt: the schema parser context
17121
* @r: the <all> or <sequence> model group particle
17122
* @b: the base <all> or <sequence> model group particle
17123
*
17124
* (3.9.6) Constraints on Particle Schema Components
17125
* Schema Component Constraint:
17126
* Particle Derivation OK (All:All,Sequence:Sequence --
17127
Recurse)
17128
* (rcase-Recurse)
17129
*
17130
* STATUS: ?
17131
* TODO: subst-groups
17132
*
17133
* Returns 0 if the constraints are satisfied, a positive
17134
* error code if not and -1 if an internal error occurred.
17135
*/
17136
static int
17137
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17138
xmlSchemaParticlePtr r,
17139
xmlSchemaParticlePtr b)
17140
{
17141
/* xmlSchemaParticlePtr part; */
17142
/* TODO: Error codes (rcase-Recurse). */
17143
if ((r->children == NULL) || (b->children == NULL) ||
17144
(r->children->type != b->children->type))
17145
return (-1);
17146
/*
17147
* SPEC "For an all or sequence group particle to be a `valid
17148
* restriction` of another group particle with the same {compositor}..."
17149
*
17150
* SPEC (1) "R's occurrence range is a valid restriction of B's
17151
* occurrence range as defined by Occurrence Range OK ($3.9.6)."
17152
*/
17153
if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17154
b->minOccurs, b->maxOccurs))
17155
return (1);
17156
17157
17158
return (0);
17159
}
17160
17161
#endif
17162
17163
#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17164
xmlSchemaPCustomErrExt(pctxt, \
17165
XML_SCHEMAP_INVALID_FACET_VALUE, \
17166
WXS_BASIC_CAST fac1, fac1->node, \
17167
"It is an error for both '%s' and '%s' to be specified on the "\
17168
"same type definition", \
17169
BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17170
BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17171
17172
#define FACET_RESTR_ERR(fac1, msg) \
17173
xmlSchemaPCustomErr(pctxt, \
17174
XML_SCHEMAP_INVALID_FACET_VALUE, \
17175
WXS_BASIC_CAST fac1, fac1->node, \
17176
msg, NULL);
17177
17178
#define FACET_RESTR_FIXED_ERR(fac) \
17179
xmlSchemaPCustomErr(pctxt, \
17180
XML_SCHEMAP_INVALID_FACET_VALUE, \
17181
WXS_BASIC_CAST fac, fac->node, \
17182
"The base type's facet is 'fixed', thus the value must not " \
17183
"differ", NULL);
17184
17185
static void
17186
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17187
xmlSchemaFacetPtr facet1,
17188
xmlSchemaFacetPtr facet2,
17189
int lessGreater,
17190
int orEqual,
17191
int ofBase)
17192
{
17193
xmlChar *msg = NULL;
17194
17195
msg = xmlStrdup(BAD_CAST "'");
17196
msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17197
msg = xmlStrcat(msg, BAD_CAST "' has to be");
17198
if (lessGreater == 0)
17199
msg = xmlStrcat(msg, BAD_CAST " equal to");
17200
if (lessGreater == 1)
17201
msg = xmlStrcat(msg, BAD_CAST " greater than");
17202
else
17203
msg = xmlStrcat(msg, BAD_CAST " less than");
17204
17205
if (orEqual)
17206
msg = xmlStrcat(msg, BAD_CAST " or equal to");
17207
msg = xmlStrcat(msg, BAD_CAST " '");
17208
msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17209
if (ofBase)
17210
msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17211
else
17212
msg = xmlStrcat(msg, BAD_CAST "'");
17213
17214
xmlSchemaPCustomErr(pctxt,
17215
XML_SCHEMAP_INVALID_FACET_VALUE,
17216
WXS_BASIC_CAST facet1, NULL,
17217
(const char *) msg, NULL);
17218
17219
if (msg != NULL)
17220
xmlFree(msg);
17221
}
17222
17223
/*
17224
* xmlSchemaDeriveAndValidateFacets:
17225
*
17226
* Schema Component Constraint: Simple Type Restriction (Facets)
17227
* (st-restrict-facets)
17228
*/
17229
static int
17230
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17231
xmlSchemaTypePtr type)
17232
{
17233
xmlSchemaTypePtr base = type->baseType;
17234
xmlSchemaFacetLinkPtr link, cur, last = NULL;
17235
xmlSchemaFacetPtr facet, bfacet,
17236
flength = NULL, ftotdig = NULL, ffracdig = NULL,
17237
fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17238
fmininc = NULL, fmaxinc = NULL,
17239
fminexc = NULL, fmaxexc = NULL,
17240
bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17241
bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17242
bfmininc = NULL, bfmaxinc = NULL,
17243
bfminexc = NULL, bfmaxexc = NULL;
17244
int res; /* err = 0, fixedErr; */
17245
17246
/*
17247
* SPEC st-restrict-facets 1:
17248
* "The {variety} of R is the same as that of B."
17249
*/
17250
/*
17251
* SPEC st-restrict-facets 2:
17252
* "If {variety} is atomic, the {primitive type definition}
17253
* of R is the same as that of B."
17254
*
17255
* NOTE: we leave 1 & 2 out for now, since this will be
17256
* satisfied by the derivation process.
17257
* CONSTRUCTION TODO: Maybe needed if using a construction API.
17258
*/
17259
/*
17260
* SPEC st-restrict-facets 3:
17261
* "The {facets} of R are the union of S and the {facets}
17262
* of B, eliminating duplicates. To eliminate duplicates,
17263
* when a facet of the same kind occurs in both S and the
17264
* {facets} of B, the one in the {facets} of B is not
17265
* included, with the exception of enumeration and pattern
17266
* facets, for which multiple occurrences with distinct values
17267
* are allowed."
17268
*/
17269
17270
if ((type->facetSet == NULL) && (base->facetSet == NULL))
17271
return (0);
17272
17273
last = type->facetSet;
17274
if (last != NULL)
17275
while (last->next != NULL)
17276
last = last->next;
17277
17278
for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17279
facet = cur->facet;
17280
switch (facet->type) {
17281
case XML_SCHEMA_FACET_LENGTH:
17282
flength = facet; break;
17283
case XML_SCHEMA_FACET_MINLENGTH:
17284
fminlen = facet; break;
17285
case XML_SCHEMA_FACET_MININCLUSIVE:
17286
fmininc = facet; break;
17287
case XML_SCHEMA_FACET_MINEXCLUSIVE:
17288
fminexc = facet; break;
17289
case XML_SCHEMA_FACET_MAXLENGTH:
17290
fmaxlen = facet; break;
17291
case XML_SCHEMA_FACET_MAXINCLUSIVE:
17292
fmaxinc = facet; break;
17293
case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17294
fmaxexc = facet; break;
17295
case XML_SCHEMA_FACET_TOTALDIGITS:
17296
ftotdig = facet; break;
17297
case XML_SCHEMA_FACET_FRACTIONDIGITS:
17298
ffracdig = facet; break;
17299
default:
17300
break;
17301
}
17302
}
17303
for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17304
facet = cur->facet;
17305
switch (facet->type) {
17306
case XML_SCHEMA_FACET_LENGTH:
17307
bflength = facet; break;
17308
case XML_SCHEMA_FACET_MINLENGTH:
17309
bfminlen = facet; break;
17310
case XML_SCHEMA_FACET_MININCLUSIVE:
17311
bfmininc = facet; break;
17312
case XML_SCHEMA_FACET_MINEXCLUSIVE:
17313
bfminexc = facet; break;
17314
case XML_SCHEMA_FACET_MAXLENGTH:
17315
bfmaxlen = facet; break;
17316
case XML_SCHEMA_FACET_MAXINCLUSIVE:
17317
bfmaxinc = facet; break;
17318
case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17319
bfmaxexc = facet; break;
17320
case XML_SCHEMA_FACET_TOTALDIGITS:
17321
bftotdig = facet; break;
17322
case XML_SCHEMA_FACET_FRACTIONDIGITS:
17323
bffracdig = facet; break;
17324
default:
17325
break;
17326
}
17327
}
17328
/*
17329
* length and minLength or maxLength (2.2) + (3.2)
17330
*/
17331
if (flength && (fminlen || fmaxlen)) {
17332
FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17333
"either of 'minLength' or 'maxLength' to be specified on "
17334
"the same type definition")
17335
}
17336
/*
17337
* Mutual exclusions in the same derivation step.
17338
*/
17339
if ((fmaxinc) && (fmaxexc)) {
17340
/*
17341
* SCC "maxInclusive and maxExclusive"
17342
*/
17343
FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17344
}
17345
if ((fmininc) && (fminexc)) {
17346
/*
17347
* SCC "minInclusive and minExclusive"
17348
*/
17349
FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17350
}
17351
17352
if (flength && bflength) {
17353
/*
17354
* SCC "length valid restriction"
17355
* The values have to be equal.
17356
*/
17357
res = xmlSchemaCompareValues(flength->val, bflength->val);
17358
if (res == -2)
17359
goto internal_error;
17360
if (res != 0)
17361
xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17362
if ((res != 0) && (bflength->fixed)) {
17363
FACET_RESTR_FIXED_ERR(flength)
17364
}
17365
17366
}
17367
if (fminlen && bfminlen) {
17368
/*
17369
* SCC "minLength valid restriction"
17370
* minLength >= BASE minLength
17371
*/
17372
res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17373
if (res == -2)
17374
goto internal_error;
17375
if (res == -1)
17376
xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17377
if ((res != 0) && (bfminlen->fixed)) {
17378
FACET_RESTR_FIXED_ERR(fminlen)
17379
}
17380
}
17381
if (fmaxlen && bfmaxlen) {
17382
/*
17383
* SCC "maxLength valid restriction"
17384
* maxLength <= BASE minLength
17385
*/
17386
res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17387
if (res == -2)
17388
goto internal_error;
17389
if (res == 1)
17390
xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17391
if ((res != 0) && (bfmaxlen->fixed)) {
17392
FACET_RESTR_FIXED_ERR(fmaxlen)
17393
}
17394
}
17395
/*
17396
* SCC "length and minLength or maxLength"
17397
*/
17398
if (! flength)
17399
flength = bflength;
17400
if (flength) {
17401
if (! fminlen)
17402
fminlen = bfminlen;
17403
if (fminlen) {
17404
/* (1.1) length >= minLength */
17405
res = xmlSchemaCompareValues(flength->val, fminlen->val);
17406
if (res == -2)
17407
goto internal_error;
17408
if (res == -1)
17409
xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17410
}
17411
if (! fmaxlen)
17412
fmaxlen = bfmaxlen;
17413
if (fmaxlen) {
17414
/* (2.1) length <= maxLength */
17415
res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17416
if (res == -2)
17417
goto internal_error;
17418
if (res == 1)
17419
xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17420
}
17421
}
17422
if (fmaxinc) {
17423
/*
17424
* "maxInclusive"
17425
*/
17426
if (fmininc) {
17427
/* SCC "maxInclusive >= minInclusive" */
17428
res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17429
if (res == -2)
17430
goto internal_error;
17431
if (res == -1) {
17432
xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17433
}
17434
}
17435
/*
17436
* SCC "maxInclusive valid restriction"
17437
*/
17438
if (bfmaxinc) {
17439
/* maxInclusive <= BASE maxInclusive */
17440
res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17441
if (res == -2)
17442
goto internal_error;
17443
if (res == 1)
17444
xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17445
if ((res != 0) && (bfmaxinc->fixed)) {
17446
FACET_RESTR_FIXED_ERR(fmaxinc)
17447
}
17448
}
17449
if (bfmaxexc) {
17450
/* maxInclusive < BASE maxExclusive */
17451
res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17452
if (res == -2)
17453
goto internal_error;
17454
if (res != -1) {
17455
xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17456
}
17457
}
17458
if (bfmininc) {
17459
/* maxInclusive >= BASE minInclusive */
17460
res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17461
if (res == -2)
17462
goto internal_error;
17463
if (res == -1) {
17464
xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17465
}
17466
}
17467
if (bfminexc) {
17468
/* maxInclusive > BASE minExclusive */
17469
res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17470
if (res == -2)
17471
goto internal_error;
17472
if (res != 1) {
17473
xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17474
}
17475
}
17476
}
17477
if (fmaxexc) {
17478
/*
17479
* "maxExclusive >= minExclusive"
17480
*/
17481
if (fminexc) {
17482
res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17483
if (res == -2)
17484
goto internal_error;
17485
if (res == -1) {
17486
xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17487
}
17488
}
17489
/*
17490
* "maxExclusive valid restriction"
17491
*/
17492
if (bfmaxexc) {
17493
/* maxExclusive <= BASE maxExclusive */
17494
res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17495
if (res == -2)
17496
goto internal_error;
17497
if (res == 1) {
17498
xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17499
}
17500
if ((res != 0) && (bfmaxexc->fixed)) {
17501
FACET_RESTR_FIXED_ERR(fmaxexc)
17502
}
17503
}
17504
if (bfmaxinc) {
17505
/* maxExclusive <= BASE maxInclusive */
17506
res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17507
if (res == -2)
17508
goto internal_error;
17509
if (res == 1) {
17510
xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17511
}
17512
}
17513
if (bfmininc) {
17514
/* maxExclusive > BASE minInclusive */
17515
res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17516
if (res == -2)
17517
goto internal_error;
17518
if (res != 1) {
17519
xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17520
}
17521
}
17522
if (bfminexc) {
17523
/* maxExclusive > BASE minExclusive */
17524
res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17525
if (res == -2)
17526
goto internal_error;
17527
if (res != 1) {
17528
xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17529
}
17530
}
17531
}
17532
if (fminexc) {
17533
/*
17534
* "minExclusive < maxInclusive"
17535
*/
17536
if (fmaxinc) {
17537
res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17538
if (res == -2)
17539
goto internal_error;
17540
if (res != -1) {
17541
xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17542
}
17543
}
17544
/*
17545
* "minExclusive valid restriction"
17546
*/
17547
if (bfminexc) {
17548
/* minExclusive >= BASE minExclusive */
17549
res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17550
if (res == -2)
17551
goto internal_error;
17552
if (res == -1) {
17553
xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17554
}
17555
if ((res != 0) && (bfminexc->fixed)) {
17556
FACET_RESTR_FIXED_ERR(fminexc)
17557
}
17558
}
17559
if (bfmaxinc) {
17560
/* minExclusive <= BASE maxInclusive */
17561
res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17562
if (res == -2)
17563
goto internal_error;
17564
if (res == 1) {
17565
xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17566
}
17567
}
17568
if (bfmininc) {
17569
/* minExclusive >= BASE minInclusive */
17570
res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17571
if (res == -2)
17572
goto internal_error;
17573
if (res == -1) {
17574
xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17575
}
17576
}
17577
if (bfmaxexc) {
17578
/* minExclusive < BASE maxExclusive */
17579
res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17580
if (res == -2)
17581
goto internal_error;
17582
if (res != -1) {
17583
xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17584
}
17585
}
17586
}
17587
if (fmininc) {
17588
/*
17589
* "minInclusive < maxExclusive"
17590
*/
17591
if (fmaxexc) {
17592
res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17593
if (res == -2)
17594
goto internal_error;
17595
if (res != -1) {
17596
xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17597
}
17598
}
17599
/*
17600
* "minExclusive valid restriction"
17601
*/
17602
if (bfmininc) {
17603
/* minInclusive >= BASE minInclusive */
17604
res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17605
if (res == -2)
17606
goto internal_error;
17607
if (res == -1) {
17608
xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17609
}
17610
if ((res != 0) && (bfmininc->fixed)) {
17611
FACET_RESTR_FIXED_ERR(fmininc)
17612
}
17613
}
17614
if (bfmaxinc) {
17615
/* minInclusive <= BASE maxInclusive */
17616
res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17617
if (res == -2)
17618
goto internal_error;
17619
if (res == 1) {
17620
xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17621
}
17622
}
17623
if (bfminexc) {
17624
/* minInclusive > BASE minExclusive */
17625
res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17626
if (res == -2)
17627
goto internal_error;
17628
if (res != 1)
17629
xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17630
}
17631
if (bfmaxexc) {
17632
/* minInclusive < BASE maxExclusive */
17633
res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17634
if (res == -2)
17635
goto internal_error;
17636
if (res != -1)
17637
xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17638
}
17639
}
17640
if (ftotdig && bftotdig) {
17641
/*
17642
* SCC " totalDigits valid restriction"
17643
* totalDigits <= BASE totalDigits
17644
*/
17645
res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17646
if (res == -2)
17647
goto internal_error;
17648
if (res == 1)
17649
xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17650
-1, 1, 1);
17651
if ((res != 0) && (bftotdig->fixed)) {
17652
FACET_RESTR_FIXED_ERR(ftotdig)
17653
}
17654
}
17655
if (ffracdig && bffracdig) {
17656
/*
17657
* SCC "fractionDigits valid restriction"
17658
* fractionDigits <= BASE fractionDigits
17659
*/
17660
res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17661
if (res == -2)
17662
goto internal_error;
17663
if (res == 1)
17664
xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17665
-1, 1, 1);
17666
if ((res != 0) && (bffracdig->fixed)) {
17667
FACET_RESTR_FIXED_ERR(ffracdig)
17668
}
17669
}
17670
/*
17671
* SCC "fractionDigits less than or equal to totalDigits"
17672
*/
17673
if (! ftotdig)
17674
ftotdig = bftotdig;
17675
if (! ffracdig)
17676
ffracdig = bffracdig;
17677
if (ftotdig && ffracdig) {
17678
res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17679
if (res == -2)
17680
goto internal_error;
17681
if (res == 1)
17682
xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17683
-1, 1, 0);
17684
}
17685
/*
17686
* *Enumerations* won' be added here, since only the first set
17687
* of enumerations in the ancestor-or-self axis is used
17688
* for validation, plus we need to use the base type of those
17689
* enumerations for whitespace.
17690
*
17691
* *Patterns*: won't be add here, since they are ORed at
17692
* type level and ANDed at ancestor level. This will
17693
* happen during validation by walking the base axis
17694
* of the type.
17695
*/
17696
for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17697
bfacet = cur->facet;
17698
/*
17699
* Special handling of enumerations and patterns.
17700
* TODO: hmm, they should not appear in the set, so remove this.
17701
*/
17702
if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17703
(bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17704
continue;
17705
/*
17706
* Search for a duplicate facet in the current type.
17707
*/
17708
link = type->facetSet;
17709
/* err = 0; */
17710
/* fixedErr = 0; */
17711
while (link != NULL) {
17712
facet = link->facet;
17713
if (facet->type == bfacet->type) {
17714
switch (facet->type) {
17715
case XML_SCHEMA_FACET_WHITESPACE:
17716
/*
17717
* The whitespace must be stronger.
17718
*/
17719
if (facet->whitespace < bfacet->whitespace) {
17720
FACET_RESTR_ERR(facet,
17721
"The 'whitespace' value has to be equal to "
17722
"or stronger than the 'whitespace' value of "
17723
"the base type")
17724
}
17725
if ((bfacet->fixed) &&
17726
(facet->whitespace != bfacet->whitespace)) {
17727
FACET_RESTR_FIXED_ERR(facet)
17728
}
17729
break;
17730
default:
17731
break;
17732
}
17733
/* Duplicate found. */
17734
break;
17735
}
17736
link = link->next;
17737
}
17738
/*
17739
* If no duplicate was found: add the base types's facet
17740
* to the set.
17741
*/
17742
if (link == NULL) {
17743
link = (xmlSchemaFacetLinkPtr)
17744
xmlMalloc(sizeof(xmlSchemaFacetLink));
17745
if (link == NULL) {
17746
xmlSchemaPErrMemory(pctxt,
17747
"deriving facets, creating a facet link", NULL);
17748
return (-1);
17749
}
17750
link->facet = cur->facet;
17751
link->next = NULL;
17752
if (last == NULL)
17753
type->facetSet = link;
17754
else
17755
last->next = link;
17756
last = link;
17757
}
17758
17759
}
17760
17761
return (0);
17762
internal_error:
17763
PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17764
"an error occurred");
17765
return (-1);
17766
}
17767
17768
static int
17769
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17770
xmlSchemaTypePtr type)
17771
{
17772
xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17773
/*
17774
* The actual value is then formed by replacing any union type
17775
* definition in the `explicit members` with the members of their
17776
* {member type definitions}, in order.
17777
*
17778
* TODO: There's a bug entry at
17779
* "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17780
* which indicates that we'll keep the union types the future.
17781
*/
17782
link = type->memberTypes;
17783
while (link != NULL) {
17784
17785
if (WXS_IS_TYPE_NOT_FIXED(link->type))
17786
xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17787
17788
if (WXS_IS_UNION(link->type)) {
17789
subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17790
if (subLink != NULL) {
17791
link->type = subLink->type;
17792
if (subLink->next != NULL) {
17793
lastLink = link->next;
17794
subLink = subLink->next;
17795
prevLink = link;
17796
while (subLink != NULL) {
17797
newLink = (xmlSchemaTypeLinkPtr)
17798
xmlMalloc(sizeof(xmlSchemaTypeLink));
17799
if (newLink == NULL) {
17800
xmlSchemaPErrMemory(pctxt, "allocating a type link",
17801
NULL);
17802
return (-1);
17803
}
17804
newLink->type = subLink->type;
17805
prevLink->next = newLink;
17806
prevLink = newLink;
17807
newLink->next = lastLink;
17808
17809
subLink = subLink->next;
17810
}
17811
}
17812
}
17813
}
17814
link = link->next;
17815
}
17816
return (0);
17817
}
17818
17819
static void
17820
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17821
{
17822
int has = 0, needVal = 0, normVal = 0;
17823
17824
has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17825
if (has) {
17826
needVal = (type->baseType->flags &
17827
XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17828
normVal = (type->baseType->flags &
17829
XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17830
}
17831
if (type->facets != NULL) {
17832
xmlSchemaFacetPtr fac;
17833
17834
for (fac = type->facets; fac != NULL; fac = fac->next) {
17835
switch (fac->type) {
17836
case XML_SCHEMA_FACET_WHITESPACE:
17837
break;
17838
case XML_SCHEMA_FACET_PATTERN:
17839
normVal = 1;
17840
has = 1;
17841
break;
17842
case XML_SCHEMA_FACET_ENUMERATION:
17843
needVal = 1;
17844
normVal = 1;
17845
has = 1;
17846
break;
17847
default:
17848
has = 1;
17849
break;
17850
}
17851
}
17852
}
17853
if (normVal)
17854
type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17855
if (needVal)
17856
type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17857
if (has)
17858
type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17859
17860
if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17861
xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17862
/*
17863
* OPTIMIZE VAL TODO: Some facets need a computed value.
17864
*/
17865
if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17866
(prim->builtInType != XML_SCHEMAS_STRING)) {
17867
type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17868
}
17869
}
17870
}
17871
17872
static int
17873
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17874
{
17875
17876
17877
/*
17878
* Evaluate the whitespace-facet value.
17879
*/
17880
if (WXS_IS_LIST(type)) {
17881
type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17882
return (0);
17883
} else if (WXS_IS_UNION(type))
17884
return (0);
17885
17886
if (type->facetSet != NULL) {
17887
xmlSchemaFacetLinkPtr lin;
17888
17889
for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17890
if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17891
switch (lin->facet->whitespace) {
17892
case XML_SCHEMAS_FACET_PRESERVE:
17893
type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17894
break;
17895
case XML_SCHEMAS_FACET_REPLACE:
17896
type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17897
break;
17898
case XML_SCHEMAS_FACET_COLLAPSE:
17899
type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17900
break;
17901
default:
17902
return (-1);
17903
}
17904
return (0);
17905
}
17906
}
17907
}
17908
/*
17909
* For all `atomic` datatypes other than string (and types `derived`
17910
* by `restriction` from it) the value of whiteSpace is fixed to
17911
* collapse
17912
*/
17913
{
17914
xmlSchemaTypePtr anc;
17915
17916
for (anc = type->baseType; anc != NULL &&
17917
anc->builtInType != XML_SCHEMAS_ANYTYPE;
17918
anc = anc->baseType) {
17919
17920
if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17921
if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17922
type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17923
17924
} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17925
(anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17926
type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17927
17928
} else
17929
type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17930
break;
17931
}
17932
}
17933
}
17934
return (0);
17935
}
17936
17937
static int
17938
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17939
xmlSchemaTypePtr type)
17940
{
17941
if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17942
return(0);
17943
if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17944
return(0);
17945
type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17946
17947
if (WXS_IS_LIST(type)) {
17948
/*
17949
* Corresponds to <simpleType><list>...
17950
*/
17951
if (type->subtypes == NULL) {
17952
/*
17953
* This one is really needed, so get out.
17954
*/
17955
PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17956
"list type has no item-type assigned");
17957
return(-1);
17958
}
17959
} else if (WXS_IS_UNION(type)) {
17960
/*
17961
* Corresponds to <simpleType><union>...
17962
*/
17963
if (type->memberTypes == NULL) {
17964
/*
17965
* This one is really needed, so get out.
17966
*/
17967
PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17968
"union type has no member-types assigned");
17969
return(-1);
17970
}
17971
} else {
17972
/*
17973
* Corresponds to <simpleType><restriction>...
17974
*/
17975
if (type->baseType == NULL) {
17976
PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17977
"type has no base-type assigned");
17978
return(-1);
17979
}
17980
if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17981
if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17982
return(-1);
17983
/*
17984
* Variety
17985
* If the <restriction> alternative is chosen, then the
17986
* {variety} of the {base type definition}.
17987
*/
17988
if (WXS_IS_ATOMIC(type->baseType))
17989
type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17990
else if (WXS_IS_LIST(type->baseType)) {
17991
type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17992
/*
17993
* Inherit the itemType.
17994
*/
17995
type->subtypes = type->baseType->subtypes;
17996
} else if (WXS_IS_UNION(type->baseType)) {
17997
type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17998
/*
17999
* NOTE that we won't assign the memberTypes of the base,
18000
* since this will make trouble when freeing them; we will
18001
* use a lookup function to access them instead.
18002
*/
18003
}
18004
}
18005
return(0);
18006
}
18007
18008
/*
18009
* 3.14.6 Constraints on Simple Type Definition Schema Components
18010
*/
18011
static int
18012
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18013
xmlSchemaTypePtr type)
18014
{
18015
int res, olderrs = pctxt->nberrors;
18016
18017
if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18018
return(-1);
18019
18020
if (! WXS_IS_TYPE_NOT_FIXED(type))
18021
return(0);
18022
18023
type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18024
type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18025
18026
if (type->baseType == NULL) {
18027
PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18028
"missing baseType");
18029
goto exit_failure;
18030
}
18031
if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18032
xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18033
/*
18034
* If a member type of a union is a union itself, we need to substitute
18035
* that member type for its member types.
18036
* NOTE that this might change in WXS 1.1; i.e. we will keep the union
18037
* types in WXS 1.1.
18038
*/
18039
if ((type->memberTypes != NULL) &&
18040
(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18041
return(-1);
18042
/*
18043
* SPEC src-simple-type 1
18044
* "The corresponding simple type definition, if any, must satisfy
18045
* the conditions set out in Constraints on Simple Type Definition
18046
* Schema Components ($3.14.6)."
18047
*/
18048
/*
18049
* Schema Component Constraint: Simple Type Definition Properties Correct
18050
* (st-props-correct)
18051
*/
18052
res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18053
HFAILURE HERROR
18054
/*
18055
* Schema Component Constraint: Derivation Valid (Restriction, Simple)
18056
* (cos-st-restricts)
18057
*/
18058
res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18059
HFAILURE HERROR
18060
/*
18061
* TODO: Removed the error report, since it got annoying to get an
18062
* extra error report, if anything failed until now.
18063
* Enable this if needed.
18064
*
18065
* xmlSchemaPErr(ctxt, type->node,
18066
* XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18067
* "Simple type '%s' does not satisfy the constraints "
18068
* "on simple type definitions.\n",
18069
* type->name, NULL);
18070
*/
18071
/*
18072
* Schema Component Constraint: Simple Type Restriction (Facets)
18073
* (st-restrict-facets)
18074
*/
18075
res = xmlSchemaCheckFacetValues(type, pctxt);
18076
HFAILURE HERROR
18077
if ((type->facetSet != NULL) ||
18078
(type->baseType->facetSet != NULL)) {
18079
res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18080
HFAILURE HERROR
18081
}
18082
/*
18083
* Whitespace value.
18084
*/
18085
res = xmlSchemaTypeFixupWhitespace(type);
18086
HFAILURE HERROR
18087
xmlSchemaTypeFixupOptimFacets(type);
18088
18089
exit_error:
18090
if (olderrs != pctxt->nberrors)
18091
return(pctxt->err);
18092
return(0);
18093
18094
exit_failure:
18095
return(-1);
18096
}
18097
18098
static int
18099
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18100
xmlSchemaTypePtr type)
18101
{
18102
int res = 0, olderrs = pctxt->nberrors;
18103
xmlSchemaTypePtr baseType = type->baseType;
18104
18105
if (! WXS_IS_TYPE_NOT_FIXED(type))
18106
return(0);
18107
type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18108
if (baseType == NULL) {
18109
PERROR_INT("xmlSchemaFixupComplexType",
18110
"missing baseType");
18111
goto exit_failure;
18112
}
18113
/*
18114
* Fixup the base type.
18115
*/
18116
if (WXS_IS_TYPE_NOT_FIXED(baseType))
18117
xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18118
if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18119
/*
18120
* Skip fixup if the base type is invalid.
18121
* TODO: Generate a warning!
18122
*/
18123
return(0);
18124
}
18125
/*
18126
* This basically checks if the base type can be derived.
18127
*/
18128
res = xmlSchemaCheckSRCCT(pctxt, type);
18129
HFAILURE HERROR
18130
/*
18131
* Fixup the content type.
18132
*/
18133
if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18134
/*
18135
* Corresponds to <complexType><simpleContent>...
18136
*/
18137
if ((WXS_IS_COMPLEX(baseType)) &&
18138
(baseType->contentTypeDef != NULL) &&
18139
(WXS_IS_RESTRICTION(type))) {
18140
xmlSchemaTypePtr contentBase, content;
18141
#ifdef ENABLE_NAMED_LOCALS
18142
char buf[30];
18143
const xmlChar *tmpname;
18144
#endif
18145
/*
18146
* SPEC (1) If <restriction> + base type is <complexType>,
18147
* "whose own {content type} is a simple type..."
18148
*/
18149
if (type->contentTypeDef != NULL) {
18150
/*
18151
* SPEC (1.1) "the simple type definition corresponding to the
18152
* <simpleType> among the [children] of <restriction> if there
18153
* is one;"
18154
* Note that this "<simpleType> among the [children]" was put
18155
* into ->contentTypeDef during parsing.
18156
*/
18157
contentBase = type->contentTypeDef;
18158
type->contentTypeDef = NULL;
18159
} else {
18160
/*
18161
* (1.2) "...otherwise (<restriction> has no <simpleType>
18162
* among its [children]), the simple type definition which
18163
* is the {content type} of the ... base type."
18164
*/
18165
contentBase = baseType->contentTypeDef;
18166
}
18167
/*
18168
* SPEC
18169
* "... a simple type definition which restricts the simple
18170
* type definition identified in clause 1.1 or clause 1.2
18171
* with a set of facet components"
18172
*
18173
* Create the anonymous simple type, which will be the content
18174
* type of the complex type.
18175
*/
18176
#ifdef ENABLE_NAMED_LOCALS
18177
snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18178
tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18179
content = xmlSchemaAddType(pctxt, pctxt->schema,
18180
XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18181
type->node, 0);
18182
#else
18183
content = xmlSchemaAddType(pctxt, pctxt->schema,
18184
XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18185
type->node, 0);
18186
#endif
18187
if (content == NULL)
18188
goto exit_failure;
18189
/*
18190
* We will use the same node as for the <complexType>
18191
* to have it somehow anchored in the schema doc.
18192
*/
18193
content->type = XML_SCHEMA_TYPE_SIMPLE;
18194
content->baseType = contentBase;
18195
/*
18196
* Move the facets, previously anchored on the
18197
* complexType during parsing.
18198
*/
18199
content->facets = type->facets;
18200
type->facets = NULL;
18201
content->facetSet = type->facetSet;
18202
type->facetSet = NULL;
18203
18204
type->contentTypeDef = content;
18205
if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18206
xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18207
/*
18208
* Fixup the newly created type. We don't need to check
18209
* for circularity here.
18210
*/
18211
res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18212
HFAILURE HERROR
18213
res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18214
HFAILURE HERROR
18215
18216
} else if ((WXS_IS_COMPLEX(baseType)) &&
18217
(baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18218
(WXS_IS_RESTRICTION(type))) {
18219
/*
18220
* SPEC (2) If <restriction> + base is a mixed <complexType> with
18221
* an emptiable particle, then a simple type definition which
18222
* restricts the <restriction>'s <simpleType> child.
18223
*/
18224
if ((type->contentTypeDef == NULL) ||
18225
(type->contentTypeDef->baseType == NULL)) {
18226
/*
18227
* TODO: Check if this ever happens.
18228
*/
18229
xmlSchemaPCustomErr(pctxt,
18230
XML_SCHEMAP_INTERNAL,
18231
WXS_BASIC_CAST type, NULL,
18232
"Internal error: xmlSchemaTypeFixup, "
18233
"complex type '%s': the <simpleContent><restriction> "
18234
"is missing a <simpleType> child, but was not caught "
18235
"by xmlSchemaCheckSRCCT()", type->name);
18236
goto exit_failure;
18237
}
18238
} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18239
/*
18240
* SPEC (3) If <extension> + base is <complexType> with
18241
* <simpleType> content, "...then the {content type} of that
18242
* complex type definition"
18243
*/
18244
if (baseType->contentTypeDef == NULL) {
18245
/*
18246
* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18247
* should have caught this already.
18248
*/
18249
xmlSchemaPCustomErr(pctxt,
18250
XML_SCHEMAP_INTERNAL,
18251
WXS_BASIC_CAST type, NULL,
18252
"Internal error: xmlSchemaTypeFixup, "
18253
"complex type '%s': the <extension>ed base type is "
18254
"a complex type with no simple content type",
18255
type->name);
18256
goto exit_failure;
18257
}
18258
type->contentTypeDef = baseType->contentTypeDef;
18259
} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18260
/*
18261
* SPEC (4) <extension> + base is <simpleType>
18262
* "... then that simple type definition"
18263
*/
18264
type->contentTypeDef = baseType;
18265
} else {
18266
/*
18267
* TODO: Check if this ever happens.
18268
*/
18269
xmlSchemaPCustomErr(pctxt,
18270
XML_SCHEMAP_INTERNAL,
18271
WXS_BASIC_CAST type, NULL,
18272
"Internal error: xmlSchemaTypeFixup, "
18273
"complex type '%s' with <simpleContent>: unhandled "
18274
"derivation case", type->name);
18275
goto exit_failure;
18276
}
18277
} else {
18278
int dummySequence = 0;
18279
xmlSchemaParticlePtr particle =
18280
(xmlSchemaParticlePtr) type->subtypes;
18281
/*
18282
* Corresponds to <complexType><complexContent>...
18283
*
18284
* NOTE that the effective mixed was already set during parsing of
18285
* <complexType> and <complexContent>; its flag value is
18286
* XML_SCHEMAS_TYPE_MIXED.
18287
*
18288
* Compute the "effective content":
18289
* (2.1.1) + (2.1.2) + (2.1.3)
18290
*/
18291
if ((particle == NULL) ||
18292
((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18293
((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18294
(particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18295
((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18296
(particle->minOccurs == 0))) &&
18297
( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18298
if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18299
/*
18300
* SPEC (2.1.4) "If the `effective mixed` is true, then
18301
* a particle whose properties are as follows:..."
18302
*
18303
* Empty sequence model group with
18304
* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18305
* NOTE that we sill assign it the <complexType> node to
18306
* somehow anchor it in the doc.
18307
*/
18308
if ((particle == NULL) ||
18309
(particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18310
/*
18311
* Create the particle.
18312
*/
18313
particle = xmlSchemaAddParticle(pctxt,
18314
type->node, 1, 1);
18315
if (particle == NULL)
18316
goto exit_failure;
18317
/*
18318
* Create the model group.
18319
*/ /* URGENT TODO: avoid adding to pending items. */
18320
particle->children = (xmlSchemaTreeItemPtr)
18321
xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18322
XML_SCHEMA_TYPE_SEQUENCE, type->node);
18323
if (particle->children == NULL)
18324
goto exit_failure;
18325
18326
type->subtypes = (xmlSchemaTypePtr) particle;
18327
}
18328
dummySequence = 1;
18329
type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18330
} else {
18331
/*
18332
* SPEC (2.1.5) "otherwise empty"
18333
*/
18334
type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18335
}
18336
} else {
18337
/*
18338
* SPEC (2.2) "otherwise the particle corresponding to the
18339
* <all>, <choice>, <group> or <sequence> among the
18340
* [children]."
18341
*/
18342
type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18343
}
18344
/*
18345
* Compute the "content type".
18346
*/
18347
if (WXS_IS_RESTRICTION(type)) {
18348
/*
18349
* SPEC (3.1) "If <restriction>..."
18350
* (3.1.1) + (3.1.2) */
18351
if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18352
if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18353
type->contentType = XML_SCHEMA_CONTENT_MIXED;
18354
}
18355
} else {
18356
/*
18357
* SPEC (3.2) "If <extension>..."
18358
*/
18359
if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18360
/*
18361
* SPEC (3.2.1)
18362
* "If the `effective content` is empty, then the
18363
* {content type} of the [...] base ..."
18364
*/
18365
type->contentType = baseType->contentType;
18366
type->subtypes = baseType->subtypes;
18367
/*
18368
* Fixes bug #347316:
18369
* This is the case when the base type has a simple
18370
* type definition as content.
18371
*/
18372
type->contentTypeDef = baseType->contentTypeDef;
18373
/*
18374
* NOTE that the effective mixed is ignored here.
18375
*/
18376
} else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18377
/*
18378
* SPEC (3.2.2)
18379
*/
18380
if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18381
type->contentType = XML_SCHEMA_CONTENT_MIXED;
18382
} else {
18383
/*
18384
* SPEC (3.2.3)
18385
*/
18386
if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18387
type->contentType = XML_SCHEMA_CONTENT_MIXED;
18388
/*
18389
* "A model group whose {compositor} is sequence and whose
18390
* {particles} are..."
18391
*/
18392
if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18393
(WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18394
((WXS_TYPE_PARTICLE_TERM(type))->type ==
18395
XML_SCHEMA_TYPE_ALL))
18396
{
18397
/*
18398
* SPEC cos-all-limited (1)
18399
*/
18400
xmlSchemaCustomErr(ACTXT_CAST pctxt,
18401
/* TODO: error code */
18402
XML_SCHEMAP_COS_ALL_LIMITED,
18403
WXS_ITEM_NODE(type), NULL,
18404
"The type has an 'all' model group in its "
18405
"{content type} and thus cannot be derived from "
18406
"a non-empty type, since this would produce a "
18407
"'sequence' model group containing the 'all' "
18408
"model group; 'all' model groups are not "
18409
"allowed to appear inside other model groups",
18410
NULL, NULL);
18411
18412
} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18413
(WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18414
((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18415
XML_SCHEMA_TYPE_ALL))
18416
{
18417
/*
18418
* SPEC cos-all-limited (1)
18419
*/
18420
xmlSchemaCustomErr(ACTXT_CAST pctxt,
18421
/* TODO: error code */
18422
XML_SCHEMAP_COS_ALL_LIMITED,
18423
WXS_ITEM_NODE(type), NULL,
18424
"A type cannot be derived by extension from a type "
18425
"which has an 'all' model group in its "
18426
"{content type}, since this would produce a "
18427
"'sequence' model group containing the 'all' "
18428
"model group; 'all' model groups are not "
18429
"allowed to appear inside other model groups",
18430
NULL, NULL);
18431
18432
} else if ((!dummySequence) && (baseType->subtypes != NULL)) {
18433
xmlSchemaTreeItemPtr effectiveContent =
18434
(xmlSchemaTreeItemPtr) type->subtypes;
18435
/*
18436
* Create the particle.
18437
*/
18438
particle = xmlSchemaAddParticle(pctxt,
18439
type->node, 1, 1);
18440
if (particle == NULL)
18441
goto exit_failure;
18442
/*
18443
* Create the "sequence" model group.
18444
*/
18445
particle->children = (xmlSchemaTreeItemPtr)
18446
xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18447
XML_SCHEMA_TYPE_SEQUENCE, type->node);
18448
if (particle->children == NULL)
18449
goto exit_failure;
18450
WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18451
/*
18452
* SPEC "the particle of the {content type} of
18453
* the ... base ..."
18454
* Create a duplicate of the base type's particle
18455
* and assign its "term" to it.
18456
*/
18457
particle->children->children =
18458
(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18459
type->node,
18460
((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18461
((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18462
if (particle->children->children == NULL)
18463
goto exit_failure;
18464
particle = (xmlSchemaParticlePtr)
18465
particle->children->children;
18466
particle->children =
18467
((xmlSchemaParticlePtr) baseType->subtypes)->children;
18468
/*
18469
* SPEC "followed by the `effective content`."
18470
*/
18471
particle->next = effectiveContent;
18472
/*
18473
* This all will result in:
18474
* new-particle
18475
* --> new-sequence(
18476
* new-particle
18477
* --> base-model,
18478
* this-particle
18479
* --> this-model
18480
* )
18481
*/
18482
} else {
18483
/*
18484
* This is the case when there is already an empty
18485
* <sequence> with minOccurs==maxOccurs==1.
18486
* Just add the base types's content type.
18487
* NOTE that, although we miss to add an intermediate
18488
* <sequence>, this should produce no difference to
18489
* neither the regex compilation of the content model,
18490
* nor to the complex type constraints.
18491
*/
18492
particle->children->children =
18493
(xmlSchemaTreeItemPtr) baseType->subtypes;
18494
}
18495
}
18496
}
18497
}
18498
/*
18499
* Now fixup attribute uses:
18500
* - expand attr. group references
18501
* - intersect attribute wildcards
18502
* - inherit attribute uses of the base type
18503
* - inherit or union attr. wildcards if extending
18504
* - apply attr. use prohibitions if restricting
18505
*/
18506
res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18507
HFAILURE HERROR
18508
/*
18509
* Apply the complex type component constraints; this will not
18510
* check attributes, since this is done in
18511
* xmlSchemaFixupTypeAttributeUses().
18512
*/
18513
res = xmlSchemaCheckCTComponent(pctxt, type);
18514
HFAILURE HERROR
18515
18516
if (olderrs != pctxt->nberrors)
18517
return(pctxt->err);
18518
else
18519
return(0);
18520
18521
exit_error:
18522
type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18523
return(pctxt->err);
18524
18525
exit_failure:
18526
type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18527
return(-1);
18528
}
18529
18530
18531
/**
18532
* xmlSchemaTypeFixup:
18533
* @typeDecl: the schema type definition
18534
* @ctxt: the schema parser context
18535
*
18536
* Fixes the content model of the type.
18537
* URGENT TODO: We need an int result!
18538
*/
18539
static int
18540
xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18541
xmlSchemaAbstractCtxtPtr actxt)
18542
{
18543
if (type == NULL)
18544
return(0);
18545
if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18546
AERROR_INT("xmlSchemaTypeFixup",
18547
"this function needs a parser context");
18548
return(-1);
18549
}
18550
if (! WXS_IS_TYPE_NOT_FIXED(type))
18551
return(0);
18552
if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18553
return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18554
else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18555
return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18556
return(0);
18557
}
18558
18559
/**
18560
* xmlSchemaCheckFacet:
18561
* @facet: the facet
18562
* @typeDecl: the schema type definition
18563
* @pctxt: the schema parser context or NULL
18564
* @name: the optional name of the type
18565
*
18566
* Checks and computes the values of facets.
18567
*
18568
* Returns 0 if valid, a positive error code if not valid and
18569
* -1 in case of an internal or API error.
18570
*/
18571
int
18572
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18573
xmlSchemaTypePtr typeDecl,
18574
xmlSchemaParserCtxtPtr pctxt,
18575
const xmlChar * name ATTRIBUTE_UNUSED)
18576
{
18577
int ret = 0, ctxtGiven;
18578
18579
if ((facet == NULL) || (typeDecl == NULL))
18580
return(-1);
18581
/*
18582
* TODO: will the parser context be given if used from
18583
* the relaxNG module?
18584
*/
18585
if (pctxt == NULL)
18586
ctxtGiven = 0;
18587
else
18588
ctxtGiven = 1;
18589
18590
switch (facet->type) {
18591
case XML_SCHEMA_FACET_MININCLUSIVE:
18592
case XML_SCHEMA_FACET_MINEXCLUSIVE:
18593
case XML_SCHEMA_FACET_MAXINCLUSIVE:
18594
case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18595
case XML_SCHEMA_FACET_ENUMERATION: {
18596
/*
18597
* Okay we need to validate the value
18598
* at that point.
18599
*/
18600
xmlSchemaTypePtr base;
18601
18602
/* 4.3.5.5 Constraints on enumeration Schema Components
18603
* Schema Component Constraint: enumeration valid restriction
18604
* It is an `error` if any member of {value} is not in the
18605
* `value space` of {base type definition}.
18606
*
18607
* minInclusive, maxInclusive, minExclusive, maxExclusive:
18608
* The value `must` be in the
18609
* `value space` of the `base type`.
18610
*/
18611
/*
18612
* This function is intended to deliver a compiled value
18613
* on the facet. In this implementation of XML Schemata the
18614
* type holding a facet, won't be a built-in type.
18615
* Thus to ensure that other API
18616
* calls (relaxng) do work, if the given type is a built-in
18617
* type, we will assume that the given built-in type *is
18618
* already* the base type.
18619
*/
18620
if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18621
base = typeDecl->baseType;
18622
if (base == NULL) {
18623
PERROR_INT("xmlSchemaCheckFacet",
18624
"a type user derived type has no base type");
18625
return (-1);
18626
}
18627
} else
18628
base = typeDecl;
18629
18630
if (! ctxtGiven) {
18631
/*
18632
* A context is needed if called from RelaxNG.
18633
*/
18634
pctxt = xmlSchemaNewParserCtxt("*");
18635
if (pctxt == NULL)
18636
return (-1);
18637
}
18638
/*
18639
* NOTE: This call does not check the content nodes,
18640
* since they are not available:
18641
* facet->node is just the node holding the facet
18642
* definition, *not* the attribute holding the *value*
18643
* of the facet.
18644
*/
18645
ret = xmlSchemaVCheckCVCSimpleType(
18646
ACTXT_CAST pctxt, facet->node, base,
18647
facet->value, &(facet->val), 1, 1, 0);
18648
if (ret != 0) {
18649
if (ret < 0) {
18650
/* No error message for RelaxNG. */
18651
if (ctxtGiven) {
18652
xmlSchemaCustomErr(ACTXT_CAST pctxt,
18653
XML_SCHEMAP_INTERNAL, facet->node, NULL,
18654
"Internal error: xmlSchemaCheckFacet, "
18655
"failed to validate the value '%s' of the "
18656
"facet '%s' against the base type",
18657
facet->value, xmlSchemaFacetTypeToString(facet->type));
18658
}
18659
goto internal_error;
18660
}
18661
ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18662
/* No error message for RelaxNG. */
18663
if (ctxtGiven) {
18664
xmlChar *str = NULL;
18665
18666
xmlSchemaCustomErr(ACTXT_CAST pctxt,
18667
ret, facet->node, WXS_BASIC_CAST facet,
18668
"The value '%s' of the facet does not validate "
18669
"against the base type '%s'",
18670
facet->value,
18671
xmlSchemaFormatQName(&str,
18672
base->targetNamespace, base->name));
18673
FREE_AND_NULL(str);
18674
}
18675
goto exit;
18676
} else if (facet->val == NULL) {
18677
if (ctxtGiven) {
18678
PERROR_INT("xmlSchemaCheckFacet",
18679
"value was not computed");
18680
}
18681
TODO
18682
}
18683
break;
18684
}
18685
case XML_SCHEMA_FACET_PATTERN:
18686
facet->regexp = xmlRegexpCompile(facet->value);
18687
if (facet->regexp == NULL) {
18688
ret = XML_SCHEMAP_REGEXP_INVALID;
18689
/* No error message for RelaxNG. */
18690
if (ctxtGiven) {
18691
xmlSchemaCustomErr(ACTXT_CAST pctxt,
18692
ret, facet->node, WXS_BASIC_CAST typeDecl,
18693
"The value '%s' of the facet 'pattern' is not a "
18694
"valid regular expression",
18695
facet->value, NULL);
18696
}
18697
}
18698
break;
18699
case XML_SCHEMA_FACET_TOTALDIGITS:
18700
case XML_SCHEMA_FACET_FRACTIONDIGITS:
18701
case XML_SCHEMA_FACET_LENGTH:
18702
case XML_SCHEMA_FACET_MAXLENGTH:
18703
case XML_SCHEMA_FACET_MINLENGTH:
18704
18705
if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18706
ret = xmlSchemaValidatePredefinedType(
18707
xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18708
facet->value, &(facet->val));
18709
} else {
18710
ret = xmlSchemaValidatePredefinedType(
18711
xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18712
facet->value, &(facet->val));
18713
}
18714
if (ret != 0) {
18715
if (ret < 0) {
18716
/* No error message for RelaxNG. */
18717
if (ctxtGiven) {
18718
PERROR_INT("xmlSchemaCheckFacet",
18719
"validating facet value");
18720
}
18721
goto internal_error;
18722
}
18723
ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18724
/* No error message for RelaxNG. */
18725
if (ctxtGiven) {
18726
/* error code */
18727
xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18728
ret, facet->node, WXS_BASIC_CAST typeDecl,
18729
"The value '%s' of the facet '%s' is not a valid '%s'",
18730
facet->value,
18731
xmlSchemaFacetTypeToString(facet->type),
18732
(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18733
BAD_CAST "nonNegativeInteger" :
18734
BAD_CAST "positiveInteger",
18735
NULL);
18736
}
18737
}
18738
break;
18739
18740
case XML_SCHEMA_FACET_WHITESPACE:{
18741
if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18742
facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18743
} else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18744
facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18745
} else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18746
facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18747
} else {
18748
ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18749
/* No error message for RelaxNG. */
18750
if (ctxtGiven) {
18751
/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18752
xmlSchemaCustomErr(ACTXT_CAST pctxt,
18753
ret, facet->node, WXS_BASIC_CAST typeDecl,
18754
"The value '%s' of the facet 'whitespace' is not "
18755
"valid", facet->value, NULL);
18756
}
18757
}
18758
}
18759
default:
18760
break;
18761
}
18762
exit:
18763
if ((! ctxtGiven) && (pctxt != NULL))
18764
xmlSchemaFreeParserCtxt(pctxt);
18765
return (ret);
18766
internal_error:
18767
if ((! ctxtGiven) && (pctxt != NULL))
18768
xmlSchemaFreeParserCtxt(pctxt);
18769
return (-1);
18770
}
18771
18772
/**
18773
* xmlSchemaCheckFacetValues:
18774
* @typeDecl: the schema type definition
18775
* @ctxt: the schema parser context
18776
*
18777
* Checks the default values types, especially for facets
18778
*/
18779
static int
18780
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18781
xmlSchemaParserCtxtPtr pctxt)
18782
{
18783
int res, olderrs = pctxt->nberrors;
18784
const xmlChar *name = typeDecl->name;
18785
/*
18786
* NOTE: It is intended to use the facets list, instead
18787
* of facetSet.
18788
*/
18789
if (typeDecl->facets != NULL) {
18790
xmlSchemaFacetPtr facet = typeDecl->facets;
18791
18792
/*
18793
* Temporarily assign the "schema" to the validation context
18794
* of the parser context. This is needed for NOTATION validation.
18795
*/
18796
if (pctxt->vctxt == NULL) {
18797
if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18798
return(-1);
18799
}
18800
pctxt->vctxt->schema = pctxt->schema;
18801
while (facet != NULL) {
18802
res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18803
HFAILURE
18804
facet = facet->next;
18805
}
18806
pctxt->vctxt->schema = NULL;
18807
}
18808
if (olderrs != pctxt->nberrors)
18809
return(pctxt->err);
18810
return(0);
18811
exit_failure:
18812
return(-1);
18813
}
18814
18815
/**
18816
* xmlSchemaGetCircModelGrDefRef:
18817
* @ctxtMGroup: the searched model group
18818
* @selfMGroup: the second searched model group
18819
* @particle: the first particle
18820
*
18821
* This one is intended to be used by
18822
* xmlSchemaCheckGroupDefCircular only.
18823
*
18824
* Returns the particle with the circular model group definition reference,
18825
* otherwise NULL.
18826
*/
18827
static xmlSchemaTreeItemPtr
18828
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18829
xmlSchemaTreeItemPtr particle)
18830
{
18831
xmlSchemaTreeItemPtr circ = NULL;
18832
xmlSchemaTreeItemPtr term;
18833
xmlSchemaModelGroupDefPtr gdef;
18834
18835
for (; particle != NULL; particle = particle->next) {
18836
term = particle->children;
18837
if (term == NULL)
18838
continue;
18839
switch (term->type) {
18840
case XML_SCHEMA_TYPE_GROUP:
18841
gdef = (xmlSchemaModelGroupDefPtr) term;
18842
if (gdef == groupDef)
18843
return (particle);
18844
/*
18845
* Mark this model group definition to avoid infinite
18846
* recursion on circular references not yet examined.
18847
*/
18848
if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18849
continue;
18850
if (gdef->children != NULL) {
18851
gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18852
circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18853
gdef->children->children);
18854
gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18855
if (circ != NULL)
18856
return (circ);
18857
}
18858
break;
18859
case XML_SCHEMA_TYPE_SEQUENCE:
18860
case XML_SCHEMA_TYPE_CHOICE:
18861
case XML_SCHEMA_TYPE_ALL:
18862
circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18863
if (circ != NULL)
18864
return (circ);
18865
break;
18866
default:
18867
break;
18868
}
18869
}
18870
return (NULL);
18871
}
18872
18873
/**
18874
* xmlSchemaCheckGroupDefCircular:
18875
* @item: the model group definition
18876
* @ctxt: the parser context
18877
* @name: the name
18878
*
18879
* Checks for circular references to model group definitions.
18880
*/
18881
static void
18882
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18883
xmlSchemaParserCtxtPtr ctxt)
18884
{
18885
/*
18886
* Schema Component Constraint: Model Group Correct
18887
* 2 Circular groups are disallowed. That is, within the {particles}
18888
* of a group there must not be at any depth a particle whose {term}
18889
* is the group itself.
18890
*/
18891
if ((item == NULL) ||
18892
(item->type != XML_SCHEMA_TYPE_GROUP) ||
18893
(item->children == NULL))
18894
return;
18895
{
18896
xmlSchemaTreeItemPtr circ;
18897
18898
circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18899
if (circ != NULL) {
18900
xmlChar *str = NULL;
18901
/*
18902
* TODO: The error report is not adequate: this constraint
18903
* is defined for model groups but not definitions, but since
18904
* there cannot be any circular model groups without a model group
18905
* definition (if not using a construction API), we check those
18906
* definitions only.
18907
*/
18908
xmlSchemaPCustomErr(ctxt,
18909
XML_SCHEMAP_MG_PROPS_CORRECT_2,
18910
NULL, WXS_ITEM_NODE(circ),
18911
"Circular reference to the model group definition '%s' "
18912
"defined", xmlSchemaFormatQName(&str,
18913
item->targetNamespace, item->name));
18914
FREE_AND_NULL(str)
18915
/*
18916
* NOTE: We will cut the reference to avoid further
18917
* confusion of the processor. This is a fatal error.
18918
*/
18919
circ->children = NULL;
18920
}
18921
}
18922
}
18923
18924
/**
18925
* xmlSchemaModelGroupToModelGroupDefFixup:
18926
* @ctxt: the parser context
18927
* @mg: the model group
18928
*
18929
* Assigns the model group of model group definitions to the "term"
18930
* of the referencing particle.
18931
* In xmlSchemaResolveModelGroupParticleReferences the model group
18932
* definitions were assigned to the "term", since needed for the
18933
* circularity check.
18934
*
18935
* Schema Component Constraint:
18936
* All Group Limited (cos-all-limited) (1.2)
18937
*/
18938
static void
18939
xmlSchemaModelGroupToModelGroupDefFixup(
18940
xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18941
xmlSchemaModelGroupPtr mg)
18942
{
18943
xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18944
18945
while (particle != NULL) {
18946
if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18947
((WXS_PARTICLE_TERM(particle))->type !=
18948
XML_SCHEMA_TYPE_GROUP))
18949
{
18950
particle = WXS_PTC_CAST particle->next;
18951
continue;
18952
}
18953
if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18954
/*
18955
* TODO: Remove the particle.
18956
*/
18957
WXS_PARTICLE_TERM(particle) = NULL;
18958
particle = WXS_PTC_CAST particle->next;
18959
continue;
18960
}
18961
/*
18962
* Assign the model group to the {term} of the particle.
18963
*/
18964
WXS_PARTICLE_TERM(particle) =
18965
WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18966
18967
particle = WXS_PTC_CAST particle->next;
18968
}
18969
}
18970
18971
/**
18972
* xmlSchemaCheckAttrGroupCircularRecur:
18973
* @ctxtGr: the searched attribute group
18974
* @attr: the current attribute list to be processed
18975
*
18976
* This one is intended to be used by
18977
* xmlSchemaCheckAttrGroupCircular only.
18978
*
18979
* Returns the circular attribute group reference, otherwise NULL.
18980
*/
18981
static xmlSchemaQNameRefPtr
18982
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18983
xmlSchemaItemListPtr list)
18984
{
18985
xmlSchemaAttributeGroupPtr gr;
18986
xmlSchemaQNameRefPtr ref, circ;
18987
int i;
18988
/*
18989
* We will search for an attribute group reference which
18990
* references the context attribute group.
18991
*/
18992
for (i = 0; i < list->nbItems; i++) {
18993
ref = list->items[i];
18994
if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18995
(ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18996
(ref->item != NULL))
18997
{
18998
gr = WXS_ATTR_GROUP_CAST ref->item;
18999
if (gr == ctxtGr)
19000
return(ref);
19001
if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19002
continue;
19003
/*
19004
* Mark as visited to avoid infinite recursion on
19005
* circular references not yet examined.
19006
*/
19007
if ((gr->attrUses) &&
19008
(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19009
{
19010
gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19011
circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19012
(xmlSchemaItemListPtr) gr->attrUses);
19013
gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19014
if (circ != NULL)
19015
return (circ);
19016
}
19017
19018
}
19019
}
19020
return (NULL);
19021
}
19022
19023
/**
19024
* xmlSchemaCheckAttrGroupCircular:
19025
* attrGr: the attribute group definition
19026
* @ctxt: the parser context
19027
* @name: the name
19028
*
19029
* Checks for circular references of attribute groups.
19030
*/
19031
static int
19032
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19033
xmlSchemaParserCtxtPtr ctxt)
19034
{
19035
/*
19036
* Schema Representation Constraint:
19037
* Attribute Group Definition Representation OK
19038
* 3 Circular group reference is disallowed outside <redefine>.
19039
* That is, unless this element information item's parent is
19040
* <redefine>, then among the [children], if any, there must
19041
* not be an <attributeGroup> with ref [attribute] which resolves
19042
* to the component corresponding to this <attributeGroup>. Indirect
19043
* circularity is also ruled out. That is, when QName resolution
19044
* (Schema Document) ($3.15.3) is applied to a `QName` arising from
19045
* any <attributeGroup>s with a ref [attribute] among the [children],
19046
* it must not be the case that a `QName` is encountered at any depth
19047
* which resolves to the component corresponding to this <attributeGroup>.
19048
*/
19049
if (attrGr->attrUses == NULL)
19050
return(0);
19051
else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19052
return(0);
19053
else {
19054
xmlSchemaQNameRefPtr circ;
19055
19056
circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19057
(xmlSchemaItemListPtr) attrGr->attrUses);
19058
if (circ != NULL) {
19059
xmlChar *str = NULL;
19060
/*
19061
* TODO: Report the referenced attr group as QName.
19062
*/
19063
xmlSchemaPCustomErr(ctxt,
19064
XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19065
NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19066
"Circular reference to the attribute group '%s' "
19067
"defined", xmlSchemaGetComponentQName(&str, attrGr));
19068
FREE_AND_NULL(str);
19069
/*
19070
* NOTE: We will cut the reference to avoid further
19071
* confusion of the processor.
19072
* BADSPEC TODO: The spec should define how to process in this case.
19073
*/
19074
circ->item = NULL;
19075
return(ctxt->err);
19076
}
19077
}
19078
return(0);
19079
}
19080
19081
static int
19082
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19083
xmlSchemaAttributeGroupPtr attrGr);
19084
19085
/**
19086
* xmlSchemaExpandAttributeGroupRefs:
19087
* @pctxt: the parser context
19088
* @node: the node of the component holding the attribute uses
19089
* @completeWild: the intersected wildcard to be returned
19090
* @list: the attribute uses
19091
*
19092
* Substitutes contained attribute group references
19093
* for their attribute uses. Wildcards are intersected.
19094
* Attribute use prohibitions are removed from the list
19095
* and returned via the @prohibs list.
19096
* Pointlessness of attr. prohibs, if a matching attr. decl
19097
* is existent a well, are checked.
19098
*/
19099
static int
19100
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19101
xmlSchemaBasicItemPtr item,
19102
xmlSchemaWildcardPtr *completeWild,
19103
xmlSchemaItemListPtr list,
19104
xmlSchemaItemListPtr prohibs)
19105
{
19106
xmlSchemaAttributeGroupPtr gr;
19107
xmlSchemaAttributeUsePtr use;
19108
xmlSchemaItemListPtr sublist;
19109
int i, j;
19110
int created = (*completeWild == NULL) ? 0 : 1;
19111
19112
if (prohibs)
19113
prohibs->nbItems = 0;
19114
19115
for (i = 0; i < list->nbItems; i++) {
19116
use = list->items[i];
19117
19118
if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19119
if (prohibs == NULL) {
19120
PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19121
"unexpected attr prohibition found");
19122
return(-1);
19123
}
19124
/*
19125
* Remove from attribute uses.
19126
*/
19127
if (xmlSchemaItemListRemove(list, i) == -1)
19128
return(-1);
19129
i--;
19130
/*
19131
* Note that duplicate prohibitions were already
19132
* handled at parsing time.
19133
*/
19134
/*
19135
* Add to list of prohibitions.
19136
*/
19137
xmlSchemaItemListAddSize(prohibs, 2, use);
19138
continue;
19139
}
19140
if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19141
((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19142
{
19143
if ((WXS_QNAME_CAST use)->item == NULL)
19144
return(-1);
19145
gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19146
/*
19147
* Expand the referenced attr. group.
19148
* TODO: remove this, this is done in a previous step, so
19149
* already done here.
19150
*/
19151
if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19152
if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19153
return(-1);
19154
}
19155
/*
19156
* Build the 'complete' wildcard; i.e. intersect multiple
19157
* wildcards.
19158
*/
19159
if (gr->attributeWildcard != NULL) {
19160
if (*completeWild == NULL) {
19161
*completeWild = gr->attributeWildcard;
19162
} else {
19163
if (! created) {
19164
xmlSchemaWildcardPtr tmpWild;
19165
19166
/*
19167
* Copy the first encountered wildcard as context,
19168
* except for the annotation.
19169
*
19170
* Although the complete wildcard might not correspond
19171
* to any node in the schema, we will anchor it on
19172
* the node of the owner component.
19173
*/
19174
tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19175
XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19176
WXS_ITEM_NODE(item));
19177
if (tmpWild == NULL)
19178
return(-1);
19179
if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19180
tmpWild, *completeWild) == -1)
19181
return (-1);
19182
tmpWild->processContents = (*completeWild)->processContents;
19183
*completeWild = tmpWild;
19184
created = 1;
19185
}
19186
19187
if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19188
gr->attributeWildcard) == -1)
19189
return(-1);
19190
}
19191
}
19192
/*
19193
* Just remove the reference if the referenced group does not
19194
* contain any attribute uses.
19195
*/
19196
sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19197
if ((sublist == NULL) || sublist->nbItems == 0) {
19198
if (xmlSchemaItemListRemove(list, i) == -1)
19199
return(-1);
19200
i--;
19201
continue;
19202
}
19203
/*
19204
* Add the attribute uses.
19205
*/
19206
list->items[i] = sublist->items[0];
19207
if (sublist->nbItems != 1) {
19208
for (j = 1; j < sublist->nbItems; j++) {
19209
i++;
19210
if (xmlSchemaItemListInsert(list,
19211
sublist->items[j], i) == -1)
19212
return(-1);
19213
}
19214
}
19215
}
19216
19217
}
19218
/*
19219
* Handle pointless prohibitions of declared attributes.
19220
*/
19221
if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19222
xmlSchemaAttributeUseProhibPtr prohib;
19223
19224
for (i = prohibs->nbItems -1; i >= 0; i--) {
19225
prohib = prohibs->items[i];
19226
for (j = 0; j < list->nbItems; j++) {
19227
use = list->items[j];
19228
19229
if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19230
(prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19231
{
19232
xmlChar *str = NULL;
19233
19234
xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19235
XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19236
prohib->node, NULL,
19237
"Skipping pointless attribute use prohibition "
19238
"'%s', since a corresponding attribute use "
19239
"exists already in the type definition",
19240
xmlSchemaFormatQName(&str,
19241
prohib->targetNamespace, prohib->name),
19242
NULL, NULL);
19243
FREE_AND_NULL(str);
19244
/*
19245
* Remove the prohibition.
19246
*/
19247
if (xmlSchemaItemListRemove(prohibs, i) == -1)
19248
return(-1);
19249
break;
19250
}
19251
}
19252
}
19253
}
19254
return(0);
19255
}
19256
19257
/**
19258
* xmlSchemaAttributeGroupExpandRefs:
19259
* @pctxt: the parser context
19260
* @attrGr: the attribute group definition
19261
*
19262
* Computation of:
19263
* {attribute uses} property
19264
* {attribute wildcard} property
19265
*
19266
* Substitutes contained attribute group references
19267
* for their attribute uses. Wildcards are intersected.
19268
*/
19269
static int
19270
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19271
xmlSchemaAttributeGroupPtr attrGr)
19272
{
19273
if ((attrGr->attrUses == NULL) ||
19274
(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19275
return(0);
19276
19277
attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19278
if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19279
&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19280
return(-1);
19281
return(0);
19282
}
19283
19284
/**
19285
* xmlSchemaAttributeGroupExpandRefs:
19286
* @pctxt: the parser context
19287
* @attrGr: the attribute group definition
19288
*
19289
* Substitutes contained attribute group references
19290
* for their attribute uses. Wildcards are intersected.
19291
*
19292
* Schema Component Constraint:
19293
* Attribute Group Definition Properties Correct (ag-props-correct)
19294
*/
19295
static int
19296
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19297
xmlSchemaAttributeGroupPtr attrGr)
19298
{
19299
/*
19300
* SPEC ag-props-correct
19301
* (1) "The values of the properties of an attribute group definition
19302
* must be as described in the property tableau in The Attribute
19303
* Group Definition Schema Component ($3.6.1), modulo the impact of
19304
* Missing Sub-components ($5.3);"
19305
*/
19306
19307
if ((attrGr->attrUses != NULL) &&
19308
(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19309
{
19310
xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19311
xmlSchemaAttributeUsePtr use, tmp;
19312
int i, j, hasId = 0;
19313
19314
for (i = uses->nbItems -1; i >= 0; i--) {
19315
use = uses->items[i];
19316
/*
19317
* SPEC ag-props-correct
19318
* (2) "Two distinct members of the {attribute uses} must not have
19319
* {attribute declaration}s both of whose {name}s match and whose
19320
* {target namespace}s are identical."
19321
*/
19322
if (i > 0) {
19323
for (j = i -1; j >= 0; j--) {
19324
tmp = uses->items[j];
19325
if ((WXS_ATTRUSE_DECL_NAME(use) ==
19326
WXS_ATTRUSE_DECL_NAME(tmp)) &&
19327
(WXS_ATTRUSE_DECL_TNS(use) ==
19328
WXS_ATTRUSE_DECL_TNS(tmp)))
19329
{
19330
xmlChar *str = NULL;
19331
19332
xmlSchemaCustomErr(ACTXT_CAST pctxt,
19333
XML_SCHEMAP_AG_PROPS_CORRECT,
19334
attrGr->node, WXS_BASIC_CAST attrGr,
19335
"Duplicate %s",
19336
xmlSchemaGetComponentDesignation(&str, use),
19337
NULL);
19338
FREE_AND_NULL(str);
19339
/*
19340
* Remove the duplicate.
19341
*/
19342
if (xmlSchemaItemListRemove(uses, i) == -1)
19343
return(-1);
19344
goto next_use;
19345
}
19346
}
19347
}
19348
/*
19349
* SPEC ag-props-correct
19350
* (3) "Two distinct members of the {attribute uses} must not have
19351
* {attribute declaration}s both of whose {type definition}s are or
19352
* are derived from ID."
19353
* TODO: Does 'derived' include member-types of unions?
19354
*/
19355
if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19356
if (xmlSchemaIsDerivedFromBuiltInType(
19357
WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19358
{
19359
if (hasId) {
19360
xmlChar *str = NULL;
19361
19362
xmlSchemaCustomErr(ACTXT_CAST pctxt,
19363
XML_SCHEMAP_AG_PROPS_CORRECT,
19364
attrGr->node, WXS_BASIC_CAST attrGr,
19365
"There must not exist more than one attribute "
19366
"declaration of type 'xs:ID' "
19367
"(or derived from 'xs:ID'). The %s violates this "
19368
"constraint",
19369
xmlSchemaGetComponentDesignation(&str, use),
19370
NULL);
19371
FREE_AND_NULL(str);
19372
if (xmlSchemaItemListRemove(uses, i) == -1)
19373
return(-1);
19374
}
19375
hasId = 1;
19376
}
19377
}
19378
next_use: {}
19379
}
19380
}
19381
return(0);
19382
}
19383
19384
/**
19385
* xmlSchemaResolveAttrGroupReferences:
19386
* @attrgrpDecl: the schema attribute definition
19387
* @ctxt: the schema parser context
19388
* @name: the attribute name
19389
*
19390
* Resolves references to attribute group definitions.
19391
*/
19392
static int
19393
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19394
xmlSchemaParserCtxtPtr ctxt)
19395
{
19396
xmlSchemaAttributeGroupPtr group;
19397
19398
if (ref->item != NULL)
19399
return(0);
19400
group = xmlSchemaGetAttributeGroup(ctxt->schema,
19401
ref->name,
19402
ref->targetNamespace);
19403
if (group == NULL) {
19404
xmlSchemaPResCompAttrErr(ctxt,
19405
XML_SCHEMAP_SRC_RESOLVE,
19406
NULL, ref->node,
19407
"ref", ref->name, ref->targetNamespace,
19408
ref->itemType, NULL);
19409
return(ctxt->err);
19410
}
19411
ref->item = WXS_BASIC_CAST group;
19412
return(0);
19413
}
19414
19415
/**
19416
* xmlSchemaCheckAttrPropsCorrect:
19417
* @item: an schema attribute declaration/use
19418
* @ctxt: a schema parser context
19419
* @name: the name of the attribute
19420
*
19421
*
19422
* Schema Component Constraint:
19423
* Attribute Declaration Properties Correct (a-props-correct)
19424
*
19425
* Validates the value constraints of an attribute declaration/use.
19426
* NOTE that this needs the simple type definitions to be already
19427
* built and checked.
19428
*/
19429
static int
19430
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19431
xmlSchemaAttributePtr attr)
19432
{
19433
19434
/*
19435
* SPEC a-props-correct (1)
19436
* "The values of the properties of an attribute declaration must
19437
* be as described in the property tableau in The Attribute
19438
* Declaration Schema Component ($3.2.1), modulo the impact of
19439
* Missing Sub-components ($5.3)."
19440
*/
19441
19442
if (WXS_ATTR_TYPEDEF(attr) == NULL)
19443
return(0);
19444
19445
if (attr->defValue != NULL) {
19446
int ret;
19447
19448
/*
19449
* SPEC a-props-correct (3)
19450
* "If the {type definition} is or is derived from ID then there
19451
* must not be a {value constraint}."
19452
*/
19453
if (xmlSchemaIsDerivedFromBuiltInType(
19454
WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19455
{
19456
xmlSchemaCustomErr(ACTXT_CAST pctxt,
19457
XML_SCHEMAP_A_PROPS_CORRECT_3,
19458
NULL, WXS_BASIC_CAST attr,
19459
"Value constraints are not allowed if the type definition "
19460
"is or is derived from xs:ID",
19461
NULL, NULL);
19462
return(pctxt->err);
19463
}
19464
/*
19465
* SPEC a-props-correct (2)
19466
* "if there is a {value constraint}, the canonical lexical
19467
* representation of its value must be `valid` with respect
19468
* to the {type definition} as defined in String Valid ($3.14.4)."
19469
* TODO: Don't care about the *canonical* stuff here, this requirement
19470
* will be removed in WXS 1.1 anyway.
19471
*/
19472
ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19473
attr->node, WXS_ATTR_TYPEDEF(attr),
19474
attr->defValue, &(attr->defVal),
19475
1, 1, 0);
19476
if (ret != 0) {
19477
if (ret < 0) {
19478
PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19479
"calling xmlSchemaVCheckCVCSimpleType()");
19480
return(-1);
19481
}
19482
xmlSchemaCustomErr(ACTXT_CAST pctxt,
19483
XML_SCHEMAP_A_PROPS_CORRECT_2,
19484
NULL, WXS_BASIC_CAST attr,
19485
"The value of the value constraint is not valid",
19486
NULL, NULL);
19487
return(pctxt->err);
19488
}
19489
}
19490
19491
return(0);
19492
}
19493
19494
static xmlSchemaElementPtr
19495
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19496
xmlSchemaElementPtr ancestor)
19497
{
19498
xmlSchemaElementPtr ret;
19499
19500
if (WXS_SUBST_HEAD(ancestor) == NULL)
19501
return (NULL);
19502
if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19503
return (ancestor);
19504
19505
if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19506
return (NULL);
19507
WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19508
ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19509
WXS_SUBST_HEAD(ancestor));
19510
WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19511
19512
return (ret);
19513
}
19514
19515
/**
19516
* xmlSchemaCheckElemPropsCorrect:
19517
* @ctxt: a schema parser context
19518
* @decl: the element declaration
19519
* @name: the name of the attribute
19520
*
19521
* Schema Component Constraint:
19522
* Element Declaration Properties Correct (e-props-correct)
19523
*
19524
* STATUS:
19525
* missing: (6)
19526
*/
19527
static int
19528
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19529
xmlSchemaElementPtr elemDecl)
19530
{
19531
int ret = 0;
19532
xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19533
/*
19534
* SPEC (1) "The values of the properties of an element declaration
19535
* must be as described in the property tableau in The Element
19536
* Declaration Schema Component ($3.3.1), modulo the impact of Missing
19537
* Sub-components ($5.3)."
19538
*/
19539
if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19540
xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19541
19542
xmlSchemaCheckElementDeclComponent(head, pctxt);
19543
/*
19544
* SPEC (3) "If there is a non-`absent` {substitution group
19545
* affiliation}, then {scope} must be global."
19546
*/
19547
if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19548
xmlSchemaPCustomErr(pctxt,
19549
XML_SCHEMAP_E_PROPS_CORRECT_3,
19550
WXS_BASIC_CAST elemDecl, NULL,
19551
"Only global element declarations can have a "
19552
"substitution group affiliation", NULL);
19553
ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19554
}
19555
/*
19556
* TODO: SPEC (6) "Circular substitution groups are disallowed.
19557
* That is, it must not be possible to return to an element declaration
19558
* by repeatedly following the {substitution group affiliation}
19559
* property."
19560
*/
19561
if (head == elemDecl)
19562
circ = head;
19563
else if (WXS_SUBST_HEAD(head) != NULL)
19564
circ = xmlSchemaCheckSubstGroupCircular(head, head);
19565
else
19566
circ = NULL;
19567
if (circ != NULL) {
19568
xmlChar *strA = NULL, *strB = NULL;
19569
19570
xmlSchemaPCustomErrExt(pctxt,
19571
XML_SCHEMAP_E_PROPS_CORRECT_6,
19572
WXS_BASIC_CAST circ, NULL,
19573
"The element declaration '%s' defines a circular "
19574
"substitution group to element declaration '%s'",
19575
xmlSchemaGetComponentQName(&strA, circ),
19576
xmlSchemaGetComponentQName(&strB, head),
19577
NULL);
19578
FREE_AND_NULL(strA)
19579
FREE_AND_NULL(strB)
19580
ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19581
}
19582
/*
19583
* SPEC (4) "If there is a {substitution group affiliation},
19584
* the {type definition}
19585
* of the element declaration must be validly derived from the {type
19586
* definition} of the {substitution group affiliation}, given the value
19587
* of the {substitution group exclusions} of the {substitution group
19588
* affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19589
* (if the {type definition} is complex) or as defined in
19590
* Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19591
* simple)."
19592
*
19593
* NOTE: {substitution group exclusions} means the values of the
19594
* attribute "final".
19595
*/
19596
19597
if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19598
int set = 0;
19599
19600
if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19601
set |= SUBSET_EXTENSION;
19602
if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19603
set |= SUBSET_RESTRICTION;
19604
19605
if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19606
WXS_ELEM_TYPEDEF(head), set) != 0) {
19607
xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19608
19609
ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19610
xmlSchemaPCustomErrExt(pctxt,
19611
XML_SCHEMAP_E_PROPS_CORRECT_4,
19612
WXS_BASIC_CAST elemDecl, NULL,
19613
"The type definition '%s' was "
19614
"either rejected by the substitution group "
19615
"affiliation '%s', or not validly derived from its type "
19616
"definition '%s'",
19617
xmlSchemaGetComponentQName(&strA, typeDef),
19618
xmlSchemaGetComponentQName(&strB, head),
19619
xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19620
FREE_AND_NULL(strA)
19621
FREE_AND_NULL(strB)
19622
FREE_AND_NULL(strC)
19623
}
19624
}
19625
}
19626
/*
19627
* SPEC (5) "If the {type definition} or {type definition}'s
19628
* {content type}
19629
* is or is derived from ID then there must not be a {value constraint}.
19630
* Note: The use of ID as a type definition for elements goes beyond
19631
* XML 1.0, and should be avoided if backwards compatibility is desired"
19632
*/
19633
if ((elemDecl->value != NULL) &&
19634
((WXS_IS_SIMPLE(typeDef) &&
19635
xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19636
(WXS_IS_COMPLEX(typeDef) &&
19637
WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19638
xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19639
XML_SCHEMAS_ID)))) {
19640
19641
ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19642
xmlSchemaPCustomErr(pctxt,
19643
XML_SCHEMAP_E_PROPS_CORRECT_5,
19644
WXS_BASIC_CAST elemDecl, NULL,
19645
"The type definition (or type definition's content type) is or "
19646
"is derived from ID; value constraints are not allowed in "
19647
"conjunction with such a type definition", NULL);
19648
} else if (elemDecl->value != NULL) {
19649
int vcret;
19650
xmlNodePtr node = NULL;
19651
19652
/*
19653
* SPEC (2) "If there is a {value constraint}, the canonical lexical
19654
* representation of its value must be `valid` with respect to the
19655
* {type definition} as defined in Element Default Valid (Immediate)
19656
* ($3.3.6)."
19657
*/
19658
if (typeDef == NULL) {
19659
xmlSchemaPErr(pctxt, elemDecl->node,
19660
XML_SCHEMAP_INTERNAL,
19661
"Internal error: xmlSchemaCheckElemPropsCorrect, "
19662
"type is missing... skipping validation of "
19663
"the value constraint", NULL, NULL);
19664
return (-1);
19665
}
19666
if (elemDecl->node != NULL) {
19667
if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19668
node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19669
BAD_CAST "fixed");
19670
else
19671
node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19672
BAD_CAST "default");
19673
}
19674
vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19675
typeDef, elemDecl->value, &(elemDecl->defVal));
19676
if (vcret != 0) {
19677
if (vcret < 0) {
19678
PERROR_INT("xmlSchemaElemCheckValConstr",
19679
"failed to validate the value constraint of an "
19680
"element declaration");
19681
return (-1);
19682
}
19683
return (vcret);
19684
}
19685
}
19686
19687
return (ret);
19688
}
19689
19690
/**
19691
* xmlSchemaCheckElemSubstGroup:
19692
* @ctxt: a schema parser context
19693
* @decl: the element declaration
19694
* @name: the name of the attribute
19695
*
19696
* Schema Component Constraint:
19697
* Substitution Group (cos-equiv-class)
19698
*
19699
* In Libxml2 the subst. groups will be precomputed, in terms of that
19700
* a list will be built for each subst. group head, holding all direct
19701
* referents to this head.
19702
* NOTE that this function needs:
19703
* 1. circular subst. groups to be checked beforehand
19704
* 2. the declaration's type to be derived from the head's type
19705
*
19706
* STATUS:
19707
*
19708
*/
19709
static void
19710
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19711
xmlSchemaElementPtr elemDecl)
19712
{
19713
if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19714
/* SPEC (1) "Its {abstract} is false." */
19715
(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19716
return;
19717
{
19718
xmlSchemaElementPtr head;
19719
xmlSchemaTypePtr headType, type;
19720
int set, methSet;
19721
/*
19722
* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19723
* {disallowed substitutions} as the blocking constraint, as defined in
19724
* Substitution Group OK (Transitive) ($3.3.6)."
19725
*/
19726
for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19727
head = WXS_SUBST_HEAD(head)) {
19728
set = 0;
19729
methSet = 0;
19730
/*
19731
* The blocking constraints.
19732
*/
19733
if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19734
continue;
19735
headType = head->subtypes;
19736
type = elemDecl->subtypes;
19737
if (headType == type)
19738
goto add_member;
19739
if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19740
set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19741
if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19742
set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19743
/*
19744
* SPEC: Substitution Group OK (Transitive) (2.3)
19745
* "The set of all {derivation method}s involved in the
19746
* derivation of D's {type definition} from C's {type definition}
19747
* does not intersect with the union of the blocking constraint,
19748
* C's {prohibited substitutions} (if C is complex, otherwise the
19749
* empty set) and the {prohibited substitutions} (respectively the
19750
* empty set) of any intermediate {type definition}s in the
19751
* derivation of D's {type definition} from C's {type definition}."
19752
*/
19753
/*
19754
* OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19755
* subst.head axis, the methSet does not need to be computed for
19756
* the full depth over and over.
19757
*/
19758
/*
19759
* The set of all {derivation method}s involved in the derivation
19760
*/
19761
while ((type != NULL) && (type != headType) &&
19762
(type != type->baseType)) {
19763
if ((WXS_IS_EXTENSION(type)) &&
19764
((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19765
methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19766
19767
if (WXS_IS_RESTRICTION(type) &&
19768
((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19769
methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19770
19771
type = type->baseType;
19772
}
19773
/*
19774
* The {prohibited substitutions} of all intermediate types +
19775
* the head's type.
19776
*/
19777
type = elemDecl->subtypes->baseType;
19778
while (type != NULL) {
19779
if (WXS_IS_COMPLEX(type)) {
19780
if ((type->flags &
19781
XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19782
((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19783
set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19784
if ((type->flags &
19785
XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19786
((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19787
set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19788
} else
19789
break;
19790
if (type == headType)
19791
break;
19792
type = type->baseType;
19793
}
19794
if ((set != 0) &&
19795
(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19796
(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19797
((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19798
(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19799
continue;
19800
}
19801
add_member:
19802
xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19803
if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19804
head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19805
}
19806
}
19807
}
19808
19809
#ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19810
/**
19811
* xmlSchemaCheckElementDeclComponent
19812
* @pctxt: the schema parser context
19813
* @ctxtComponent: the context component (an element declaration)
19814
* @ctxtParticle: the first particle of the context component
19815
* @searchParticle: the element declaration particle to be analysed
19816
*
19817
* Schema Component Constraint: Element Declarations Consistent
19818
*/
19819
static int
19820
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19821
xmlSchemaBasicItemPtr ctxtComponent,
19822
xmlSchemaParticlePtr ctxtParticle,
19823
xmlSchemaParticlePtr searchParticle,
19824
xmlSchemaParticlePtr curParticle,
19825
int search)
19826
{
19827
return(0);
19828
19829
int ret = 0;
19830
xmlSchemaParticlePtr cur = curParticle;
19831
if (curParticle == NULL) {
19832
return(0);
19833
}
19834
if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19835
/*
19836
* Just return in this case. A missing "term" of the particle
19837
* might arise due to an invalid "term" component.
19838
*/
19839
return(0);
19840
}
19841
while (cur != NULL) {
19842
switch (WXS_PARTICLE_TERM(cur)->type) {
19843
case XML_SCHEMA_TYPE_ANY:
19844
break;
19845
case XML_SCHEMA_TYPE_ELEMENT:
19846
if (search == 0) {
19847
ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19848
ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19849
if (ret != 0)
19850
return(ret);
19851
} else {
19852
xmlSchemaElementPtr elem =
19853
WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19854
/*
19855
* SPEC Element Declarations Consistent:
19856
* "If the {particles} contains, either directly,
19857
* indirectly (that is, within the {particles} of a
19858
* contained model group, recursively) or `implicitly`
19859
* two or more element declaration particles with
19860
* the same {name} and {target namespace}, then
19861
* all their type definitions must be the same
19862
* top-level definition [...]"
19863
*/
19864
if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19865
WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19866
xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19867
WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19868
{
19869
xmlChar *strA = NULL, *strB = NULL;
19870
19871
xmlSchemaCustomErr(ACTXT_CAST pctxt,
19872
/* TODO: error code */
19873
XML_SCHEMAP_COS_NONAMBIG,
19874
WXS_ITEM_NODE(cur), NULL,
19875
"In the content model of %s, there are multiple "
19876
"element declarations for '%s' with different "
19877
"type definitions",
19878
xmlSchemaGetComponentDesignation(&strA,
19879
ctxtComponent),
19880
xmlSchemaFormatQName(&strB,
19881
WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19882
WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19883
FREE_AND_NULL(strA);
19884
FREE_AND_NULL(strB);
19885
return(XML_SCHEMAP_COS_NONAMBIG);
19886
}
19887
}
19888
break;
19889
case XML_SCHEMA_TYPE_SEQUENCE: {
19890
break;
19891
}
19892
case XML_SCHEMA_TYPE_CHOICE:{
19893
/*
19894
xmlSchemaTreeItemPtr sub;
19895
19896
sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
19897
while (sub != NULL) {
19898
ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19899
ctxtParticle, ctxtElem);
19900
if (ret != 0)
19901
return(ret);
19902
sub = sub->next;
19903
}
19904
*/
19905
break;
19906
}
19907
case XML_SCHEMA_TYPE_ALL:
19908
break;
19909
case XML_SCHEMA_TYPE_GROUP:
19910
break;
19911
default:
19912
xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19913
"xmlSchemaCheckElementDeclConsistent",
19914
"found unexpected term of type '%s' in content model",
19915
WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19916
return(-1);
19917
}
19918
cur = (xmlSchemaParticlePtr) cur->next;
19919
}
19920
19921
exit:
19922
return(ret);
19923
}
19924
#endif
19925
19926
/**
19927
* xmlSchemaCheckElementDeclComponent
19928
* @item: an schema element declaration/particle
19929
* @ctxt: a schema parser context
19930
* @name: the name of the attribute
19931
*
19932
* Validates the value constraints of an element declaration.
19933
* Adds substitution group members.
19934
*/
19935
static void
19936
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19937
xmlSchemaParserCtxtPtr ctxt)
19938
{
19939
if (elemDecl == NULL)
19940
return;
19941
if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19942
return;
19943
elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19944
if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19945
/*
19946
* Adds substitution group members.
19947
*/
19948
xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19949
}
19950
}
19951
19952
/**
19953
* xmlSchemaResolveModelGroupParticleReferences:
19954
* @particle: a particle component
19955
* @ctxt: a parser context
19956
*
19957
* Resolves references of a model group's {particles} to
19958
* model group definitions and to element declarations.
19959
*/
19960
static void
19961
xmlSchemaResolveModelGroupParticleReferences(
19962
xmlSchemaParserCtxtPtr ctxt,
19963
xmlSchemaModelGroupPtr mg)
19964
{
19965
xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19966
xmlSchemaQNameRefPtr ref;
19967
xmlSchemaBasicItemPtr refItem;
19968
19969
/*
19970
* URGENT TODO: Test this.
19971
*/
19972
while (particle != NULL) {
19973
if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19974
((WXS_PARTICLE_TERM(particle))->type !=
19975
XML_SCHEMA_EXTRA_QNAMEREF))
19976
{
19977
goto next_particle;
19978
}
19979
ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
19980
/*
19981
* Resolve the reference.
19982
* NULL the {term} by default.
19983
*/
19984
particle->children = NULL;
19985
19986
refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19987
ref->itemType, ref->name, ref->targetNamespace);
19988
if (refItem == NULL) {
19989
xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
19990
NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
19991
ref->targetNamespace, ref->itemType, NULL);
19992
/* TODO: remove the particle. */
19993
goto next_particle;
19994
}
19995
if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19996
if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19997
/* TODO: remove the particle. */
19998
goto next_particle;
19999
/*
20000
* NOTE that we will assign the model group definition
20001
* itself to the "term" of the particle. This will ease
20002
* the check for circular model group definitions. After
20003
* that the "term" will be assigned the model group of the
20004
* model group definition.
20005
*/
20006
if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20007
XML_SCHEMA_TYPE_ALL) {
20008
/*
20009
* SPEC cos-all-limited (1)
20010
* SPEC cos-all-limited (1.2)
20011
* "It appears only as the value of one or both of the
20012
* following properties:"
20013
* (1.1) "the {model group} property of a model group
20014
* definition."
20015
* (1.2) "the {term} property of a particle [... of] the "
20016
* {content type} of a complex type definition."
20017
*/
20018
xmlSchemaCustomErr(ACTXT_CAST ctxt,
20019
/* TODO: error code */
20020
XML_SCHEMAP_COS_ALL_LIMITED,
20021
WXS_ITEM_NODE(particle), NULL,
20022
"A model group definition is referenced, but "
20023
"it contains an 'all' model group, which "
20024
"cannot be contained by model groups",
20025
NULL, NULL);
20026
/* TODO: remove the particle. */
20027
goto next_particle;
20028
}
20029
particle->children = (xmlSchemaTreeItemPtr) refItem;
20030
} else {
20031
/*
20032
* TODO: Are referenced element declarations the only
20033
* other components we expect here?
20034
*/
20035
particle->children = (xmlSchemaTreeItemPtr) refItem;
20036
}
20037
next_particle:
20038
particle = WXS_PTC_CAST particle->next;
20039
}
20040
}
20041
20042
static int
20043
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20044
xmlSchemaValPtr y)
20045
{
20046
xmlSchemaTypePtr tx, ty, ptx, pty;
20047
int ret;
20048
20049
while (x != NULL) {
20050
/* Same types. */
20051
tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20052
ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20053
ptx = xmlSchemaGetPrimitiveType(tx);
20054
pty = xmlSchemaGetPrimitiveType(ty);
20055
/*
20056
* (1) if a datatype T' is `derived` by `restriction` from an
20057
* atomic datatype T then the `value space` of T' is a subset of
20058
* the `value space` of T. */
20059
/*
20060
* (2) if datatypes T' and T'' are `derived` by `restriction`
20061
* from a common atomic ancestor T then the `value space`s of T'
20062
* and T'' may overlap.
20063
*/
20064
if (ptx != pty)
20065
return(0);
20066
/*
20067
* We assume computed values to be normalized, so do a fast
20068
* string comparison for string based types.
20069
*/
20070
if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20071
WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20072
if (! xmlStrEqual(
20073
xmlSchemaValueGetAsString(x),
20074
xmlSchemaValueGetAsString(y)))
20075
return (0);
20076
} else {
20077
ret = xmlSchemaCompareValuesWhtsp(
20078
x, XML_SCHEMA_WHITESPACE_PRESERVE,
20079
y, XML_SCHEMA_WHITESPACE_PRESERVE);
20080
if (ret == -2)
20081
return(-1);
20082
if (ret != 0)
20083
return(0);
20084
}
20085
/*
20086
* Lists.
20087
*/
20088
x = xmlSchemaValueGetNext(x);
20089
if (x != NULL) {
20090
y = xmlSchemaValueGetNext(y);
20091
if (y == NULL)
20092
return (0);
20093
} else if (xmlSchemaValueGetNext(y) != NULL)
20094
return (0);
20095
else
20096
return (1);
20097
}
20098
return (0);
20099
}
20100
20101
/**
20102
* xmlSchemaResolveAttrUseReferences:
20103
* @item: an attribute use
20104
* @ctxt: a parser context
20105
*
20106
* Resolves the referenced attribute declaration.
20107
*/
20108
static int
20109
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20110
xmlSchemaParserCtxtPtr ctxt)
20111
{
20112
if ((ctxt == NULL) || (ause == NULL))
20113
return(-1);
20114
if ((ause->attrDecl == NULL) ||
20115
(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20116
return(0);
20117
20118
{
20119
xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20120
20121
/*
20122
* TODO: Evaluate, what errors could occur if the declaration is not
20123
* found.
20124
*/
20125
ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20126
ref->name, ref->targetNamespace);
20127
if (ause->attrDecl == NULL) {
20128
xmlSchemaPResCompAttrErr(ctxt,
20129
XML_SCHEMAP_SRC_RESOLVE,
20130
WXS_BASIC_CAST ause, ause->node,
20131
"ref", ref->name, ref->targetNamespace,
20132
XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20133
return(ctxt->err);
20134
}
20135
}
20136
return(0);
20137
}
20138
20139
/**
20140
* xmlSchemaCheckAttrUsePropsCorrect:
20141
* @ctxt: a parser context
20142
* @use: an attribute use
20143
*
20144
* Schema Component Constraint:
20145
* Attribute Use Correct (au-props-correct)
20146
*
20147
*/
20148
static int
20149
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20150
xmlSchemaAttributeUsePtr use)
20151
{
20152
if ((ctxt == NULL) || (use == NULL))
20153
return(-1);
20154
if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20155
((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20156
return(0);
20157
20158
/*
20159
* SPEC au-props-correct (1)
20160
* "The values of the properties of an attribute use must be as
20161
* described in the property tableau in The Attribute Use Schema
20162
* Component ($3.5.1), modulo the impact of Missing
20163
* Sub-components ($5.3)."
20164
*/
20165
20166
if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20167
((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20168
((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20169
{
20170
xmlSchemaPCustomErr(ctxt,
20171
XML_SCHEMAP_AU_PROPS_CORRECT_2,
20172
WXS_BASIC_CAST use, NULL,
20173
"The attribute declaration has a 'fixed' value constraint "
20174
", thus the attribute use must also have a 'fixed' value "
20175
"constraint",
20176
NULL);
20177
return(ctxt->err);
20178
}
20179
/*
20180
* Compute and check the value constraint's value.
20181
*/
20182
if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20183
int ret;
20184
/*
20185
* TODO: The spec seems to be missing a check of the
20186
* value constraint of the attribute use. We will do it here.
20187
*/
20188
/*
20189
* SPEC a-props-correct (3)
20190
*/
20191
if (xmlSchemaIsDerivedFromBuiltInType(
20192
WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20193
{
20194
xmlSchemaCustomErr(ACTXT_CAST ctxt,
20195
XML_SCHEMAP_AU_PROPS_CORRECT,
20196
NULL, WXS_BASIC_CAST use,
20197
"Value constraints are not allowed if the type definition "
20198
"is or is derived from xs:ID",
20199
NULL, NULL);
20200
return(ctxt->err);
20201
}
20202
20203
ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20204
use->node, WXS_ATTRUSE_TYPEDEF(use),
20205
use->defValue, &(use->defVal),
20206
1, 1, 0);
20207
if (ret != 0) {
20208
if (ret < 0) {
20209
PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20210
"calling xmlSchemaVCheckCVCSimpleType()");
20211
return(-1);
20212
}
20213
xmlSchemaCustomErr(ACTXT_CAST ctxt,
20214
XML_SCHEMAP_AU_PROPS_CORRECT,
20215
NULL, WXS_BASIC_CAST use,
20216
"The value of the value constraint is not valid",
20217
NULL, NULL);
20218
return(ctxt->err);
20219
}
20220
}
20221
/*
20222
* SPEC au-props-correct (2)
20223
* "If the {attribute declaration} has a fixed
20224
* {value constraint}, then if the attribute use itself has a
20225
* {value constraint}, it must also be fixed and its value must match
20226
* that of the {attribute declaration}'s {value constraint}."
20227
*/
20228
if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20229
(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20230
{
20231
if (! xmlSchemaAreValuesEqual(use->defVal,
20232
(WXS_ATTRUSE_DECL(use))->defVal))
20233
{
20234
xmlSchemaPCustomErr(ctxt,
20235
XML_SCHEMAP_AU_PROPS_CORRECT_2,
20236
WXS_BASIC_CAST use, NULL,
20237
"The 'fixed' value constraint of the attribute use "
20238
"must match the attribute declaration's value "
20239
"constraint '%s'",
20240
(WXS_ATTRUSE_DECL(use))->defValue);
20241
}
20242
return(ctxt->err);
20243
}
20244
return(0);
20245
}
20246
20247
20248
20249
20250
/**
20251
* xmlSchemaResolveAttrTypeReferences:
20252
* @item: an attribute declaration
20253
* @ctxt: a parser context
20254
*
20255
* Resolves the referenced type definition component.
20256
*/
20257
static int
20258
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20259
xmlSchemaParserCtxtPtr ctxt)
20260
{
20261
/*
20262
* The simple type definition corresponding to the <simpleType> element
20263
* information item in the [children], if present, otherwise the simple
20264
* type definition `resolved` to by the `actual value` of the type
20265
* [attribute], if present, otherwise the `simple ur-type definition`.
20266
*/
20267
if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20268
return(0);
20269
item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20270
if (item->subtypes != NULL)
20271
return(0);
20272
if (item->typeName != NULL) {
20273
xmlSchemaTypePtr type;
20274
20275
type = xmlSchemaGetType(ctxt->schema, item->typeName,
20276
item->typeNs);
20277
if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20278
xmlSchemaPResCompAttrErr(ctxt,
20279
XML_SCHEMAP_SRC_RESOLVE,
20280
WXS_BASIC_CAST item, item->node,
20281
"type", item->typeName, item->typeNs,
20282
XML_SCHEMA_TYPE_SIMPLE, NULL);
20283
return(ctxt->err);
20284
} else
20285
item->subtypes = type;
20286
20287
} else {
20288
/*
20289
* The type defaults to the xs:anySimpleType.
20290
*/
20291
item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20292
}
20293
return(0);
20294
}
20295
20296
/**
20297
* xmlSchemaResolveIDCKeyReferences:
20298
* @idc: the identity-constraint definition
20299
* @ctxt: the schema parser context
20300
* @name: the attribute name
20301
*
20302
* Resolve keyRef references to key/unique IDCs.
20303
* Schema Component Constraint:
20304
* Identity-constraint Definition Properties Correct (c-props-correct)
20305
*/
20306
static int
20307
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20308
xmlSchemaParserCtxtPtr pctxt)
20309
{
20310
if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20311
return(0);
20312
if (idc->ref->name != NULL) {
20313
idc->ref->item = (xmlSchemaBasicItemPtr)
20314
xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20315
idc->ref->targetNamespace);
20316
if (idc->ref->item == NULL) {
20317
/*
20318
* TODO: It is actually not an error to fail to resolve
20319
* at this stage. BUT we need to be that strict!
20320
*/
20321
xmlSchemaPResCompAttrErr(pctxt,
20322
XML_SCHEMAP_SRC_RESOLVE,
20323
WXS_BASIC_CAST idc, idc->node,
20324
"refer", idc->ref->name,
20325
idc->ref->targetNamespace,
20326
XML_SCHEMA_TYPE_IDC_KEY, NULL);
20327
return(pctxt->err);
20328
} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20329
/*
20330
* SPEC c-props-correct (1)
20331
*/
20332
xmlSchemaCustomErr(ACTXT_CAST pctxt,
20333
XML_SCHEMAP_C_PROPS_CORRECT,
20334
NULL, WXS_BASIC_CAST idc,
20335
"The keyref references a keyref",
20336
NULL, NULL);
20337
idc->ref->item = NULL;
20338
return(pctxt->err);
20339
} else {
20340
if (idc->nbFields !=
20341
((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20342
xmlChar *str = NULL;
20343
xmlSchemaIDCPtr refer;
20344
20345
refer = (xmlSchemaIDCPtr) idc->ref->item;
20346
/*
20347
* SPEC c-props-correct(2)
20348
* "If the {identity-constraint category} is keyref,
20349
* the cardinality of the {fields} must equal that of
20350
* the {fields} of the {referenced key}.
20351
*/
20352
xmlSchemaCustomErr(ACTXT_CAST pctxt,
20353
XML_SCHEMAP_C_PROPS_CORRECT,
20354
NULL, WXS_BASIC_CAST idc,
20355
"The cardinality of the keyref differs from the "
20356
"cardinality of the referenced key/unique '%s'",
20357
xmlSchemaFormatQName(&str, refer->targetNamespace,
20358
refer->name),
20359
NULL);
20360
FREE_AND_NULL(str)
20361
return(pctxt->err);
20362
}
20363
}
20364
}
20365
return(0);
20366
}
20367
20368
static int
20369
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20370
xmlSchemaParserCtxtPtr pctxt)
20371
{
20372
if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20373
prohib->targetNamespace) == NULL) {
20374
20375
xmlSchemaPResCompAttrErr(pctxt,
20376
XML_SCHEMAP_SRC_RESOLVE,
20377
NULL, prohib->node,
20378
"ref", prohib->name, prohib->targetNamespace,
20379
XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20380
return(XML_SCHEMAP_SRC_RESOLVE);
20381
}
20382
return(0);
20383
}
20384
20385
#define WXS_REDEFINED_TYPE(c) \
20386
(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20387
20388
#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20389
(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20390
20391
#define WXS_REDEFINED_ATTR_GROUP(c) \
20392
(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20393
20394
static int
20395
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20396
{
20397
int err = 0;
20398
xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20399
xmlSchemaBasicItemPtr prev, item;
20400
int wasRedefined;
20401
20402
if (redef == NULL)
20403
return(0);
20404
20405
do {
20406
item = redef->item;
20407
/*
20408
* First try to locate the redefined component in the
20409
* schema graph starting with the redefined schema.
20410
* NOTE: According to this schema bug entry:
20411
* http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20412
* it's not clear if the referenced component needs to originate
20413
* from the <redefine>d schema _document_ or the schema; the latter
20414
* would include all imported and included sub-schemas of the
20415
* <redefine>d schema. Currently the latter approach is used.
20416
* SUPPLEMENT: It seems that the WG moves towards the latter
20417
* approach, so we are doing it right.
20418
*
20419
*/
20420
prev = xmlSchemaFindRedefCompInGraph(
20421
redef->targetBucket, item->type,
20422
redef->refName, redef->refTargetNs);
20423
if (prev == NULL) {
20424
xmlChar *str = NULL;
20425
xmlNodePtr node;
20426
20427
/*
20428
* SPEC src-redefine:
20429
* (6.2.1) "The `actual value` of its own name attribute plus
20430
* target namespace must successfully `resolve` to a model
20431
* group definition in I."
20432
* (7.2.1) "The `actual value` of its own name attribute plus
20433
* target namespace must successfully `resolve` to an attribute
20434
* group definition in I."
20435
20436
*
20437
* Note that, if we are redefining with the use of references
20438
* to components, the spec assumes the src-resolve to be used;
20439
* but this won't assure that we search only *inside* the
20440
* redefined schema.
20441
*/
20442
if (redef->reference)
20443
node = WXS_ITEM_NODE(redef->reference);
20444
else
20445
node = WXS_ITEM_NODE(item);
20446
xmlSchemaCustomErr(ACTXT_CAST pctxt,
20447
/*
20448
* TODO: error code.
20449
* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20450
* reference kind.
20451
*/
20452
XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20453
"The %s '%s' to be redefined could not be found in "
20454
"the redefined schema",
20455
WXS_ITEM_TYPE_NAME(item),
20456
xmlSchemaFormatQName(&str, redef->refTargetNs,
20457
redef->refName));
20458
FREE_AND_NULL(str);
20459
err = pctxt->err;
20460
redef = redef->next;
20461
continue;
20462
}
20463
/*
20464
* TODO: Obtaining and setting the redefinition state is really
20465
* clumsy.
20466
*/
20467
wasRedefined = 0;
20468
switch (item->type) {
20469
case XML_SCHEMA_TYPE_COMPLEX:
20470
case XML_SCHEMA_TYPE_SIMPLE:
20471
if ((WXS_TYPE_CAST prev)->flags &
20472
XML_SCHEMAS_TYPE_REDEFINED)
20473
{
20474
wasRedefined = 1;
20475
break;
20476
}
20477
/* Mark it as redefined. */
20478
(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20479
/*
20480
* Assign the redefined type to the
20481
* base type of the redefining type.
20482
* TODO: How
20483
*/
20484
((xmlSchemaTypePtr) item)->baseType =
20485
(xmlSchemaTypePtr) prev;
20486
break;
20487
case XML_SCHEMA_TYPE_GROUP:
20488
if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20489
XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20490
{
20491
wasRedefined = 1;
20492
break;
20493
}
20494
/* Mark it as redefined. */
20495
(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20496
XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20497
if (redef->reference != NULL) {
20498
/*
20499
* Overwrite the QName-reference with the
20500
* referenced model group def.
20501
*/
20502
(WXS_PTC_CAST redef->reference)->children =
20503
WXS_TREE_CAST prev;
20504
}
20505
redef->target = prev;
20506
break;
20507
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20508
if ((WXS_ATTR_GROUP_CAST prev)->flags &
20509
XML_SCHEMAS_ATTRGROUP_REDEFINED)
20510
{
20511
wasRedefined = 1;
20512
break;
20513
}
20514
(WXS_ATTR_GROUP_CAST prev)->flags |=
20515
XML_SCHEMAS_ATTRGROUP_REDEFINED;
20516
if (redef->reference != NULL) {
20517
/*
20518
* Assign the redefined attribute group to the
20519
* QName-reference component.
20520
* This is the easy case, since we will just
20521
* expand the redefined group.
20522
*/
20523
(WXS_QNAME_CAST redef->reference)->item = prev;
20524
redef->target = NULL;
20525
} else {
20526
/*
20527
* This is the complicated case: we need
20528
* to apply src-redefine (7.2.2) at a later
20529
* stage, i.e. when attribute group references
20530
* have been expanded and simple types have
20531
* been fixed.
20532
*/
20533
redef->target = prev;
20534
}
20535
break;
20536
default:
20537
PERROR_INT("xmlSchemaResolveRedefReferences",
20538
"Unexpected redefined component type");
20539
return(-1);
20540
}
20541
if (wasRedefined) {
20542
xmlChar *str = NULL;
20543
xmlNodePtr node;
20544
20545
if (redef->reference)
20546
node = WXS_ITEM_NODE(redef->reference);
20547
else
20548
node = WXS_ITEM_NODE(redef->item);
20549
20550
xmlSchemaCustomErr(ACTXT_CAST pctxt,
20551
/* TODO: error code. */
20552
XML_SCHEMAP_SRC_REDEFINE,
20553
node, NULL,
20554
"The referenced %s was already redefined. Multiple "
20555
"redefinition of the same component is not supported",
20556
xmlSchemaGetComponentDesignation(&str, prev),
20557
NULL);
20558
FREE_AND_NULL(str)
20559
err = pctxt->err;
20560
redef = redef->next;
20561
continue;
20562
}
20563
redef = redef->next;
20564
} while (redef != NULL);
20565
20566
return(err);
20567
}
20568
20569
static int
20570
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20571
{
20572
int err = 0;
20573
xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20574
xmlSchemaBasicItemPtr item;
20575
20576
if (redef == NULL)
20577
return(0);
20578
20579
do {
20580
if (redef->target == NULL) {
20581
redef = redef->next;
20582
continue;
20583
}
20584
item = redef->item;
20585
20586
switch (item->type) {
20587
case XML_SCHEMA_TYPE_SIMPLE:
20588
case XML_SCHEMA_TYPE_COMPLEX:
20589
/*
20590
* Since the spec wants the {name} of the redefined
20591
* type to be 'absent', we'll NULL it.
20592
*/
20593
(WXS_TYPE_CAST redef->target)->name = NULL;
20594
20595
/*
20596
* TODO: Seems like there's nothing more to do. The normal
20597
* inheritance mechanism is used. But not 100% sure.
20598
*/
20599
break;
20600
case XML_SCHEMA_TYPE_GROUP:
20601
/*
20602
* URGENT TODO:
20603
* SPEC src-redefine:
20604
* (6.2.2) "The {model group} of the model group definition
20605
* which corresponds to it per XML Representation of Model
20606
* Group Definition Schema Components ($3.7.2) must be a
20607
* `valid restriction` of the {model group} of that model
20608
* group definition in I, as defined in Particle Valid
20609
* (Restriction) ($3.9.6)."
20610
*/
20611
break;
20612
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20613
/*
20614
* SPEC src-redefine:
20615
* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20616
* the attribute group definition which corresponds to it
20617
* per XML Representation of Attribute Group Definition Schema
20618
* Components ($3.6.2) must be `valid restrictions` of the
20619
* {attribute uses} and {attribute wildcard} of that attribute
20620
* group definition in I, as defined in clause 2, clause 3 and
20621
* clause 4 of Derivation Valid (Restriction, Complex)
20622
* ($3.4.6) (where references to the base type definition are
20623
* understood as references to the attribute group definition
20624
* in I)."
20625
*/
20626
err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20627
XML_SCHEMA_ACTION_REDEFINE,
20628
item, redef->target,
20629
(WXS_ATTR_GROUP_CAST item)->attrUses,
20630
(WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20631
(WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20632
(WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20633
if (err == -1)
20634
return(-1);
20635
break;
20636
default:
20637
break;
20638
}
20639
redef = redef->next;
20640
} while (redef != NULL);
20641
return(0);
20642
}
20643
20644
20645
static int
20646
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20647
xmlSchemaBucketPtr bucket)
20648
{
20649
xmlSchemaBasicItemPtr item;
20650
int err;
20651
xmlHashTablePtr *table;
20652
const xmlChar *name;
20653
int i;
20654
20655
#define WXS_GET_GLOBAL_HASH(c, slot) { \
20656
if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20657
table = &(WXS_IMPBUCKET((c))->schema->slot); \
20658
else \
20659
table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20660
20661
/*
20662
* Add global components to the schema's hash tables.
20663
* This is the place where duplicate components will be
20664
* detected.
20665
* TODO: I think normally we should support imports of the
20666
* same namespace from multiple locations. We don't do currently,
20667
* but if we do then according to:
20668
* http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20669
* we would need, if imported directly, to import redefined
20670
* components as well to be able to catch clashing components.
20671
* (I hope I'll still know what this means after some months :-()
20672
*/
20673
if (bucket == NULL)
20674
return(-1);
20675
if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20676
return(0);
20677
bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20678
20679
for (i = 0; i < bucket->globals->nbItems; i++) {
20680
item = bucket->globals->items[i];
20681
table = NULL;
20682
switch (item->type) {
20683
case XML_SCHEMA_TYPE_COMPLEX:
20684
case XML_SCHEMA_TYPE_SIMPLE:
20685
if (WXS_REDEFINED_TYPE(item))
20686
continue;
20687
name = (WXS_TYPE_CAST item)->name;
20688
WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20689
break;
20690
case XML_SCHEMA_TYPE_ELEMENT:
20691
name = (WXS_ELEM_CAST item)->name;
20692
WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20693
break;
20694
case XML_SCHEMA_TYPE_ATTRIBUTE:
20695
name = (WXS_ATTR_CAST item)->name;
20696
WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20697
break;
20698
case XML_SCHEMA_TYPE_GROUP:
20699
if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20700
continue;
20701
name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20702
WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20703
break;
20704
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20705
if (WXS_REDEFINED_ATTR_GROUP(item))
20706
continue;
20707
name = (WXS_ATTR_GROUP_CAST item)->name;
20708
WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20709
break;
20710
case XML_SCHEMA_TYPE_IDC_KEY:
20711
case XML_SCHEMA_TYPE_IDC_UNIQUE:
20712
case XML_SCHEMA_TYPE_IDC_KEYREF:
20713
name = (WXS_IDC_CAST item)->name;
20714
WXS_GET_GLOBAL_HASH(bucket, idcDef)
20715
break;
20716
case XML_SCHEMA_TYPE_NOTATION:
20717
name = ((xmlSchemaNotationPtr) item)->name;
20718
WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20719
break;
20720
default:
20721
PERROR_INT("xmlSchemaAddComponents",
20722
"Unexpected global component type");
20723
continue;
20724
}
20725
if (*table == NULL) {
20726
*table = xmlHashCreateDict(10, pctxt->dict);
20727
if (*table == NULL) {
20728
PERROR_INT("xmlSchemaAddComponents",
20729
"failed to create a component hash table");
20730
return(-1);
20731
}
20732
}
20733
err = xmlHashAddEntry(*table, name, item);
20734
if (err != 0) {
20735
xmlChar *str = NULL;
20736
20737
xmlSchemaCustomErr(ACTXT_CAST pctxt,
20738
XML_SCHEMAP_REDEFINED_TYPE,
20739
WXS_ITEM_NODE(item),
20740
WXS_BASIC_CAST item,
20741
"A global %s '%s' does already exist",
20742
WXS_ITEM_TYPE_NAME(item),
20743
xmlSchemaGetComponentQName(&str, item));
20744
FREE_AND_NULL(str);
20745
}
20746
}
20747
/*
20748
* Process imported/included schemas.
20749
*/
20750
if (bucket->relations != NULL) {
20751
xmlSchemaSchemaRelationPtr rel = bucket->relations;
20752
do {
20753
if ((rel->bucket != NULL) &&
20754
((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20755
if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20756
return(-1);
20757
}
20758
rel = rel->next;
20759
} while (rel != NULL);
20760
}
20761
return(0);
20762
}
20763
20764
static int
20765
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20766
xmlSchemaBucketPtr rootBucket)
20767
{
20768
xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20769
xmlSchemaTreeItemPtr item, *items;
20770
int nbItems, i, ret = 0;
20771
xmlSchemaBucketPtr oldbucket = con->bucket;
20772
xmlSchemaElementPtr elemDecl;
20773
20774
#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20775
20776
if ((con->pending == NULL) ||
20777
(con->pending->nbItems == 0))
20778
return(0);
20779
20780
/*
20781
* Since xmlSchemaFixupComplexType() will create new particles
20782
* (local components), and those particle components need a bucket
20783
* on the constructor, we'll assure here that the constructor has
20784
* a bucket.
20785
* TODO: Think about storing locals _only_ on the main bucket.
20786
*/
20787
if (con->bucket == NULL)
20788
con->bucket = rootBucket;
20789
20790
/* TODO:
20791
* SPEC (src-redefine):
20792
* (6.2) "If it has no such self-reference, then all of the
20793
* following must be true:"
20794
20795
* (6.2.2) The {model group} of the model group definition which
20796
* corresponds to it per XML Representation of Model Group
20797
* Definition Schema Components ($3.7.2) must be a `valid
20798
* restriction` of the {model group} of that model group definition
20799
* in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20800
*/
20801
xmlSchemaCheckSRCRedefineFirst(pctxt);
20802
20803
/*
20804
* Add global components to the schemata's hash tables.
20805
*/
20806
xmlSchemaAddComponents(pctxt, rootBucket);
20807
20808
pctxt->ctxtType = NULL;
20809
items = (xmlSchemaTreeItemPtr *) con->pending->items;
20810
nbItems = con->pending->nbItems;
20811
/*
20812
* Now that we have parsed *all* the schema document(s) and converted
20813
* them to schema components, we can resolve references, apply component
20814
* constraints, create the FSA from the content model, etc.
20815
*/
20816
/*
20817
* Resolve references of..
20818
*
20819
* 1. element declarations:
20820
* - the type definition
20821
* - the substitution group affiliation
20822
* 2. simple/complex types:
20823
* - the base type definition
20824
* - the memberTypes of union types
20825
* - the itemType of list types
20826
* 3. attributes declarations and attribute uses:
20827
* - the type definition
20828
* - if an attribute use, then the attribute declaration
20829
* 4. attribute group references:
20830
* - the attribute group definition
20831
* 5. particles:
20832
* - the term of the particle (e.g. a model group)
20833
* 6. IDC key-references:
20834
* - the referenced IDC 'key' or 'unique' definition
20835
* 7. Attribute prohibitions which had a "ref" attribute.
20836
*/
20837
for (i = 0; i < nbItems; i++) {
20838
item = items[i];
20839
switch (item->type) {
20840
case XML_SCHEMA_TYPE_ELEMENT:
20841
xmlSchemaResolveElementReferences(
20842
(xmlSchemaElementPtr) item, pctxt);
20843
FIXHFAILURE;
20844
break;
20845
case XML_SCHEMA_TYPE_COMPLEX:
20846
case XML_SCHEMA_TYPE_SIMPLE:
20847
xmlSchemaResolveTypeReferences(
20848
(xmlSchemaTypePtr) item, pctxt);
20849
FIXHFAILURE;
20850
break;
20851
case XML_SCHEMA_TYPE_ATTRIBUTE:
20852
xmlSchemaResolveAttrTypeReferences(
20853
(xmlSchemaAttributePtr) item, pctxt);
20854
FIXHFAILURE;
20855
break;
20856
case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20857
xmlSchemaResolveAttrUseReferences(
20858
(xmlSchemaAttributeUsePtr) item, pctxt);
20859
FIXHFAILURE;
20860
break;
20861
case XML_SCHEMA_EXTRA_QNAMEREF:
20862
if ((WXS_QNAME_CAST item)->itemType ==
20863
XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20864
{
20865
xmlSchemaResolveAttrGroupReferences(
20866
WXS_QNAME_CAST item, pctxt);
20867
}
20868
FIXHFAILURE;
20869
break;
20870
case XML_SCHEMA_TYPE_SEQUENCE:
20871
case XML_SCHEMA_TYPE_CHOICE:
20872
case XML_SCHEMA_TYPE_ALL:
20873
xmlSchemaResolveModelGroupParticleReferences(pctxt,
20874
WXS_MODEL_GROUP_CAST item);
20875
FIXHFAILURE;
20876
break;
20877
case XML_SCHEMA_TYPE_IDC_KEY:
20878
case XML_SCHEMA_TYPE_IDC_UNIQUE:
20879
case XML_SCHEMA_TYPE_IDC_KEYREF:
20880
xmlSchemaResolveIDCKeyReferences(
20881
(xmlSchemaIDCPtr) item, pctxt);
20882
FIXHFAILURE;
20883
break;
20884
case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20885
/*
20886
* Handle attribute prohibition which had a
20887
* "ref" attribute.
20888
*/
20889
xmlSchemaResolveAttrUseProhibReferences(
20890
WXS_ATTR_PROHIB_CAST item, pctxt);
20891
FIXHFAILURE;
20892
break;
20893
default:
20894
break;
20895
}
20896
}
20897
if (pctxt->nberrors != 0)
20898
goto exit_error;
20899
20900
/*
20901
* Now that all references are resolved we
20902
* can check for circularity of...
20903
* 1. the base axis of type definitions
20904
* 2. nested model group definitions
20905
* 3. nested attribute group definitions
20906
* TODO: check for circular substitution groups.
20907
*/
20908
for (i = 0; i < nbItems; i++) {
20909
item = items[i];
20910
/*
20911
* Let's better stop on the first error here.
20912
*/
20913
switch (item->type) {
20914
case XML_SCHEMA_TYPE_COMPLEX:
20915
case XML_SCHEMA_TYPE_SIMPLE:
20916
xmlSchemaCheckTypeDefCircular(
20917
(xmlSchemaTypePtr) item, pctxt);
20918
FIXHFAILURE;
20919
if (pctxt->nberrors != 0)
20920
goto exit_error;
20921
break;
20922
case XML_SCHEMA_TYPE_GROUP:
20923
xmlSchemaCheckGroupDefCircular(
20924
(xmlSchemaModelGroupDefPtr) item, pctxt);
20925
FIXHFAILURE;
20926
if (pctxt->nberrors != 0)
20927
goto exit_error;
20928
break;
20929
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20930
xmlSchemaCheckAttrGroupCircular(
20931
(xmlSchemaAttributeGroupPtr) item, pctxt);
20932
FIXHFAILURE;
20933
if (pctxt->nberrors != 0)
20934
goto exit_error;
20935
break;
20936
default:
20937
break;
20938
}
20939
}
20940
if (pctxt->nberrors != 0)
20941
goto exit_error;
20942
/*
20943
* Model group definition references:
20944
* Such a reference is reflected by a particle at the component
20945
* level. Until now the 'term' of such particles pointed
20946
* to the model group definition; this was done, in order to
20947
* ease circularity checks. Now we need to set the 'term' of
20948
* such particles to the model group of the model group definition.
20949
*/
20950
for (i = 0; i < nbItems; i++) {
20951
item = items[i];
20952
switch (item->type) {
20953
case XML_SCHEMA_TYPE_SEQUENCE:
20954
case XML_SCHEMA_TYPE_CHOICE:
20955
xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20956
WXS_MODEL_GROUP_CAST item);
20957
break;
20958
default:
20959
break;
20960
}
20961
}
20962
if (pctxt->nberrors != 0)
20963
goto exit_error;
20964
/*
20965
* Expand attribute group references of attribute group definitions.
20966
*/
20967
for (i = 0; i < nbItems; i++) {
20968
item = items[i];
20969
switch (item->type) {
20970
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20971
if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20972
WXS_ATTR_GROUP_HAS_REFS(item))
20973
{
20974
xmlSchemaAttributeGroupExpandRefs(pctxt,
20975
WXS_ATTR_GROUP_CAST item);
20976
FIXHFAILURE;
20977
}
20978
break;
20979
default:
20980
break;
20981
}
20982
}
20983
if (pctxt->nberrors != 0)
20984
goto exit_error;
20985
/*
20986
* First compute the variety of simple types. This is needed as
20987
* a separate step, since otherwise we won't be able to detect
20988
* circular union types in all cases.
20989
*/
20990
for (i = 0; i < nbItems; i++) {
20991
item = items[i];
20992
switch (item->type) {
20993
case XML_SCHEMA_TYPE_SIMPLE:
20994
if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
20995
xmlSchemaFixupSimpleTypeStageOne(pctxt,
20996
(xmlSchemaTypePtr) item);
20997
FIXHFAILURE;
20998
}
20999
break;
21000
default:
21001
break;
21002
}
21003
}
21004
if (pctxt->nberrors != 0)
21005
goto exit_error;
21006
/*
21007
* Detect circular union types. Note that this needs the variety to
21008
* be already computed.
21009
*/
21010
for (i = 0; i < nbItems; i++) {
21011
item = items[i];
21012
switch (item->type) {
21013
case XML_SCHEMA_TYPE_SIMPLE:
21014
if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21015
xmlSchemaCheckUnionTypeDefCircular(pctxt,
21016
(xmlSchemaTypePtr) item);
21017
FIXHFAILURE;
21018
}
21019
break;
21020
default:
21021
break;
21022
}
21023
}
21024
if (pctxt->nberrors != 0)
21025
goto exit_error;
21026
21027
/*
21028
* Do the complete type fixup for simple types.
21029
*/
21030
for (i = 0; i < nbItems; i++) {
21031
item = items[i];
21032
switch (item->type) {
21033
case XML_SCHEMA_TYPE_SIMPLE:
21034
if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21035
xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21036
FIXHFAILURE;
21037
}
21038
break;
21039
default:
21040
break;
21041
}
21042
}
21043
if (pctxt->nberrors != 0)
21044
goto exit_error;
21045
/*
21046
* At this point we need build and check all simple types.
21047
*/
21048
/*
21049
* Apply constraints for attribute declarations.
21050
*/
21051
for (i = 0; i < nbItems; i++) {
21052
item = items[i];
21053
switch (item->type) {
21054
case XML_SCHEMA_TYPE_ATTRIBUTE:
21055
xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21056
FIXHFAILURE;
21057
break;
21058
default:
21059
break;
21060
}
21061
}
21062
if (pctxt->nberrors != 0)
21063
goto exit_error;
21064
/*
21065
* Apply constraints for attribute uses.
21066
*/
21067
for (i = 0; i < nbItems; i++) {
21068
item = items[i];
21069
switch (item->type) {
21070
case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21071
if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21072
xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21073
WXS_ATTR_USE_CAST item);
21074
FIXHFAILURE;
21075
}
21076
break;
21077
default:
21078
break;
21079
}
21080
}
21081
if (pctxt->nberrors != 0)
21082
goto exit_error;
21083
21084
/*
21085
* Apply constraints for attribute group definitions.
21086
*/
21087
for (i = 0; i < nbItems; i++) {
21088
item = items[i];
21089
switch (item->type) {
21090
case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21091
if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21092
( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21093
{
21094
xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21095
FIXHFAILURE;
21096
}
21097
break;
21098
default:
21099
break;
21100
}
21101
}
21102
if (pctxt->nberrors != 0)
21103
goto exit_error;
21104
21105
/*
21106
* Apply constraints for redefinitions.
21107
*/
21108
if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21109
xmlSchemaCheckSRCRedefineSecond(pctxt);
21110
if (pctxt->nberrors != 0)
21111
goto exit_error;
21112
21113
/*
21114
* Complex types are built and checked.
21115
*/
21116
for (i = 0; i < nbItems; i++) {
21117
item = con->pending->items[i];
21118
switch (item->type) {
21119
case XML_SCHEMA_TYPE_COMPLEX:
21120
if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21121
xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21122
FIXHFAILURE;
21123
}
21124
break;
21125
default:
21126
break;
21127
}
21128
}
21129
if (pctxt->nberrors != 0)
21130
goto exit_error;
21131
21132
/*
21133
* The list could have changed, since xmlSchemaFixupComplexType()
21134
* will create particles and model groups in some cases.
21135
*/
21136
items = (xmlSchemaTreeItemPtr *) con->pending->items;
21137
nbItems = con->pending->nbItems;
21138
21139
/*
21140
* Apply some constraints for element declarations.
21141
*/
21142
for (i = 0; i < nbItems; i++) {
21143
item = items[i];
21144
switch (item->type) {
21145
case XML_SCHEMA_TYPE_ELEMENT:
21146
elemDecl = (xmlSchemaElementPtr) item;
21147
21148
if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21149
{
21150
xmlSchemaCheckElementDeclComponent(
21151
(xmlSchemaElementPtr) elemDecl, pctxt);
21152
FIXHFAILURE;
21153
}
21154
21155
#ifdef WXS_ELEM_DECL_CONS_ENABLED
21156
/*
21157
* Schema Component Constraint: Element Declarations Consistent
21158
* Apply this constraint to local types of element declarations.
21159
*/
21160
if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21161
(WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21162
(WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21163
{
21164
xmlSchemaCheckElementDeclConsistent(pctxt,
21165
WXS_BASIC_CAST elemDecl,
21166
WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21167
NULL, NULL, 0);
21168
}
21169
#endif
21170
break;
21171
default:
21172
break;
21173
}
21174
}
21175
if (pctxt->nberrors != 0)
21176
goto exit_error;
21177
21178
/*
21179
* Finally we can build the automaton from the content model of
21180
* complex types.
21181
*/
21182
21183
for (i = 0; i < nbItems; i++) {
21184
item = items[i];
21185
switch (item->type) {
21186
case XML_SCHEMA_TYPE_COMPLEX:
21187
xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21188
/* FIXHFAILURE; */
21189
break;
21190
default:
21191
break;
21192
}
21193
}
21194
if (pctxt->nberrors != 0)
21195
goto exit_error;
21196
/*
21197
* URGENT TODO: cos-element-consistent
21198
*/
21199
goto exit;
21200
21201
exit_error:
21202
ret = pctxt->err;
21203
goto exit;
21204
21205
exit_failure:
21206
ret = -1;
21207
21208
exit:
21209
/*
21210
* Reset the constructor. This is needed for XSI acquisition, since
21211
* those items will be processed over and over again for every XSI
21212
* if not cleared here.
21213
*/
21214
con->bucket = oldbucket;
21215
con->pending->nbItems = 0;
21216
if (con->substGroups != NULL) {
21217
xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21218
con->substGroups = NULL;
21219
}
21220
if (con->redefs != NULL) {
21221
xmlSchemaRedefListFree(con->redefs);
21222
con->redefs = NULL;
21223
}
21224
return(ret);
21225
}
21226
/**
21227
* xmlSchemaParse:
21228
* @ctxt: a schema validation context
21229
*
21230
* parse a schema definition resource and build an internal
21231
* XML Schema structure which can be used to validate instances.
21232
*
21233
* Returns the internal XML Schema structure built from the resource or
21234
* NULL in case of error
21235
*/
21236
xmlSchemaPtr
21237
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21238
{
21239
xmlSchemaPtr mainSchema = NULL;
21240
xmlSchemaBucketPtr bucket = NULL;
21241
int res;
21242
21243
/*
21244
* This one is used if the schema to be parsed was specified via
21245
* the API; i.e. not automatically by the validated instance document.
21246
*/
21247
21248
if (xmlSchemaInitTypes() < 0)
21249
return (NULL);
21250
21251
if (ctxt == NULL)
21252
return (NULL);
21253
21254
/* TODO: Init the context. Is this all we need?*/
21255
ctxt->nberrors = 0;
21256
ctxt->err = 0;
21257
ctxt->counter = 0;
21258
21259
/* Create the *main* schema. */
21260
mainSchema = xmlSchemaNewSchema(ctxt);
21261
if (mainSchema == NULL)
21262
goto exit_failure;
21263
/*
21264
* Create the schema constructor.
21265
*/
21266
if (ctxt->constructor == NULL) {
21267
ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21268
if (ctxt->constructor == NULL)
21269
goto exit_failure;
21270
/* Take ownership of the constructor to be able to free it. */
21271
ctxt->ownsConstructor = 1;
21272
}
21273
ctxt->constructor->mainSchema = mainSchema;
21274
/*
21275
* Locate and add the schema document.
21276
*/
21277
res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21278
ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21279
NULL, NULL, &bucket);
21280
if (res == -1)
21281
goto exit_failure;
21282
if (res != 0)
21283
goto exit;
21284
21285
if (bucket == NULL) {
21286
/* TODO: Error code, actually we failed to *locate* the schema. */
21287
if (ctxt->URL)
21288
xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21289
NULL, NULL,
21290
"Failed to locate the main schema resource at '%s'",
21291
ctxt->URL, NULL);
21292
else
21293
xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21294
NULL, NULL,
21295
"Failed to locate the main schema resource",
21296
NULL, NULL);
21297
goto exit;
21298
}
21299
/* Then do the parsing for good. */
21300
if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21301
goto exit_failure;
21302
if (ctxt->nberrors != 0)
21303
goto exit;
21304
21305
mainSchema->doc = bucket->doc;
21306
mainSchema->preserve = ctxt->preserve;
21307
21308
ctxt->schema = mainSchema;
21309
21310
if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21311
goto exit_failure;
21312
21313
/*
21314
* TODO: This is not nice, since we cannot distinguish from the
21315
* result if there was an internal error or not.
21316
*/
21317
exit:
21318
if (ctxt->nberrors != 0) {
21319
if (mainSchema) {
21320
xmlSchemaFree(mainSchema);
21321
mainSchema = NULL;
21322
}
21323
if (ctxt->constructor) {
21324
xmlSchemaConstructionCtxtFree(ctxt->constructor);
21325
ctxt->constructor = NULL;
21326
ctxt->ownsConstructor = 0;
21327
}
21328
}
21329
ctxt->schema = NULL;
21330
return(mainSchema);
21331
exit_failure:
21332
/*
21333
* Quite verbose, but should catch internal errors, which were
21334
* not communicated.
21335
*/
21336
if (mainSchema) {
21337
xmlSchemaFree(mainSchema);
21338
mainSchema = NULL;
21339
}
21340
if (ctxt->constructor) {
21341
xmlSchemaConstructionCtxtFree(ctxt->constructor);
21342
ctxt->constructor = NULL;
21343
ctxt->ownsConstructor = 0;
21344
}
21345
PERROR_INT2("xmlSchemaParse",
21346
"An internal error occurred");
21347
ctxt->schema = NULL;
21348
return(NULL);
21349
}
21350
21351
/**
21352
* xmlSchemaSetParserErrors:
21353
* @ctxt: a schema validation context
21354
* @err: the error callback
21355
* @warn: the warning callback
21356
* @ctx: contextual data for the callbacks
21357
*
21358
* Set the callback functions used to handle errors for a validation context
21359
*/
21360
void
21361
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21362
xmlSchemaValidityErrorFunc err,
21363
xmlSchemaValidityWarningFunc warn, void *ctx)
21364
{
21365
if (ctxt == NULL)
21366
return;
21367
ctxt->error = err;
21368
ctxt->warning = warn;
21369
ctxt->errCtxt = ctx;
21370
if (ctxt->vctxt != NULL)
21371
xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21372
}
21373
21374
/**
21375
* xmlSchemaSetParserStructuredErrors:
21376
* @ctxt: a schema parser context
21377
* @serror: the structured error function
21378
* @ctx: the functions context
21379
*
21380
* Set the structured error callback
21381
*/
21382
void
21383
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21384
xmlStructuredErrorFunc serror,
21385
void *ctx)
21386
{
21387
if (ctxt == NULL)
21388
return;
21389
ctxt->serror = serror;
21390
ctxt->errCtxt = ctx;
21391
if (ctxt->vctxt != NULL)
21392
xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21393
}
21394
21395
/**
21396
* xmlSchemaGetParserErrors:
21397
* @ctxt: a XMl-Schema parser context
21398
* @err: the error callback result
21399
* @warn: the warning callback result
21400
* @ctx: contextual data for the callbacks result
21401
*
21402
* Get the callback information used to handle errors for a parser context
21403
*
21404
* Returns -1 in case of failure, 0 otherwise
21405
*/
21406
int
21407
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21408
xmlSchemaValidityErrorFunc * err,
21409
xmlSchemaValidityWarningFunc * warn, void **ctx)
21410
{
21411
if (ctxt == NULL)
21412
return(-1);
21413
if (err != NULL)
21414
*err = ctxt->error;
21415
if (warn != NULL)
21416
*warn = ctxt->warning;
21417
if (ctx != NULL)
21418
*ctx = ctxt->errCtxt;
21419
return(0);
21420
}
21421
21422
/**
21423
* xmlSchemaFacetTypeToString:
21424
* @type: the facet type
21425
*
21426
* Convert the xmlSchemaTypeType to a char string.
21427
*
21428
* Returns the char string representation of the facet type if the
21429
* type is a facet and an "Internal Error" string otherwise.
21430
*/
21431
static const xmlChar *
21432
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21433
{
21434
switch (type) {
21435
case XML_SCHEMA_FACET_PATTERN:
21436
return (BAD_CAST "pattern");
21437
case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21438
return (BAD_CAST "maxExclusive");
21439
case XML_SCHEMA_FACET_MAXINCLUSIVE:
21440
return (BAD_CAST "maxInclusive");
21441
case XML_SCHEMA_FACET_MINEXCLUSIVE:
21442
return (BAD_CAST "minExclusive");
21443
case XML_SCHEMA_FACET_MININCLUSIVE:
21444
return (BAD_CAST "minInclusive");
21445
case XML_SCHEMA_FACET_WHITESPACE:
21446
return (BAD_CAST "whiteSpace");
21447
case XML_SCHEMA_FACET_ENUMERATION:
21448
return (BAD_CAST "enumeration");
21449
case XML_SCHEMA_FACET_LENGTH:
21450
return (BAD_CAST "length");
21451
case XML_SCHEMA_FACET_MAXLENGTH:
21452
return (BAD_CAST "maxLength");
21453
case XML_SCHEMA_FACET_MINLENGTH:
21454
return (BAD_CAST "minLength");
21455
case XML_SCHEMA_FACET_TOTALDIGITS:
21456
return (BAD_CAST "totalDigits");
21457
case XML_SCHEMA_FACET_FRACTIONDIGITS:
21458
return (BAD_CAST "fractionDigits");
21459
default:
21460
break;
21461
}
21462
return (BAD_CAST "Internal Error");
21463
}
21464
21465
static xmlSchemaWhitespaceValueType
21466
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21467
{
21468
/*
21469
* The normalization type can be changed only for types which are derived
21470
* from xsd:string.
21471
*/
21472
if (type->type == XML_SCHEMA_TYPE_BASIC) {
21473
/*
21474
* Note that we assume a whitespace of preserve for anySimpleType.
21475
*/
21476
if ((type->builtInType == XML_SCHEMAS_STRING) ||
21477
(type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21478
return(XML_SCHEMA_WHITESPACE_PRESERVE);
21479
else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21480
return(XML_SCHEMA_WHITESPACE_REPLACE);
21481
else {
21482
/*
21483
* For all `atomic` datatypes other than string (and types `derived`
21484
* by `restriction` from it) the value of whiteSpace is fixed to
21485
* collapse
21486
* Note that this includes built-in list datatypes.
21487
*/
21488
return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21489
}
21490
} else if (WXS_IS_LIST(type)) {
21491
/*
21492
* For list types the facet "whiteSpace" is fixed to "collapse".
21493
*/
21494
return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21495
} else if (WXS_IS_UNION(type)) {
21496
return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21497
} else if (WXS_IS_ATOMIC(type)) {
21498
if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21499
return (XML_SCHEMA_WHITESPACE_PRESERVE);
21500
else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21501
return (XML_SCHEMA_WHITESPACE_REPLACE);
21502
else
21503
return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21504
}
21505
return (-1);
21506
}
21507
21508
/************************************************************************
21509
* *
21510
* Simple type validation *
21511
* *
21512
************************************************************************/
21513
21514
21515
/************************************************************************
21516
* *
21517
* DOM Validation code *
21518
* *
21519
************************************************************************/
21520
21521
/**
21522
* xmlSchemaAssembleByLocation:
21523
* @pctxt: a schema parser context
21524
* @vctxt: a schema validation context
21525
* @schema: the existing schema
21526
* @node: the node that fired the assembling
21527
* @nsName: the namespace name of the new schema
21528
* @location: the location of the schema
21529
*
21530
* Expands an existing schema by an additional schema.
21531
*
21532
* Returns 0 if the new schema is correct, a positive error code
21533
* number otherwise and -1 in case of an internal or API error.
21534
*/
21535
static int
21536
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21537
xmlSchemaPtr schema,
21538
xmlNodePtr node,
21539
const xmlChar *nsName,
21540
const xmlChar *location)
21541
{
21542
int ret = 0;
21543
xmlSchemaParserCtxtPtr pctxt;
21544
xmlSchemaBucketPtr bucket = NULL;
21545
21546
if ((vctxt == NULL) || (schema == NULL))
21547
return (-1);
21548
21549
if (vctxt->pctxt == NULL) {
21550
VERROR_INT("xmlSchemaAssembleByLocation",
21551
"no parser context available");
21552
return(-1);
21553
}
21554
pctxt = vctxt->pctxt;
21555
if (pctxt->constructor == NULL) {
21556
PERROR_INT("xmlSchemaAssembleByLocation",
21557
"no constructor");
21558
return(-1);
21559
}
21560
/*
21561
* Acquire the schema document.
21562
*/
21563
location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21564
location, node);
21565
/*
21566
* Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21567
* the process will automatically change this to
21568
* XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21569
*/
21570
ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21571
location, NULL, NULL, 0, node, NULL, nsName,
21572
&bucket);
21573
if (ret != 0)
21574
return(ret);
21575
if (bucket == NULL) {
21576
/*
21577
* Generate a warning that the document could not be located.
21578
*/
21579
xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21580
node, NULL,
21581
"The document at location '%s' could not be acquired",
21582
location, NULL, NULL);
21583
return(ret);
21584
}
21585
/*
21586
* The first located schema will be handled as if all other
21587
* schemas imported by XSI were imported by this first schema.
21588
*/
21589
if ((bucket != NULL) &&
21590
(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21591
WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21592
/*
21593
* TODO: Is this handled like an import? I.e. is it not an error
21594
* if the schema cannot be located?
21595
*/
21596
if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21597
return(0);
21598
/*
21599
* We will reuse the parser context for every schema imported
21600
* directly via XSI. So reset the context.
21601
*/
21602
pctxt->nberrors = 0;
21603
pctxt->err = 0;
21604
pctxt->doc = bucket->doc;
21605
21606
ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21607
if (ret == -1) {
21608
pctxt->doc = NULL;
21609
goto exit_failure;
21610
}
21611
/* Paranoid error channelling. */
21612
if ((ret == 0) && (pctxt->nberrors != 0))
21613
ret = pctxt->err;
21614
if (pctxt->nberrors == 0) {
21615
/*
21616
* Only bother to fixup pending components, if there was
21617
* no error yet.
21618
* For every XSI acquired schema (and its sub-schemata) we will
21619
* fixup the components.
21620
*/
21621
xmlSchemaFixupComponents(pctxt, bucket);
21622
ret = pctxt->err;
21623
/*
21624
* Not nice, but we need somehow to channel the schema parser
21625
* error to the validation context.
21626
*/
21627
if ((ret != 0) && (vctxt->err == 0))
21628
vctxt->err = ret;
21629
vctxt->nberrors += pctxt->nberrors;
21630
} else {
21631
/* Add to validation error sum. */
21632
vctxt->nberrors += pctxt->nberrors;
21633
}
21634
pctxt->doc = NULL;
21635
return(ret);
21636
exit_failure:
21637
pctxt->doc = NULL;
21638
return (-1);
21639
}
21640
21641
static xmlSchemaAttrInfoPtr
21642
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21643
int metaType)
21644
{
21645
if (vctxt->nbAttrInfos == 0)
21646
return (NULL);
21647
{
21648
int i;
21649
xmlSchemaAttrInfoPtr iattr;
21650
21651
for (i = 0; i < vctxt->nbAttrInfos; i++) {
21652
iattr = vctxt->attrInfos[i];
21653
if (iattr->metaType == metaType)
21654
return (iattr);
21655
}
21656
21657
}
21658
return (NULL);
21659
}
21660
21661
/**
21662
* xmlSchemaAssembleByXSI:
21663
* @vctxt: a schema validation context
21664
*
21665
* Expands an existing schema by an additional schema using
21666
* the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21667
* of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21668
* must be set to 1.
21669
*
21670
* Returns 0 if the new schema is correct, a positive error code
21671
* number otherwise and -1 in case of an internal or API error.
21672
*/
21673
static int
21674
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21675
{
21676
const xmlChar *cur, *end;
21677
const xmlChar *nsname = NULL, *location;
21678
int ret = 0;
21679
xmlSchemaAttrInfoPtr iattr;
21680
21681
/*
21682
* Parse the value; we will assume an even number of values
21683
* to be given (this is how Xerces and XSV work).
21684
*
21685
* URGENT TODO: !! This needs to work for both
21686
* @noNamespaceSchemaLocation AND @schemaLocation on the same
21687
* element !!
21688
*/
21689
iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21690
XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21691
if (iattr == NULL)
21692
iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21693
XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21694
if (iattr == NULL)
21695
return (0);
21696
cur = iattr->value;
21697
do {
21698
/*
21699
* TODO: Move the string parsing mechanism away from here.
21700
*/
21701
if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21702
/*
21703
* Get the namespace name.
21704
*/
21705
while (IS_BLANK_CH(*cur))
21706
cur++;
21707
end = cur;
21708
while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21709
end++;
21710
if (end == cur)
21711
break;
21712
/* TODO: Don't use the schema's dict. */
21713
nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21714
cur = end;
21715
}
21716
/*
21717
* Get the URI.
21718
*/
21719
while (IS_BLANK_CH(*cur))
21720
cur++;
21721
end = cur;
21722
while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21723
end++;
21724
if (end == cur) {
21725
if (iattr->metaType ==
21726
XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21727
{
21728
/*
21729
* If using @schemaLocation then tuples are expected.
21730
* I.e. the namespace name *and* the document's URI.
21731
*/
21732
xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21733
iattr->node, NULL,
21734
"The value must consist of tuples: the target namespace "
21735
"name and the document's URI", NULL, NULL, NULL);
21736
}
21737
break;
21738
}
21739
/* TODO: Don't use the schema's dict. */
21740
location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21741
cur = end;
21742
ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21743
iattr->node, nsname, location);
21744
if (ret == -1) {
21745
VERROR_INT("xmlSchemaAssembleByXSI",
21746
"assembling schemata");
21747
return (-1);
21748
}
21749
} while (*cur != 0);
21750
return (ret);
21751
}
21752
21753
static const xmlChar *
21754
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21755
const xmlChar *prefix)
21756
{
21757
if (vctxt->sax != NULL) {
21758
int i, j;
21759
xmlSchemaNodeInfoPtr inode;
21760
21761
for (i = vctxt->depth; i >= 0; i--) {
21762
if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21763
inode = vctxt->elemInfos[i];
21764
for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21765
if (((prefix == NULL) &&
21766
(inode->nsBindings[j] == NULL)) ||
21767
((prefix != NULL) && xmlStrEqual(prefix,
21768
inode->nsBindings[j]))) {
21769
21770
/*
21771
* Note that the namespace bindings are already
21772
* in a string dict.
21773
*/
21774
return (inode->nsBindings[j+1]);
21775
}
21776
}
21777
}
21778
}
21779
return (NULL);
21780
#ifdef LIBXML_READER_ENABLED
21781
} else if (vctxt->reader != NULL) {
21782
xmlChar *nsName;
21783
21784
nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21785
if (nsName != NULL) {
21786
const xmlChar *ret;
21787
21788
ret = xmlDictLookup(vctxt->dict, nsName, -1);
21789
xmlFree(nsName);
21790
return (ret);
21791
} else
21792
return (NULL);
21793
#endif
21794
} else {
21795
xmlNsPtr ns;
21796
21797
if ((vctxt->inode->node == NULL) ||
21798
(vctxt->inode->node->doc == NULL)) {
21799
VERROR_INT("xmlSchemaLookupNamespace",
21800
"no node or node's doc available");
21801
return (NULL);
21802
}
21803
ns = xmlSearchNs(vctxt->inode->node->doc,
21804
vctxt->inode->node, prefix);
21805
if (ns != NULL)
21806
return (ns->href);
21807
return (NULL);
21808
}
21809
}
21810
21811
/*
21812
* This one works on the schema of the validation context.
21813
*/
21814
static int
21815
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21816
xmlSchemaPtr schema,
21817
xmlNodePtr node,
21818
const xmlChar *value,
21819
xmlSchemaValPtr *val,
21820
int valNeeded)
21821
{
21822
int ret;
21823
21824
if (vctxt && (vctxt->schema == NULL)) {
21825
VERROR_INT("xmlSchemaValidateNotation",
21826
"a schema is needed on the validation context");
21827
return (-1);
21828
}
21829
ret = xmlValidateQName(value, 1);
21830
if (ret != 0)
21831
return (ret);
21832
{
21833
xmlChar *localName = NULL;
21834
xmlChar *prefix = NULL;
21835
21836
localName = xmlSplitQName2(value, &prefix);
21837
if (prefix != NULL) {
21838
const xmlChar *nsName = NULL;
21839
21840
if (vctxt != NULL)
21841
nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21842
else if (node != NULL) {
21843
xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21844
if (ns != NULL)
21845
nsName = ns->href;
21846
} else {
21847
xmlFree(prefix);
21848
xmlFree(localName);
21849
return (1);
21850
}
21851
if (nsName == NULL) {
21852
xmlFree(prefix);
21853
xmlFree(localName);
21854
return (1);
21855
}
21856
if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21857
if ((valNeeded) && (val != NULL)) {
21858
(*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21859
xmlStrdup(nsName));
21860
if (*val == NULL)
21861
ret = -1;
21862
}
21863
} else
21864
ret = 1;
21865
xmlFree(prefix);
21866
xmlFree(localName);
21867
} else {
21868
if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21869
if (valNeeded && (val != NULL)) {
21870
(*val) = xmlSchemaNewNOTATIONValue(
21871
BAD_CAST xmlStrdup(value), NULL);
21872
if (*val == NULL)
21873
ret = -1;
21874
}
21875
} else
21876
return (1);
21877
}
21878
}
21879
return (ret);
21880
}
21881
21882
static int
21883
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21884
const xmlChar* lname,
21885
const xmlChar* nsname)
21886
{
21887
int i;
21888
21889
lname = xmlDictLookup(vctxt->dict, lname, -1);
21890
if (lname == NULL)
21891
return(-1);
21892
if (nsname != NULL) {
21893
nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21894
if (nsname == NULL)
21895
return(-1);
21896
}
21897
for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21898
if ((vctxt->nodeQNames->items [i] == lname) &&
21899
(vctxt->nodeQNames->items[i +1] == nsname))
21900
/* Already there */
21901
return(i);
21902
}
21903
/* Add new entry. */
21904
i = vctxt->nodeQNames->nbItems;
21905
xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21906
xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21907
return(i);
21908
}
21909
21910
/************************************************************************
21911
* *
21912
* Validation of identity-constraints (IDC) *
21913
* *
21914
************************************************************************/
21915
21916
/**
21917
* xmlSchemaAugmentIDC:
21918
* @idcDef: the IDC definition
21919
*
21920
* Creates an augmented IDC definition item.
21921
*
21922
* Returns the item, or NULL on internal errors.
21923
*/
21924
static void
21925
xmlSchemaAugmentIDC(void *payload, void *data,
21926
const xmlChar *name ATTRIBUTE_UNUSED)
21927
{
21928
xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
21929
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
21930
xmlSchemaIDCAugPtr aidc;
21931
21932
aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21933
if (aidc == NULL) {
21934
xmlSchemaVErrMemory(vctxt,
21935
"xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21936
NULL);
21937
return;
21938
}
21939
aidc->keyrefDepth = -1;
21940
aidc->def = idcDef;
21941
aidc->next = NULL;
21942
if (vctxt->aidcs == NULL)
21943
vctxt->aidcs = aidc;
21944
else {
21945
aidc->next = vctxt->aidcs;
21946
vctxt->aidcs = aidc;
21947
}
21948
/*
21949
* Save if we have keyrefs at all.
21950
*/
21951
if ((vctxt->hasKeyrefs == 0) &&
21952
(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21953
vctxt->hasKeyrefs = 1;
21954
}
21955
21956
/**
21957
* xmlSchemaAugmentImportedIDC:
21958
* @imported: the imported schema
21959
*
21960
* Creates an augmented IDC definition for the imported schema.
21961
*/
21962
static void
21963
xmlSchemaAugmentImportedIDC(void *payload, void *data,
21964
const xmlChar *name ATTRIBUTE_UNUSED) {
21965
xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
21966
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
21967
if (imported->schema->idcDef != NULL) {
21968
xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
21969
}
21970
}
21971
21972
/**
21973
* xmlSchemaIDCNewBinding:
21974
* @idcDef: the IDC definition of this binding
21975
*
21976
* Creates a new IDC binding.
21977
*
21978
* Returns the new IDC binding, NULL on internal errors.
21979
*/
21980
static xmlSchemaPSVIIDCBindingPtr
21981
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21982
{
21983
xmlSchemaPSVIIDCBindingPtr ret;
21984
21985
ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21986
sizeof(xmlSchemaPSVIIDCBinding));
21987
if (ret == NULL) {
21988
xmlSchemaVErrMemory(NULL,
21989
"allocating a PSVI IDC binding item", NULL);
21990
return (NULL);
21991
}
21992
memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21993
ret->definition = idcDef;
21994
return (ret);
21995
}
21996
21997
/**
21998
* xmlSchemaIDCStoreNodeTableItem:
21999
* @vctxt: the WXS validation context
22000
* @item: the IDC node table item
22001
*
22002
* The validation context is used to store IDC node table items.
22003
* They are stored to avoid copying them if IDC node-tables are merged
22004
* with corresponding parent IDC node-tables (bubbling).
22005
*
22006
* Returns 0 if succeeded, -1 on internal errors.
22007
*/
22008
static int
22009
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22010
xmlSchemaPSVIIDCNodePtr item)
22011
{
22012
/*
22013
* Add to global list.
22014
*/
22015
if (vctxt->idcNodes == NULL) {
22016
vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22017
xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22018
if (vctxt->idcNodes == NULL) {
22019
xmlSchemaVErrMemory(vctxt,
22020
"allocating the IDC node table item list", NULL);
22021
return (-1);
22022
}
22023
vctxt->sizeIdcNodes = 20;
22024
} else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22025
vctxt->sizeIdcNodes *= 2;
22026
vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22027
xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22028
sizeof(xmlSchemaPSVIIDCNodePtr));
22029
if (vctxt->idcNodes == NULL) {
22030
xmlSchemaVErrMemory(vctxt,
22031
"re-allocating the IDC node table item list", NULL);
22032
return (-1);
22033
}
22034
}
22035
vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22036
22037
return (0);
22038
}
22039
22040
/**
22041
* xmlSchemaIDCStoreKey:
22042
* @vctxt: the WXS validation context
22043
* @item: the IDC key
22044
*
22045
* The validation context is used to store an IDC key.
22046
*
22047
* Returns 0 if succeeded, -1 on internal errors.
22048
*/
22049
static int
22050
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22051
xmlSchemaPSVIIDCKeyPtr key)
22052
{
22053
/*
22054
* Add to global list.
22055
*/
22056
if (vctxt->idcKeys == NULL) {
22057
vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22058
xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22059
if (vctxt->idcKeys == NULL) {
22060
xmlSchemaVErrMemory(vctxt,
22061
"allocating the IDC key storage list", NULL);
22062
return (-1);
22063
}
22064
vctxt->sizeIdcKeys = 40;
22065
} else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22066
vctxt->sizeIdcKeys *= 2;
22067
vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22068
xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22069
sizeof(xmlSchemaPSVIIDCKeyPtr));
22070
if (vctxt->idcKeys == NULL) {
22071
xmlSchemaVErrMemory(vctxt,
22072
"re-allocating the IDC key storage list", NULL);
22073
return (-1);
22074
}
22075
}
22076
vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22077
22078
return (0);
22079
}
22080
22081
/**
22082
* xmlSchemaIDCAppendNodeTableItem:
22083
* @bind: the IDC binding
22084
* @ntItem: the node-table item
22085
*
22086
* Appends the IDC node-table item to the binding.
22087
*
22088
* Returns 0 on success and -1 on internal errors.
22089
*/
22090
static int
22091
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22092
xmlSchemaPSVIIDCNodePtr ntItem)
22093
{
22094
if (bind->nodeTable == NULL) {
22095
bind->sizeNodes = 10;
22096
bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22097
xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22098
if (bind->nodeTable == NULL) {
22099
xmlSchemaVErrMemory(NULL,
22100
"allocating an array of IDC node-table items", NULL);
22101
return(-1);
22102
}
22103
} else if (bind->sizeNodes <= bind->nbNodes) {
22104
bind->sizeNodes *= 2;
22105
bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22106
xmlRealloc(bind->nodeTable, bind->sizeNodes *
22107
sizeof(xmlSchemaPSVIIDCNodePtr));
22108
if (bind->nodeTable == NULL) {
22109
xmlSchemaVErrMemory(NULL,
22110
"re-allocating an array of IDC node-table items", NULL);
22111
return(-1);
22112
}
22113
}
22114
bind->nodeTable[bind->nbNodes++] = ntItem;
22115
return(0);
22116
}
22117
22118
/**
22119
* xmlSchemaIDCAcquireBinding:
22120
* @vctxt: the WXS validation context
22121
* @matcher: the IDC matcher
22122
*
22123
* Looks up an PSVI IDC binding, for the IDC definition and
22124
* of the given matcher. If none found, a new one is created
22125
* and added to the IDC table.
22126
*
22127
* Returns an IDC binding or NULL on internal errors.
22128
*/
22129
static xmlSchemaPSVIIDCBindingPtr
22130
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22131
xmlSchemaIDCMatcherPtr matcher)
22132
{
22133
xmlSchemaNodeInfoPtr ielem;
22134
22135
ielem = vctxt->elemInfos[matcher->depth];
22136
22137
if (ielem->idcTable == NULL) {
22138
ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22139
if (ielem->idcTable == NULL)
22140
return (NULL);
22141
return(ielem->idcTable);
22142
} else {
22143
xmlSchemaPSVIIDCBindingPtr bind = NULL;
22144
22145
bind = ielem->idcTable;
22146
do {
22147
if (bind->definition == matcher->aidc->def)
22148
return(bind);
22149
if (bind->next == NULL) {
22150
bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22151
if (bind->next == NULL)
22152
return (NULL);
22153
return(bind->next);
22154
}
22155
bind = bind->next;
22156
} while (bind != NULL);
22157
}
22158
return (NULL);
22159
}
22160
22161
static xmlSchemaItemListPtr
22162
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22163
xmlSchemaIDCMatcherPtr matcher)
22164
{
22165
if (matcher->targets == NULL)
22166
matcher->targets = xmlSchemaItemListCreate();
22167
return(matcher->targets);
22168
}
22169
22170
/**
22171
* xmlSchemaIDCFreeKey:
22172
* @key: the IDC key
22173
*
22174
* Frees an IDC key together with its compiled value.
22175
*/
22176
static void
22177
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22178
{
22179
if (key->val != NULL)
22180
xmlSchemaFreeValue(key->val);
22181
xmlFree(key);
22182
}
22183
22184
/**
22185
* xmlSchemaIDCFreeBinding:
22186
*
22187
* Frees an IDC binding. Note that the node table-items
22188
* are not freed.
22189
*/
22190
static void
22191
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22192
{
22193
if (bind->nodeTable != NULL)
22194
xmlFree(bind->nodeTable);
22195
if (bind->dupls != NULL)
22196
xmlSchemaItemListFree(bind->dupls);
22197
xmlFree(bind);
22198
}
22199
22200
/**
22201
* xmlSchemaIDCFreeIDCTable:
22202
* @bind: the first IDC binding in the list
22203
*
22204
* Frees an IDC table, i.e. all the IDC bindings in the list.
22205
*/
22206
static void
22207
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22208
{
22209
xmlSchemaPSVIIDCBindingPtr prev;
22210
22211
while (bind != NULL) {
22212
prev = bind;
22213
bind = bind->next;
22214
xmlSchemaIDCFreeBinding(prev);
22215
}
22216
}
22217
22218
static void
22219
xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
22220
{
22221
xmlIDCHashEntryPtr e = payload, n;
22222
while (e) {
22223
n = e->next;
22224
xmlFree(e);
22225
e = n;
22226
}
22227
}
22228
22229
/**
22230
* xmlSchemaIDCFreeMatcherList:
22231
* @matcher: the first IDC matcher in the list
22232
*
22233
* Frees a list of IDC matchers.
22234
*/
22235
static void
22236
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22237
{
22238
xmlSchemaIDCMatcherPtr next;
22239
22240
while (matcher != NULL) {
22241
next = matcher->next;
22242
if (matcher->keySeqs != NULL) {
22243
int i;
22244
for (i = 0; i < matcher->sizeKeySeqs; i++)
22245
if (matcher->keySeqs[i] != NULL)
22246
xmlFree(matcher->keySeqs[i]);
22247
xmlFree(matcher->keySeqs);
22248
}
22249
if (matcher->targets != NULL) {
22250
if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22251
int i;
22252
xmlSchemaPSVIIDCNodePtr idcNode;
22253
/*
22254
* Node-table items for keyrefs are not stored globally
22255
* to the validation context, since they are not bubbled.
22256
* We need to free them here.
22257
*/
22258
for (i = 0; i < matcher->targets->nbItems; i++) {
22259
idcNode =
22260
(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22261
xmlFree(idcNode->keys);
22262
xmlFree(idcNode);
22263
}
22264
}
22265
xmlSchemaItemListFree(matcher->targets);
22266
}
22267
if (matcher->htab != NULL)
22268
xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22269
xmlFree(matcher);
22270
matcher = next;
22271
}
22272
}
22273
22274
/**
22275
* xmlSchemaIDCReleaseMatcherList:
22276
* @vctxt: the WXS validation context
22277
* @matcher: the first IDC matcher in the list
22278
*
22279
* Caches a list of IDC matchers for reuse.
22280
*/
22281
static void
22282
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22283
xmlSchemaIDCMatcherPtr matcher)
22284
{
22285
xmlSchemaIDCMatcherPtr next;
22286
22287
while (matcher != NULL) {
22288
next = matcher->next;
22289
if (matcher->keySeqs != NULL) {
22290
int i;
22291
/*
22292
* Don't free the array, but only the content.
22293
*/
22294
for (i = 0; i < matcher->sizeKeySeqs; i++)
22295
if (matcher->keySeqs[i] != NULL) {
22296
xmlFree(matcher->keySeqs[i]);
22297
matcher->keySeqs[i] = NULL;
22298
}
22299
}
22300
if (matcher->targets) {
22301
if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22302
int i;
22303
xmlSchemaPSVIIDCNodePtr idcNode;
22304
/*
22305
* Node-table items for keyrefs are not stored globally
22306
* to the validation context, since they are not bubbled.
22307
* We need to free them here.
22308
*/
22309
for (i = 0; i < matcher->targets->nbItems; i++) {
22310
idcNode =
22311
(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22312
xmlFree(idcNode->keys);
22313
xmlFree(idcNode);
22314
}
22315
}
22316
xmlSchemaItemListFree(matcher->targets);
22317
matcher->targets = NULL;
22318
}
22319
if (matcher->htab != NULL) {
22320
xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22321
matcher->htab = NULL;
22322
}
22323
matcher->next = NULL;
22324
/*
22325
* Cache the matcher.
22326
*/
22327
if (vctxt->idcMatcherCache != NULL)
22328
matcher->nextCached = vctxt->idcMatcherCache;
22329
vctxt->idcMatcherCache = matcher;
22330
22331
matcher = next;
22332
}
22333
}
22334
22335
/**
22336
* xmlSchemaIDCAddStateObject:
22337
* @vctxt: the WXS validation context
22338
* @matcher: the IDC matcher
22339
* @sel: the XPath information
22340
* @parent: the parent "selector" state object if any
22341
* @type: "selector" or "field"
22342
*
22343
* Creates/reuses and activates state objects for the given
22344
* XPath information; if the XPath expression consists of unions,
22345
* multiple state objects are created for every unioned expression.
22346
*
22347
* Returns 0 on success and -1 on internal errors.
22348
*/
22349
static int
22350
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22351
xmlSchemaIDCMatcherPtr matcher,
22352
xmlSchemaIDCSelectPtr sel,
22353
int type)
22354
{
22355
xmlSchemaIDCStateObjPtr sto;
22356
22357
/*
22358
* Reuse the state objects from the pool.
22359
*/
22360
if (vctxt->xpathStatePool != NULL) {
22361
sto = vctxt->xpathStatePool;
22362
vctxt->xpathStatePool = sto->next;
22363
sto->next = NULL;
22364
} else {
22365
/*
22366
* Create a new state object.
22367
*/
22368
sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22369
if (sto == NULL) {
22370
xmlSchemaVErrMemory(NULL,
22371
"allocating an IDC state object", NULL);
22372
return (-1);
22373
}
22374
memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22375
}
22376
/*
22377
* Add to global list.
22378
*/
22379
if (vctxt->xpathStates != NULL)
22380
sto->next = vctxt->xpathStates;
22381
vctxt->xpathStates = sto;
22382
22383
/*
22384
* Free the old xpath validation context.
22385
*/
22386
if (sto->xpathCtxt != NULL)
22387
xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22388
22389
/*
22390
* Create a new XPath (pattern) validation context.
22391
*/
22392
sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22393
(xmlPatternPtr) sel->xpathComp);
22394
if (sto->xpathCtxt == NULL) {
22395
VERROR_INT("xmlSchemaIDCAddStateObject",
22396
"failed to create an XPath validation context");
22397
return (-1);
22398
}
22399
sto->type = type;
22400
sto->depth = vctxt->depth;
22401
sto->matcher = matcher;
22402
sto->sel = sel;
22403
sto->nbHistory = 0;
22404
22405
return (0);
22406
}
22407
22408
/**
22409
* xmlSchemaXPathEvaluate:
22410
* @vctxt: the WXS validation context
22411
* @nodeType: the nodeType of the current node
22412
*
22413
* Evaluates all active XPath state objects.
22414
*
22415
* Returns the number of IC "field" state objects which resolved to
22416
* this node, 0 if none resolved and -1 on internal errors.
22417
*/
22418
static int
22419
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22420
xmlElementType nodeType)
22421
{
22422
xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22423
int res, resolved = 0, depth = vctxt->depth;
22424
22425
if (vctxt->xpathStates == NULL)
22426
return (0);
22427
22428
if (nodeType == XML_ATTRIBUTE_NODE)
22429
depth++;
22430
/*
22431
* Process all active XPath state objects.
22432
*/
22433
first = vctxt->xpathStates;
22434
sto = first;
22435
while (sto != head) {
22436
if (nodeType == XML_ELEMENT_NODE)
22437
res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22438
vctxt->inode->localName, vctxt->inode->nsName);
22439
else
22440
res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22441
vctxt->inode->localName, vctxt->inode->nsName);
22442
22443
if (res == -1) {
22444
VERROR_INT("xmlSchemaXPathEvaluate",
22445
"calling xmlStreamPush()");
22446
return (-1);
22447
}
22448
if (res == 0)
22449
goto next_sto;
22450
/*
22451
* Full match.
22452
*/
22453
/*
22454
* Register a match in the state object history.
22455
*/
22456
if (sto->history == NULL) {
22457
sto->history = (int *) xmlMalloc(5 * sizeof(int));
22458
if (sto->history == NULL) {
22459
xmlSchemaVErrMemory(NULL,
22460
"allocating the state object history", NULL);
22461
return(-1);
22462
}
22463
sto->sizeHistory = 5;
22464
} else if (sto->sizeHistory <= sto->nbHistory) {
22465
sto->sizeHistory *= 2;
22466
sto->history = (int *) xmlRealloc(sto->history,
22467
sto->sizeHistory * sizeof(int));
22468
if (sto->history == NULL) {
22469
xmlSchemaVErrMemory(NULL,
22470
"re-allocating the state object history", NULL);
22471
return(-1);
22472
}
22473
}
22474
sto->history[sto->nbHistory++] = depth;
22475
22476
if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22477
xmlSchemaIDCSelectPtr sel;
22478
/*
22479
* Activate state objects for the IDC fields of
22480
* the IDC selector.
22481
*/
22482
sel = sto->matcher->aidc->def->fields;
22483
while (sel != NULL) {
22484
if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22485
sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22486
return (-1);
22487
sel = sel->next;
22488
}
22489
} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22490
/*
22491
* An IDC key node was found by the IDC field.
22492
*/
22493
/*
22494
* Notify that the character value of this node is
22495
* needed.
22496
*/
22497
if (resolved == 0) {
22498
if ((vctxt->inode->flags &
22499
XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22500
vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22501
}
22502
resolved++;
22503
}
22504
next_sto:
22505
if (sto->next == NULL) {
22506
/*
22507
* Evaluate field state objects created on this node as well.
22508
*/
22509
head = first;
22510
sto = vctxt->xpathStates;
22511
} else
22512
sto = sto->next;
22513
}
22514
return (resolved);
22515
}
22516
22517
static const xmlChar *
22518
xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
22519
xmlChar **buf,
22520
xmlSchemaPSVIIDCKeyPtr *seq,
22521
int count, int for_hash)
22522
{
22523
int i, res;
22524
xmlChar *value = NULL;
22525
22526
*buf = xmlStrdup(BAD_CAST "[");
22527
for (i = 0; i < count; i++) {
22528
*buf = xmlStrcat(*buf, BAD_CAST "'");
22529
if (!for_hash)
22530
res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22531
xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22532
&value);
22533
else {
22534
res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
22535
}
22536
if (res == 0)
22537
*buf = xmlStrcat(*buf, BAD_CAST value);
22538
else {
22539
VERROR_INT("xmlSchemaFormatIDCKeySequence",
22540
"failed to compute a canonical value");
22541
*buf = xmlStrcat(*buf, BAD_CAST "???");
22542
}
22543
if (i < count -1)
22544
*buf = xmlStrcat(*buf, BAD_CAST "', ");
22545
else
22546
*buf = xmlStrcat(*buf, BAD_CAST "'");
22547
if (value != NULL) {
22548
xmlFree(value);
22549
value = NULL;
22550
}
22551
}
22552
*buf = xmlStrcat(*buf, BAD_CAST "]");
22553
22554
return (BAD_CAST *buf);
22555
}
22556
22557
static const xmlChar *
22558
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22559
xmlChar **buf,
22560
xmlSchemaPSVIIDCKeyPtr *seq,
22561
int count)
22562
{
22563
return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
22564
}
22565
22566
static const xmlChar *
22567
xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
22568
xmlChar **buf,
22569
xmlSchemaPSVIIDCKeyPtr *seq,
22570
int count)
22571
{
22572
return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
22573
}
22574
22575
/**
22576
* xmlSchemaXPathPop:
22577
* @vctxt: the WXS validation context
22578
*
22579
* Pops all XPath states.
22580
*
22581
* Returns 0 on success and -1 on internal errors.
22582
*/
22583
static int
22584
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22585
{
22586
xmlSchemaIDCStateObjPtr sto;
22587
int res;
22588
22589
if (vctxt->xpathStates == NULL)
22590
return(0);
22591
sto = vctxt->xpathStates;
22592
do {
22593
res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22594
if (res == -1)
22595
return (-1);
22596
sto = sto->next;
22597
} while (sto != NULL);
22598
return(0);
22599
}
22600
22601
/**
22602
* xmlSchemaXPathProcessHistory:
22603
* @vctxt: the WXS validation context
22604
* @type: the simple/complex type of the current node if any at all
22605
* @val: the precompiled value
22606
*
22607
* Processes and pops the history items of the IDC state objects.
22608
* IDC key-sequences are validated/created on IDC bindings.
22609
*
22610
* Returns 0 on success and -1 on internal errors.
22611
*/
22612
static int
22613
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22614
int depth)
22615
{
22616
xmlSchemaIDCStateObjPtr sto, nextsto;
22617
int res, matchDepth;
22618
xmlSchemaPSVIIDCKeyPtr key = NULL;
22619
xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22620
22621
if (vctxt->xpathStates == NULL)
22622
return (0);
22623
sto = vctxt->xpathStates;
22624
22625
/*
22626
* Evaluate the state objects.
22627
*/
22628
while (sto != NULL) {
22629
res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22630
if (res == -1) {
22631
VERROR_INT("xmlSchemaXPathProcessHistory",
22632
"calling xmlStreamPop()");
22633
return (-1);
22634
}
22635
if (sto->nbHistory == 0)
22636
goto deregister_check;
22637
22638
matchDepth = sto->history[sto->nbHistory -1];
22639
22640
/*
22641
* Only matches at the current depth are of interest.
22642
*/
22643
if (matchDepth != depth) {
22644
sto = sto->next;
22645
continue;
22646
}
22647
if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22648
/*
22649
* NOTE: According to
22650
* http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22651
* ... the simple-content of complex types is also allowed.
22652
*/
22653
22654
if (WXS_IS_COMPLEX(type)) {
22655
if (WXS_HAS_SIMPLE_CONTENT(type)) {
22656
/*
22657
* Sanity check for complex types with simple content.
22658
*/
22659
simpleType = type->contentTypeDef;
22660
if (simpleType == NULL) {
22661
VERROR_INT("xmlSchemaXPathProcessHistory",
22662
"field resolves to a CT with simple content "
22663
"but the CT is missing the ST definition");
22664
return (-1);
22665
}
22666
} else
22667
simpleType = NULL;
22668
} else
22669
simpleType = type;
22670
if (simpleType == NULL) {
22671
xmlChar *str = NULL;
22672
22673
/*
22674
* Not qualified if the field resolves to a node of non
22675
* simple type.
22676
*/
22677
xmlSchemaCustomErr(ACTXT_CAST vctxt,
22678
XML_SCHEMAV_CVC_IDC, NULL,
22679
WXS_BASIC_CAST sto->matcher->aidc->def,
22680
"The XPath '%s' of a field of %s does evaluate to a node of "
22681
"non-simple type",
22682
sto->sel->xpath,
22683
xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22684
FREE_AND_NULL(str);
22685
sto->nbHistory--;
22686
goto deregister_check;
22687
}
22688
22689
if ((key == NULL) && (vctxt->inode->val == NULL)) {
22690
/*
22691
* Failed to provide the normalized value; maybe
22692
* the value was invalid.
22693
*/
22694
VERROR(XML_SCHEMAV_CVC_IDC,
22695
WXS_BASIC_CAST sto->matcher->aidc->def,
22696
"Warning: No precomputed value available, the value "
22697
"was either invalid or something strange happened");
22698
sto->nbHistory--;
22699
goto deregister_check;
22700
} else {
22701
xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22702
xmlSchemaPSVIIDCKeyPtr *keySeq;
22703
int pos, idx;
22704
22705
/*
22706
* The key will be anchored on the matcher's list of
22707
* key-sequences. The position in this list is determined
22708
* by the target node's depth relative to the matcher's
22709
* depth of creation (i.e. the depth of the scope element).
22710
*
22711
* Element Depth Pos List-entries
22712
* <scope> 0 NULL
22713
* <bar> 1 NULL
22714
* <target/> 2 2 target
22715
* <bar>
22716
* </scope>
22717
*
22718
* The size of the list is only dependent on the depth of
22719
* the tree.
22720
* An entry will be NULLed in selector_leave, i.e. when
22721
* we hit the target's
22722
*/
22723
pos = sto->depth - matcher->depth;
22724
idx = sto->sel->index;
22725
22726
/*
22727
* Create/grow the array of key-sequences.
22728
*/
22729
if (matcher->keySeqs == NULL) {
22730
if (pos > 9)
22731
matcher->sizeKeySeqs = pos * 2;
22732
else
22733
matcher->sizeKeySeqs = 10;
22734
matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22735
xmlMalloc(matcher->sizeKeySeqs *
22736
sizeof(xmlSchemaPSVIIDCKeyPtr *));
22737
if (matcher->keySeqs == NULL) {
22738
xmlSchemaVErrMemory(NULL,
22739
"allocating an array of key-sequences",
22740
NULL);
22741
return(-1);
22742
}
22743
memset(matcher->keySeqs, 0,
22744
matcher->sizeKeySeqs *
22745
sizeof(xmlSchemaPSVIIDCKeyPtr *));
22746
} else if (pos >= matcher->sizeKeySeqs) {
22747
int i = matcher->sizeKeySeqs;
22748
22749
matcher->sizeKeySeqs = pos * 2;
22750
matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22751
xmlRealloc(matcher->keySeqs,
22752
matcher->sizeKeySeqs *
22753
sizeof(xmlSchemaPSVIIDCKeyPtr *));
22754
if (matcher->keySeqs == NULL) {
22755
xmlSchemaVErrMemory(NULL,
22756
"reallocating an array of key-sequences",
22757
NULL);
22758
return (-1);
22759
}
22760
/*
22761
* The array needs to be NULLed.
22762
* TODO: Use memset?
22763
*/
22764
for (; i < matcher->sizeKeySeqs; i++)
22765
matcher->keySeqs[i] = NULL;
22766
}
22767
22768
/*
22769
* Get/create the key-sequence.
22770
*/
22771
keySeq = matcher->keySeqs[pos];
22772
if (keySeq == NULL) {
22773
goto create_sequence;
22774
} else if (keySeq[idx] != NULL) {
22775
xmlChar *str = NULL;
22776
/*
22777
* cvc-identity-constraint:
22778
* 3 For each node in the `target node set` all
22779
* of the {fields}, with that node as the context
22780
* node, evaluate to either an empty node-set or
22781
* a node-set with exactly one member, which must
22782
* have a simple type.
22783
*
22784
* The key was already set; report an error.
22785
*/
22786
xmlSchemaCustomErr(ACTXT_CAST vctxt,
22787
XML_SCHEMAV_CVC_IDC, NULL,
22788
WXS_BASIC_CAST matcher->aidc->def,
22789
"The XPath '%s' of a field of %s evaluates to a "
22790
"node-set with more than one member",
22791
sto->sel->xpath,
22792
xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22793
FREE_AND_NULL(str);
22794
sto->nbHistory--;
22795
goto deregister_check;
22796
} else
22797
goto create_key;
22798
22799
create_sequence:
22800
/*
22801
* Create a key-sequence.
22802
*/
22803
keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22804
matcher->aidc->def->nbFields *
22805
sizeof(xmlSchemaPSVIIDCKeyPtr));
22806
if (keySeq == NULL) {
22807
xmlSchemaVErrMemory(NULL,
22808
"allocating an IDC key-sequence", NULL);
22809
return(-1);
22810
}
22811
memset(keySeq, 0, matcher->aidc->def->nbFields *
22812
sizeof(xmlSchemaPSVIIDCKeyPtr));
22813
matcher->keySeqs[pos] = keySeq;
22814
create_key:
22815
/*
22816
* Create a key once per node only.
22817
*/
22818
if (key == NULL) {
22819
key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22820
sizeof(xmlSchemaPSVIIDCKey));
22821
if (key == NULL) {
22822
xmlSchemaVErrMemory(NULL,
22823
"allocating a IDC key", NULL);
22824
xmlFree(keySeq);
22825
matcher->keySeqs[pos] = NULL;
22826
return(-1);
22827
}
22828
/*
22829
* Consume the compiled value.
22830
*/
22831
key->type = simpleType;
22832
key->val = vctxt->inode->val;
22833
vctxt->inode->val = NULL;
22834
/*
22835
* Store the key in a global list.
22836
*/
22837
if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22838
xmlSchemaIDCFreeKey(key);
22839
return (-1);
22840
}
22841
}
22842
keySeq[idx] = key;
22843
}
22844
} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22845
22846
xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22847
/* xmlSchemaPSVIIDCBindingPtr bind; */
22848
xmlSchemaPSVIIDCNodePtr ntItem;
22849
xmlSchemaIDCMatcherPtr matcher;
22850
xmlSchemaIDCPtr idc;
22851
xmlSchemaItemListPtr targets;
22852
int pos, i, j, nbKeys;
22853
/*
22854
* Here we have the following scenario:
22855
* An IDC 'selector' state object resolved to a target node,
22856
* during the time this target node was in the
22857
* ancestor-or-self axis, the 'field' state object(s) looked
22858
* out for matching nodes to create a key-sequence for this
22859
* target node. Now we are back to this target node and need
22860
* to put the key-sequence, together with the target node
22861
* itself, into the node-table of the corresponding IDC
22862
* binding.
22863
*/
22864
matcher = sto->matcher;
22865
idc = matcher->aidc->def;
22866
nbKeys = idc->nbFields;
22867
pos = depth - matcher->depth;
22868
/*
22869
* Check if the matcher has any key-sequences at all, plus
22870
* if it has a key-sequence for the current target node.
22871
*/
22872
if ((matcher->keySeqs == NULL) ||
22873
(matcher->sizeKeySeqs <= pos)) {
22874
if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22875
goto selector_key_error;
22876
else
22877
goto selector_leave;
22878
}
22879
22880
keySeq = &(matcher->keySeqs[pos]);
22881
if (*keySeq == NULL) {
22882
if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22883
goto selector_key_error;
22884
else
22885
goto selector_leave;
22886
}
22887
22888
for (i = 0; i < nbKeys; i++) {
22889
if ((*keySeq)[i] == NULL) {
22890
/*
22891
* Not qualified, if not all fields did resolve.
22892
*/
22893
if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22894
/*
22895
* All fields of a "key" IDC must resolve.
22896
*/
22897
goto selector_key_error;
22898
}
22899
goto selector_leave;
22900
}
22901
}
22902
/*
22903
* All fields did resolve.
22904
*/
22905
22906
/*
22907
* 4.1 If the {identity-constraint category} is unique(/key),
22908
* then no two members of the `qualified node set` have
22909
* `key-sequences` whose members are pairwise equal, as
22910
* defined by Equal in [XML Schemas: Datatypes].
22911
*
22912
* Get the IDC binding from the matcher and check for
22913
* duplicate key-sequences.
22914
*/
22915
#if 0
22916
bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22917
#endif
22918
targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22919
if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22920
(targets->nbItems != 0)) {
22921
xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22922
xmlIDCHashEntryPtr e;
22923
22924
res = 0;
22925
22926
if (!matcher->htab)
22927
e = NULL;
22928
else {
22929
xmlChar *value = NULL;
22930
xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
22931
e = xmlHashLookup(matcher->htab, value);
22932
FREE_AND_NULL(value);
22933
}
22934
22935
/*
22936
* Compare the key-sequences, key by key.
22937
*/
22938
for (;e; e = e->next) {
22939
bkeySeq =
22940
((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
22941
for (j = 0; j < nbKeys; j++) {
22942
ckey = (*keySeq)[j];
22943
bkey = bkeySeq[j];
22944
res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22945
if (res == -1) {
22946
return (-1);
22947
} else if (res == 0) {
22948
/*
22949
* One of the keys differs, so the key-sequence
22950
* won't be equal; get out.
22951
*/
22952
break;
22953
}
22954
}
22955
if (res == 1) {
22956
/*
22957
* Duplicate key-sequence found.
22958
*/
22959
break;
22960
}
22961
}
22962
if (e) {
22963
xmlChar *str = NULL, *strB = NULL;
22964
/*
22965
* TODO: Try to report the key-sequence.
22966
*/
22967
xmlSchemaCustomErr(ACTXT_CAST vctxt,
22968
XML_SCHEMAV_CVC_IDC, NULL,
22969
WXS_BASIC_CAST idc,
22970
"Duplicate key-sequence %s in %s",
22971
xmlSchemaFormatIDCKeySequence(vctxt, &str,
22972
(*keySeq), nbKeys),
22973
xmlSchemaGetIDCDesignation(&strB, idc));
22974
FREE_AND_NULL(str);
22975
FREE_AND_NULL(strB);
22976
goto selector_leave;
22977
}
22978
}
22979
/*
22980
* Add a node-table item to the IDC binding.
22981
*/
22982
ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22983
sizeof(xmlSchemaPSVIIDCNode));
22984
if (ntItem == NULL) {
22985
xmlSchemaVErrMemory(NULL,
22986
"allocating an IDC node-table item", NULL);
22987
xmlFree(*keySeq);
22988
*keySeq = NULL;
22989
return(-1);
22990
}
22991
memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
22992
22993
/*
22994
* Store the node-table item in a global list.
22995
*/
22996
if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22997
if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22998
xmlFree(ntItem);
22999
xmlFree(*keySeq);
23000
*keySeq = NULL;
23001
return (-1);
23002
}
23003
ntItem->nodeQNameID = -1;
23004
} else {
23005
/*
23006
* Save a cached QName for this node on the IDC node, to be
23007
* able to report it, even if the node is not saved.
23008
*/
23009
ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23010
vctxt->inode->localName, vctxt->inode->nsName);
23011
if (ntItem->nodeQNameID == -1) {
23012
xmlFree(ntItem);
23013
xmlFree(*keySeq);
23014
*keySeq = NULL;
23015
return (-1);
23016
}
23017
}
23018
/*
23019
* Init the node-table item: Save the node, position and
23020
* consume the key-sequence.
23021
*/
23022
ntItem->node = vctxt->node;
23023
ntItem->nodeLine = vctxt->inode->nodeLine;
23024
ntItem->keys = *keySeq;
23025
*keySeq = NULL;
23026
#if 0
23027
if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23028
#endif
23029
if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23030
if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23031
/*
23032
* Free the item, since keyref items won't be
23033
* put on a global list.
23034
*/
23035
xmlFree(ntItem->keys);
23036
xmlFree(ntItem);
23037
}
23038
return (-1);
23039
}
23040
if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23041
xmlChar *value = NULL;
23042
xmlIDCHashEntryPtr r, e;
23043
if (!matcher->htab)
23044
matcher->htab = xmlHashCreate(4);
23045
xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
23046
e = xmlMalloc(sizeof *e);
23047
e->index = targets->nbItems - 1;
23048
r = xmlHashLookup(matcher->htab, value);
23049
if (r) {
23050
e->next = r->next;
23051
r->next = e;
23052
} else {
23053
e->next = NULL;
23054
xmlHashAddEntry(matcher->htab, value, e);
23055
}
23056
FREE_AND_NULL(value);
23057
}
23058
23059
goto selector_leave;
23060
selector_key_error:
23061
{
23062
xmlChar *str = NULL;
23063
/*
23064
* 4.2.1 (KEY) The `target node set` and the
23065
* `qualified node set` are equal, that is, every
23066
* member of the `target node set` is also a member
23067
* of the `qualified node set` and vice versa.
23068
*/
23069
xmlSchemaCustomErr(ACTXT_CAST vctxt,
23070
XML_SCHEMAV_CVC_IDC, NULL,
23071
WXS_BASIC_CAST idc,
23072
"Not all fields of %s evaluate to a node",
23073
xmlSchemaGetIDCDesignation(&str, idc), NULL);
23074
FREE_AND_NULL(str);
23075
}
23076
selector_leave:
23077
/*
23078
* Free the key-sequence if not added to the IDC table.
23079
*/
23080
if ((keySeq != NULL) && (*keySeq != NULL)) {
23081
xmlFree(*keySeq);
23082
*keySeq = NULL;
23083
}
23084
} /* if selector */
23085
23086
sto->nbHistory--;
23087
23088
deregister_check:
23089
/*
23090
* Deregister state objects if they reach the depth of creation.
23091
*/
23092
if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23093
if (vctxt->xpathStates != sto) {
23094
VERROR_INT("xmlSchemaXPathProcessHistory",
23095
"The state object to be removed is not the first "
23096
"in the list");
23097
}
23098
nextsto = sto->next;
23099
/*
23100
* Unlink from the list of active XPath state objects.
23101
*/
23102
vctxt->xpathStates = sto->next;
23103
sto->next = vctxt->xpathStatePool;
23104
/*
23105
* Link it to the pool of reusable state objects.
23106
*/
23107
vctxt->xpathStatePool = sto;
23108
sto = nextsto;
23109
} else
23110
sto = sto->next;
23111
} /* while (sto != NULL) */
23112
return (0);
23113
}
23114
23115
/**
23116
* xmlSchemaIDCRegisterMatchers:
23117
* @vctxt: the WXS validation context
23118
* @elemDecl: the element declaration
23119
*
23120
* Creates helper objects to evaluate IDC selectors/fields
23121
* successively.
23122
*
23123
* Returns 0 if OK and -1 on internal errors.
23124
*/
23125
static int
23126
xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23127
xmlSchemaElementPtr elemDecl)
23128
{
23129
xmlSchemaIDCMatcherPtr matcher, last = NULL;
23130
xmlSchemaIDCPtr idc, refIdc;
23131
xmlSchemaIDCAugPtr aidc;
23132
23133
idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23134
if (idc == NULL)
23135
return (0);
23136
23137
if (vctxt->inode->idcMatchers != NULL) {
23138
VERROR_INT("xmlSchemaIDCRegisterMatchers",
23139
"The chain of IDC matchers is expected to be empty");
23140
return (-1);
23141
}
23142
do {
23143
if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23144
/*
23145
* Since IDCs bubbles are expensive we need to know the
23146
* depth at which the bubbles should stop; this will be
23147
* the depth of the top-most keyref IDC. If no keyref
23148
* references a key/unique IDC, the keyrefDepth will
23149
* be -1, indicating that no bubbles are needed.
23150
*/
23151
refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23152
if (refIdc != NULL) {
23153
/*
23154
* Remember that we have keyrefs on this node.
23155
*/
23156
vctxt->inode->hasKeyrefs = 1;
23157
/*
23158
* Lookup the referenced augmented IDC info.
23159
*/
23160
aidc = vctxt->aidcs;
23161
while (aidc != NULL) {
23162
if (aidc->def == refIdc)
23163
break;
23164
aidc = aidc->next;
23165
}
23166
if (aidc == NULL) {
23167
VERROR_INT("xmlSchemaIDCRegisterMatchers",
23168
"Could not find an augmented IDC item for an IDC "
23169
"definition");
23170
return (-1);
23171
}
23172
if ((aidc->keyrefDepth == -1) ||
23173
(vctxt->depth < aidc->keyrefDepth))
23174
aidc->keyrefDepth = vctxt->depth;
23175
}
23176
}
23177
/*
23178
* Lookup the augmented IDC item for the IDC definition.
23179
*/
23180
aidc = vctxt->aidcs;
23181
while (aidc != NULL) {
23182
if (aidc->def == idc)
23183
break;
23184
aidc = aidc->next;
23185
}
23186
if (aidc == NULL) {
23187
VERROR_INT("xmlSchemaIDCRegisterMatchers",
23188
"Could not find an augmented IDC item for an IDC definition");
23189
return (-1);
23190
}
23191
/*
23192
* Create an IDC matcher for every IDC definition.
23193
*/
23194
if (vctxt->idcMatcherCache != NULL) {
23195
/*
23196
* Reuse a cached matcher.
23197
*/
23198
matcher = vctxt->idcMatcherCache;
23199
vctxt->idcMatcherCache = matcher->nextCached;
23200
matcher->nextCached = NULL;
23201
} else {
23202
matcher = (xmlSchemaIDCMatcherPtr)
23203
xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23204
if (matcher == NULL) {
23205
xmlSchemaVErrMemory(vctxt,
23206
"allocating an IDC matcher", NULL);
23207
return (-1);
23208
}
23209
memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23210
}
23211
if (last == NULL)
23212
vctxt->inode->idcMatchers = matcher;
23213
else
23214
last->next = matcher;
23215
last = matcher;
23216
23217
matcher->type = IDC_MATCHER;
23218
matcher->depth = vctxt->depth;
23219
matcher->aidc = aidc;
23220
matcher->idcType = aidc->def->type;
23221
/*
23222
* Init the automaton state object.
23223
*/
23224
if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23225
idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23226
return (-1);
23227
23228
idc = idc->next;
23229
} while (idc != NULL);
23230
return (0);
23231
}
23232
23233
static int
23234
xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23235
xmlSchemaNodeInfoPtr ielem)
23236
{
23237
xmlSchemaPSVIIDCBindingPtr bind;
23238
int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23239
xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23240
xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23241
23242
xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23243
/* vctxt->createIDCNodeTables */
23244
while (matcher != NULL) {
23245
/*
23246
* Skip keyref IDCs and empty IDC target-lists.
23247
*/
23248
if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23249
WXS_ILIST_IS_EMPTY(matcher->targets))
23250
{
23251
matcher = matcher->next;
23252
continue;
23253
}
23254
/*
23255
* If we _want_ the IDC node-table to be created in any case
23256
* then do so. Otherwise create them only if keyrefs need them.
23257
*/
23258
if ((! vctxt->createIDCNodeTables) &&
23259
((matcher->aidc->keyrefDepth == -1) ||
23260
(matcher->aidc->keyrefDepth > vctxt->depth)))
23261
{
23262
matcher = matcher->next;
23263
continue;
23264
}
23265
/*
23266
* Get/create the IDC binding on this element for the IDC definition.
23267
*/
23268
bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23269
if (bind == NULL)
23270
goto internal_error;
23271
23272
if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23273
dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23274
nbDupls = bind->dupls->nbItems;
23275
} else {
23276
dupls = NULL;
23277
nbDupls = 0;
23278
}
23279
if (bind->nodeTable != NULL) {
23280
nbNodeTable = bind->nbNodes;
23281
} else {
23282
nbNodeTable = 0;
23283
}
23284
23285
if ((nbNodeTable == 0) && (nbDupls == 0)) {
23286
/*
23287
* Transfer all IDC target-nodes to the IDC node-table.
23288
*/
23289
bind->nodeTable =
23290
(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23291
bind->sizeNodes = matcher->targets->sizeItems;
23292
bind->nbNodes = matcher->targets->nbItems;
23293
23294
matcher->targets->items = NULL;
23295
matcher->targets->sizeItems = 0;
23296
matcher->targets->nbItems = 0;
23297
if (matcher->htab) {
23298
xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
23299
matcher->htab = NULL;
23300
}
23301
} else {
23302
/*
23303
* Compare the key-sequences and add to the IDC node-table.
23304
*/
23305
nbTargets = matcher->targets->nbItems;
23306
targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23307
nbFields = matcher->aidc->def->nbFields;
23308
i = 0;
23309
do {
23310
keys = targets[i]->keys;
23311
if (nbDupls) {
23312
/*
23313
* Search in already found duplicates first.
23314
*/
23315
j = 0;
23316
do {
23317
if (nbFields == 1) {
23318
res = xmlSchemaAreValuesEqual(keys[0]->val,
23319
dupls[j]->keys[0]->val);
23320
if (res == -1)
23321
goto internal_error;
23322
if (res == 1) {
23323
/*
23324
* Equal key-sequence.
23325
*/
23326
goto next_target;
23327
}
23328
} else {
23329
res = 0;
23330
ntkeys = dupls[j]->keys;
23331
for (k = 0; k < nbFields; k++) {
23332
res = xmlSchemaAreValuesEqual(keys[k]->val,
23333
ntkeys[k]->val);
23334
if (res == -1)
23335
goto internal_error;
23336
if (res == 0) {
23337
/*
23338
* One of the keys differs.
23339
*/
23340
break;
23341
}
23342
}
23343
if (res == 1) {
23344
/*
23345
* Equal key-sequence found.
23346
*/
23347
goto next_target;
23348
}
23349
}
23350
j++;
23351
} while (j < nbDupls);
23352
}
23353
if (nbNodeTable) {
23354
j = 0;
23355
do {
23356
if (nbFields == 1) {
23357
res = xmlSchemaAreValuesEqual(keys[0]->val,
23358
bind->nodeTable[j]->keys[0]->val);
23359
if (res == -1)
23360
goto internal_error;
23361
if (res == 0) {
23362
/*
23363
* The key-sequence differs.
23364
*/
23365
goto next_node_table_entry;
23366
}
23367
} else {
23368
res = 0;
23369
ntkeys = bind->nodeTable[j]->keys;
23370
for (k = 0; k < nbFields; k++) {
23371
res = xmlSchemaAreValuesEqual(keys[k]->val,
23372
ntkeys[k]->val);
23373
if (res == -1)
23374
goto internal_error;
23375
if (res == 0) {
23376
/*
23377
* One of the keys differs.
23378
*/
23379
goto next_node_table_entry;
23380
}
23381
}
23382
}
23383
/*
23384
* Add the duplicate to the list of duplicates.
23385
*/
23386
if (bind->dupls == NULL) {
23387
bind->dupls = xmlSchemaItemListCreate();
23388
if (bind->dupls == NULL)
23389
goto internal_error;
23390
}
23391
if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23392
goto internal_error;
23393
dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23394
/*
23395
* Remove the duplicate entry from the IDC node-table.
23396
*/
23397
bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23398
bind->nbNodes--;
23399
23400
goto next_target;
23401
23402
next_node_table_entry:
23403
j++;
23404
} while (j < nbNodeTable);
23405
}
23406
/*
23407
* If everything is fine, then add the IDC target-node to
23408
* the IDC node-table.
23409
*/
23410
if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23411
goto internal_error;
23412
23413
next_target:
23414
i++;
23415
} while (i < nbTargets);
23416
}
23417
matcher = matcher->next;
23418
}
23419
return(0);
23420
23421
internal_error:
23422
return(-1);
23423
}
23424
23425
/**
23426
* xmlSchemaBubbleIDCNodeTables:
23427
* @depth: the current tree depth
23428
*
23429
* Merges IDC bindings of an element at @depth into the corresponding IDC
23430
* bindings of its parent element. If a duplicate note-table entry is found,
23431
* both, the parent node-table entry and child entry are discarded from the
23432
* node-table of the parent.
23433
*
23434
* Returns 0 if OK and -1 on internal errors.
23435
*/
23436
static int
23437
xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23438
{
23439
xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23440
xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23441
xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23442
xmlSchemaIDCAugPtr aidc;
23443
int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23444
23445
bind = vctxt->inode->idcTable;
23446
if (bind == NULL) {
23447
/* Fine, no table, no bubbles. */
23448
return (0);
23449
}
23450
23451
parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23452
/*
23453
* Walk all bindings; create new or add to existing bindings.
23454
* Remove duplicate key-sequences.
23455
*/
23456
while (bind != NULL) {
23457
23458
if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23459
goto next_binding;
23460
/*
23461
* Check if the key/unique IDC table needs to be bubbled.
23462
*/
23463
if (! vctxt->createIDCNodeTables) {
23464
aidc = vctxt->aidcs;
23465
do {
23466
if (aidc->def == bind->definition) {
23467
if ((aidc->keyrefDepth == -1) ||
23468
(aidc->keyrefDepth >= vctxt->depth)) {
23469
goto next_binding;
23470
}
23471
break;
23472
}
23473
aidc = aidc->next;
23474
} while (aidc != NULL);
23475
}
23476
23477
if (parTable != NULL)
23478
parBind = *parTable;
23479
/*
23480
* Search a matching parent binding for the
23481
* IDC definition.
23482
*/
23483
while (parBind != NULL) {
23484
if (parBind->definition == bind->definition)
23485
break;
23486
parBind = parBind->next;
23487
}
23488
23489
if (parBind != NULL) {
23490
/*
23491
* Compare every node-table entry of the child node,
23492
* i.e. the key-sequence within, ...
23493
*/
23494
oldNum = parBind->nbNodes; /* Skip newly added items. */
23495
23496
if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23497
oldDupls = parBind->dupls->nbItems;
23498
dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23499
} else {
23500
dupls = NULL;
23501
oldDupls = 0;
23502
}
23503
23504
parNodes = parBind->nodeTable;
23505
nbFields = bind->definition->nbFields;
23506
23507
for (i = 0; i < bind->nbNodes; i++) {
23508
node = bind->nodeTable[i];
23509
if (node == NULL)
23510
continue;
23511
/*
23512
* ...with every key-sequence of the parent node, already
23513
* evaluated to be a duplicate key-sequence.
23514
*/
23515
if (oldDupls) {
23516
j = 0;
23517
while (j < oldDupls) {
23518
if (nbFields == 1) {
23519
ret = xmlSchemaAreValuesEqual(
23520
node->keys[0]->val,
23521
dupls[j]->keys[0]->val);
23522
if (ret == -1)
23523
goto internal_error;
23524
if (ret == 0) {
23525
j++;
23526
continue;
23527
}
23528
} else {
23529
parNode = dupls[j];
23530
for (k = 0; k < nbFields; k++) {
23531
ret = xmlSchemaAreValuesEqual(
23532
node->keys[k]->val,
23533
parNode->keys[k]->val);
23534
if (ret == -1)
23535
goto internal_error;
23536
if (ret == 0)
23537
break;
23538
}
23539
}
23540
if (ret == 1)
23541
/* Duplicate found. */
23542
break;
23543
j++;
23544
}
23545
if (j != oldDupls) {
23546
/* Duplicate found. Skip this entry. */
23547
continue;
23548
}
23549
}
23550
/*
23551
* ... and with every key-sequence of the parent node.
23552
*/
23553
if (oldNum) {
23554
j = 0;
23555
while (j < oldNum) {
23556
parNode = parNodes[j];
23557
if (nbFields == 1) {
23558
ret = xmlSchemaAreValuesEqual(
23559
node->keys[0]->val,
23560
parNode->keys[0]->val);
23561
if (ret == -1)
23562
goto internal_error;
23563
if (ret == 0) {
23564
j++;
23565
continue;
23566
}
23567
} else {
23568
for (k = 0; k < nbFields; k++) {
23569
ret = xmlSchemaAreValuesEqual(
23570
node->keys[k]->val,
23571
parNode->keys[k]->val);
23572
if (ret == -1)
23573
goto internal_error;
23574
if (ret == 0)
23575
break;
23576
}
23577
}
23578
if (ret == 1)
23579
/* Duplicate found. */
23580
break;
23581
j++;
23582
}
23583
if (j != oldNum) {
23584
/*
23585
* Handle duplicates. Move the duplicate in
23586
* the parent's node-table to the list of
23587
* duplicates.
23588
*/
23589
oldNum--;
23590
parBind->nbNodes--;
23591
/*
23592
* Move last old item to pos of duplicate.
23593
*/
23594
parNodes[j] = parNodes[oldNum];
23595
23596
if (parBind->nbNodes != oldNum) {
23597
/*
23598
* If new items exist, move last new item to
23599
* last of old items.
23600
*/
23601
parNodes[oldNum] =
23602
parNodes[parBind->nbNodes];
23603
}
23604
if (parBind->dupls == NULL) {
23605
parBind->dupls = xmlSchemaItemListCreate();
23606
if (parBind->dupls == NULL)
23607
goto internal_error;
23608
}
23609
xmlSchemaItemListAdd(parBind->dupls, parNode);
23610
dupls = (xmlSchemaPSVIIDCNodePtr *)
23611
parBind->dupls->items;
23612
} else {
23613
/*
23614
* Add the node-table entry (node and key-sequence) of
23615
* the child node to the node table of the parent node.
23616
*/
23617
if (parBind->nodeTable == NULL) {
23618
parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23619
xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23620
if (parBind->nodeTable == NULL) {
23621
xmlSchemaVErrMemory(NULL,
23622
"allocating IDC list of node-table items", NULL);
23623
goto internal_error;
23624
}
23625
parBind->sizeNodes = 1;
23626
} else if (parBind->nbNodes >= parBind->sizeNodes) {
23627
parBind->sizeNodes *= 2;
23628
parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23629
xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23630
sizeof(xmlSchemaPSVIIDCNodePtr));
23631
if (parBind->nodeTable == NULL) {
23632
xmlSchemaVErrMemory(NULL,
23633
"re-allocating IDC list of node-table items", NULL);
23634
goto internal_error;
23635
}
23636
}
23637
parNodes = parBind->nodeTable;
23638
/*
23639
* Append the new node-table entry to the 'new node-table
23640
* entries' section.
23641
*/
23642
parNodes[parBind->nbNodes++] = node;
23643
}
23644
23645
}
23646
23647
}
23648
} else {
23649
/*
23650
* No binding for the IDC was found: create a new one and
23651
* copy all node-tables.
23652
*/
23653
parBind = xmlSchemaIDCNewBinding(bind->definition);
23654
if (parBind == NULL)
23655
goto internal_error;
23656
23657
/*
23658
* TODO: Hmm, how to optimize the initial number of
23659
* allocated entries?
23660
*/
23661
if (bind->nbNodes != 0) {
23662
/*
23663
* Add all IDC node-table entries.
23664
*/
23665
if (! vctxt->psviExposeIDCNodeTables) {
23666
/*
23667
* Just move the entries.
23668
* NOTE: this is quite save here, since
23669
* all the keyref lookups have already been
23670
* performed.
23671
*/
23672
parBind->nodeTable = bind->nodeTable;
23673
bind->nodeTable = NULL;
23674
parBind->sizeNodes = bind->sizeNodes;
23675
bind->sizeNodes = 0;
23676
parBind->nbNodes = bind->nbNodes;
23677
bind->nbNodes = 0;
23678
} else {
23679
/*
23680
* Copy the entries.
23681
*/
23682
parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23683
xmlMalloc(bind->nbNodes *
23684
sizeof(xmlSchemaPSVIIDCNodePtr));
23685
if (parBind->nodeTable == NULL) {
23686
xmlSchemaVErrMemory(NULL,
23687
"allocating an array of IDC node-table "
23688
"items", NULL);
23689
xmlSchemaIDCFreeBinding(parBind);
23690
goto internal_error;
23691
}
23692
parBind->sizeNodes = bind->nbNodes;
23693
parBind->nbNodes = bind->nbNodes;
23694
memcpy(parBind->nodeTable, bind->nodeTable,
23695
bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23696
}
23697
}
23698
if (bind->dupls) {
23699
/*
23700
* Move the duplicates.
23701
*/
23702
if (parBind->dupls != NULL)
23703
xmlSchemaItemListFree(parBind->dupls);
23704
parBind->dupls = bind->dupls;
23705
bind->dupls = NULL;
23706
}
23707
if (parTable != NULL) {
23708
if (*parTable == NULL)
23709
*parTable = parBind;
23710
else {
23711
parBind->next = *parTable;
23712
*parTable = parBind;
23713
}
23714
}
23715
}
23716
23717
next_binding:
23718
bind = bind->next;
23719
}
23720
return (0);
23721
23722
internal_error:
23723
return(-1);
23724
}
23725
23726
/**
23727
* xmlSchemaCheckCVCIDCKeyRef:
23728
* @vctxt: the WXS validation context
23729
* @elemDecl: the element declaration
23730
*
23731
* Check the cvc-idc-keyref constraints.
23732
*/
23733
static int
23734
xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23735
{
23736
xmlSchemaIDCMatcherPtr matcher;
23737
xmlSchemaPSVIIDCBindingPtr bind;
23738
23739
matcher = vctxt->inode->idcMatchers;
23740
/*
23741
* Find a keyref.
23742
*/
23743
while (matcher != NULL) {
23744
if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23745
matcher->targets &&
23746
matcher->targets->nbItems)
23747
{
23748
int i, j, k, res, nbFields, hasDupls;
23749
xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23750
xmlSchemaPSVIIDCNodePtr refNode = NULL;
23751
xmlHashTablePtr table = NULL;
23752
23753
nbFields = matcher->aidc->def->nbFields;
23754
23755
/*
23756
* Find the IDC node-table for the referenced IDC key/unique.
23757
*/
23758
bind = vctxt->inode->idcTable;
23759
while (bind != NULL) {
23760
if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23761
bind->definition)
23762
break;
23763
bind = bind->next;
23764
}
23765
hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23766
/*
23767
* Search for a matching key-sequences.
23768
*/
23769
if (bind) {
23770
table = xmlHashCreate(bind->nbNodes * 2);
23771
for (j = 0; j < bind->nbNodes; j++) {
23772
xmlChar *value;
23773
xmlIDCHashEntryPtr r, e;
23774
keys = bind->nodeTable[j]->keys;
23775
xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
23776
e = xmlMalloc(sizeof *e);
23777
e->index = j;
23778
r = xmlHashLookup(table, value);
23779
if (r) {
23780
e->next = r->next;
23781
r->next = e;
23782
} else {
23783
e->next = NULL;
23784
xmlHashAddEntry(table, value, e);
23785
}
23786
FREE_AND_NULL(value);
23787
}
23788
}
23789
for (i = 0; i < matcher->targets->nbItems; i++) {
23790
res = 0;
23791
refNode = matcher->targets->items[i];
23792
if (bind != NULL) {
23793
xmlChar *value;
23794
xmlIDCHashEntryPtr e;
23795
refKeys = refNode->keys;
23796
xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
23797
e = xmlHashLookup(table, value);
23798
FREE_AND_NULL(value);
23799
res = 0;
23800
for (;e; e = e->next) {
23801
keys = bind->nodeTable[e->index]->keys;
23802
for (k = 0; k < nbFields; k++) {
23803
res = xmlSchemaAreValuesEqual(keys[k]->val,
23804
refKeys[k]->val);
23805
if (res == 0)
23806
break;
23807
else if (res == -1) {
23808
return (-1);
23809
}
23810
}
23811
if (res == 1) {
23812
/*
23813
* Match found.
23814
*/
23815
break;
23816
}
23817
}
23818
if ((res == 0) && hasDupls) {
23819
/*
23820
* Search in duplicates
23821
*/
23822
for (j = 0; j < bind->dupls->nbItems; j++) {
23823
keys = ((xmlSchemaPSVIIDCNodePtr)
23824
bind->dupls->items[j])->keys;
23825
for (k = 0; k < nbFields; k++) {
23826
res = xmlSchemaAreValuesEqual(keys[k]->val,
23827
refKeys[k]->val);
23828
if (res == 0)
23829
break;
23830
else if (res == -1) {
23831
return (-1);
23832
}
23833
}
23834
if (res == 1) {
23835
/*
23836
* Match in duplicates found.
23837
*/
23838
xmlChar *str = NULL, *strB = NULL;
23839
xmlSchemaKeyrefErr(vctxt,
23840
XML_SCHEMAV_CVC_IDC, refNode,
23841
(xmlSchemaTypePtr) matcher->aidc->def,
23842
"More than one match found for "
23843
"key-sequence %s of keyref '%s'",
23844
xmlSchemaFormatIDCKeySequence(vctxt, &str,
23845
refNode->keys, nbFields),
23846
xmlSchemaGetComponentQName(&strB,
23847
matcher->aidc->def));
23848
FREE_AND_NULL(str);
23849
FREE_AND_NULL(strB);
23850
break;
23851
}
23852
}
23853
}
23854
}
23855
23856
if (res == 0) {
23857
xmlChar *str = NULL, *strB = NULL;
23858
xmlSchemaKeyrefErr(vctxt,
23859
XML_SCHEMAV_CVC_IDC, refNode,
23860
(xmlSchemaTypePtr) matcher->aidc->def,
23861
"No match found for key-sequence %s of keyref '%s'",
23862
xmlSchemaFormatIDCKeySequence(vctxt, &str,
23863
refNode->keys, nbFields),
23864
xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23865
FREE_AND_NULL(str);
23866
FREE_AND_NULL(strB);
23867
}
23868
}
23869
if (table) {
23870
xmlHashFree(table, xmlFreeIDCHashEntry);
23871
}
23872
}
23873
matcher = matcher->next;
23874
}
23875
/* TODO: Return an error if any error encountered. */
23876
return (0);
23877
}
23878
23879
/************************************************************************
23880
* *
23881
* XML Reader validation code *
23882
* *
23883
************************************************************************/
23884
23885
static xmlSchemaAttrInfoPtr
23886
xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23887
{
23888
xmlSchemaAttrInfoPtr iattr;
23889
/*
23890
* Grow/create list of attribute infos.
23891
*/
23892
if (vctxt->attrInfos == NULL) {
23893
vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23894
xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23895
vctxt->sizeAttrInfos = 1;
23896
if (vctxt->attrInfos == NULL) {
23897
xmlSchemaVErrMemory(vctxt,
23898
"allocating attribute info list", NULL);
23899
return (NULL);
23900
}
23901
} else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23902
vctxt->sizeAttrInfos++;
23903
vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23904
xmlRealloc(vctxt->attrInfos,
23905
vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23906
if (vctxt->attrInfos == NULL) {
23907
xmlSchemaVErrMemory(vctxt,
23908
"re-allocating attribute info list", NULL);
23909
return (NULL);
23910
}
23911
} else {
23912
iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23913
if (iattr->localName != NULL) {
23914
VERROR_INT("xmlSchemaGetFreshAttrInfo",
23915
"attr info not cleared");
23916
return (NULL);
23917
}
23918
iattr->nodeType = XML_ATTRIBUTE_NODE;
23919
return (iattr);
23920
}
23921
/*
23922
* Create an attribute info.
23923
*/
23924
iattr = (xmlSchemaAttrInfoPtr)
23925
xmlMalloc(sizeof(xmlSchemaAttrInfo));
23926
if (iattr == NULL) {
23927
xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23928
return (NULL);
23929
}
23930
memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23931
iattr->nodeType = XML_ATTRIBUTE_NODE;
23932
vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23933
23934
return (iattr);
23935
}
23936
23937
static int
23938
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23939
xmlNodePtr attrNode,
23940
int nodeLine,
23941
const xmlChar *localName,
23942
const xmlChar *nsName,
23943
int ownedNames,
23944
xmlChar *value,
23945
int ownedValue)
23946
{
23947
xmlSchemaAttrInfoPtr attr;
23948
23949
attr = xmlSchemaGetFreshAttrInfo(vctxt);
23950
if (attr == NULL) {
23951
VERROR_INT("xmlSchemaPushAttribute",
23952
"calling xmlSchemaGetFreshAttrInfo()");
23953
return (-1);
23954
}
23955
attr->node = attrNode;
23956
attr->nodeLine = nodeLine;
23957
attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23958
attr->localName = localName;
23959
attr->nsName = nsName;
23960
if (ownedNames)
23961
attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23962
/*
23963
* Evaluate if it's an XSI attribute.
23964
*/
23965
if (nsName != NULL) {
23966
if (xmlStrEqual(localName, BAD_CAST "nil")) {
23967
if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23968
attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23969
}
23970
} else if (xmlStrEqual(localName, BAD_CAST "type")) {
23971
if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23972
attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23973
}
23974
} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23975
if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23976
attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23977
}
23978
} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23979
if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23980
attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23981
}
23982
} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23983
attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23984
}
23985
}
23986
attr->value = value;
23987
if (ownedValue)
23988
attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23989
if (attr->metaType != 0)
23990
attr->state = XML_SCHEMAS_ATTR_META;
23991
return (0);
23992
}
23993
23994
/**
23995
* xmlSchemaClearElemInfo:
23996
* @vctxt: the WXS validation context
23997
* @ielem: the element information item
23998
*/
23999
static void
24000
xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24001
xmlSchemaNodeInfoPtr ielem)
24002
{
24003
ielem->hasKeyrefs = 0;
24004
ielem->appliedXPath = 0;
24005
if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24006
FREE_AND_NULL(ielem->localName);
24007
FREE_AND_NULL(ielem->nsName);
24008
} else {
24009
ielem->localName = NULL;
24010
ielem->nsName = NULL;
24011
}
24012
if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24013
FREE_AND_NULL(ielem->value);
24014
} else {
24015
ielem->value = NULL;
24016
}
24017
if (ielem->val != NULL) {
24018
/*
24019
* PSVI TODO: Be careful not to free it when the value is
24020
* exposed via PSVI.
24021
*/
24022
xmlSchemaFreeValue(ielem->val);
24023
ielem->val = NULL;
24024
}
24025
if (ielem->idcMatchers != NULL) {
24026
/*
24027
* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24028
* Does it work?
24029
*/
24030
xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24031
#if 0
24032
xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24033
#endif
24034
ielem->idcMatchers = NULL;
24035
}
24036
if (ielem->idcTable != NULL) {
24037
/*
24038
* OPTIMIZE TODO: Use a pool of IDC tables??.
24039
*/
24040
xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24041
ielem->idcTable = NULL;
24042
}
24043
if (ielem->regexCtxt != NULL) {
24044
xmlRegFreeExecCtxt(ielem->regexCtxt);
24045
ielem->regexCtxt = NULL;
24046
}
24047
if (ielem->nsBindings != NULL) {
24048
xmlFree((xmlChar **)ielem->nsBindings);
24049
ielem->nsBindings = NULL;
24050
ielem->nbNsBindings = 0;
24051
ielem->sizeNsBindings = 0;
24052
}
24053
}
24054
24055
/**
24056
* xmlSchemaGetFreshElemInfo:
24057
* @vctxt: the schema validation context
24058
*
24059
* Creates/reuses and initializes the element info item for
24060
* the current tree depth.
24061
*
24062
* Returns the element info item or NULL on API or internal errors.
24063
*/
24064
static xmlSchemaNodeInfoPtr
24065
xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24066
{
24067
xmlSchemaNodeInfoPtr info = NULL;
24068
24069
if (vctxt->depth > vctxt->sizeElemInfos) {
24070
VERROR_INT("xmlSchemaGetFreshElemInfo",
24071
"inconsistent depth encountered");
24072
return (NULL);
24073
}
24074
if (vctxt->elemInfos == NULL) {
24075
vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24076
xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24077
if (vctxt->elemInfos == NULL) {
24078
xmlSchemaVErrMemory(vctxt,
24079
"allocating the element info array", NULL);
24080
return (NULL);
24081
}
24082
memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24083
vctxt->sizeElemInfos = 10;
24084
} else if (vctxt->sizeElemInfos <= vctxt->depth) {
24085
int i = vctxt->sizeElemInfos;
24086
24087
vctxt->sizeElemInfos *= 2;
24088
vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24089
xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24090
sizeof(xmlSchemaNodeInfoPtr));
24091
if (vctxt->elemInfos == NULL) {
24092
xmlSchemaVErrMemory(vctxt,
24093
"re-allocating the element info array", NULL);
24094
return (NULL);
24095
}
24096
/*
24097
* We need the new memory to be NULLed.
24098
* TODO: Use memset instead?
24099
*/
24100
for (; i < vctxt->sizeElemInfos; i++)
24101
vctxt->elemInfos[i] = NULL;
24102
} else
24103
info = vctxt->elemInfos[vctxt->depth];
24104
24105
if (info == NULL) {
24106
info = (xmlSchemaNodeInfoPtr)
24107
xmlMalloc(sizeof(xmlSchemaNodeInfo));
24108
if (info == NULL) {
24109
xmlSchemaVErrMemory(vctxt,
24110
"allocating an element info", NULL);
24111
return (NULL);
24112
}
24113
vctxt->elemInfos[vctxt->depth] = info;
24114
} else {
24115
if (info->localName != NULL) {
24116
VERROR_INT("xmlSchemaGetFreshElemInfo",
24117
"elem info has not been cleared");
24118
return (NULL);
24119
}
24120
}
24121
memset(info, 0, sizeof(xmlSchemaNodeInfo));
24122
info->nodeType = XML_ELEMENT_NODE;
24123
info->depth = vctxt->depth;
24124
24125
return (info);
24126
}
24127
24128
#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24129
#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24130
#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24131
24132
static int
24133
xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24134
xmlNodePtr node,
24135
xmlSchemaTypePtr type,
24136
xmlSchemaValType valType,
24137
const xmlChar * value,
24138
xmlSchemaValPtr val,
24139
unsigned long length,
24140
int fireErrors)
24141
{
24142
int ret, error = 0, found;
24143
24144
xmlSchemaTypePtr tmpType;
24145
xmlSchemaFacetLinkPtr facetLink;
24146
xmlSchemaFacetPtr facet;
24147
unsigned long len = 0;
24148
xmlSchemaWhitespaceValueType ws;
24149
24150
/*
24151
* In Libxml2, derived built-in types have currently no explicit facets.
24152
*/
24153
if (type->type == XML_SCHEMA_TYPE_BASIC)
24154
return (0);
24155
24156
/*
24157
* NOTE: Do not jump away, if the facetSet of the given type is
24158
* empty: until now, "pattern" and "enumeration" facets of the
24159
* *base types* need to be checked as well.
24160
*/
24161
if (type->facetSet == NULL)
24162
goto pattern_and_enum;
24163
24164
if (! WXS_IS_ATOMIC(type)) {
24165
if (WXS_IS_LIST(type))
24166
goto WXS_IS_LIST;
24167
else
24168
goto pattern_and_enum;
24169
}
24170
24171
/*
24172
* Whitespace handling is only of importance for string-based
24173
* types.
24174
*/
24175
tmpType = xmlSchemaGetPrimitiveType(type);
24176
if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24177
WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24178
ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24179
} else
24180
ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24181
24182
/*
24183
* If the value was not computed (for string or
24184
* anySimpleType based types), then use the provided
24185
* type.
24186
*/
24187
if (val != NULL)
24188
valType = xmlSchemaGetValType(val);
24189
24190
ret = 0;
24191
for (facetLink = type->facetSet; facetLink != NULL;
24192
facetLink = facetLink->next) {
24193
/*
24194
* Skip the pattern "whiteSpace": it is used to
24195
* format the character content beforehand.
24196
*/
24197
switch (facetLink->facet->type) {
24198
case XML_SCHEMA_FACET_WHITESPACE:
24199
case XML_SCHEMA_FACET_PATTERN:
24200
case XML_SCHEMA_FACET_ENUMERATION:
24201
continue;
24202
case XML_SCHEMA_FACET_LENGTH:
24203
case XML_SCHEMA_FACET_MINLENGTH:
24204
case XML_SCHEMA_FACET_MAXLENGTH:
24205
ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24206
valType, value, val, &len, ws);
24207
break;
24208
default:
24209
ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24210
valType, value, val, ws);
24211
break;
24212
}
24213
if (ret < 0) {
24214
AERROR_INT("xmlSchemaValidateFacets",
24215
"validating against a atomic type facet");
24216
return (-1);
24217
} else if (ret > 0) {
24218
if (fireErrors)
24219
xmlSchemaFacetErr(actxt, ret, node,
24220
value, len, type, facetLink->facet, NULL, NULL, NULL);
24221
else
24222
return (ret);
24223
if (error == 0)
24224
error = ret;
24225
}
24226
ret = 0;
24227
}
24228
24229
WXS_IS_LIST:
24230
if (! WXS_IS_LIST(type))
24231
goto pattern_and_enum;
24232
/*
24233
* "length", "minLength" and "maxLength" of list types.
24234
*/
24235
ret = 0;
24236
for (facetLink = type->facetSet; facetLink != NULL;
24237
facetLink = facetLink->next) {
24238
24239
switch (facetLink->facet->type) {
24240
case XML_SCHEMA_FACET_LENGTH:
24241
case XML_SCHEMA_FACET_MINLENGTH:
24242
case XML_SCHEMA_FACET_MAXLENGTH:
24243
ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24244
value, length, NULL);
24245
break;
24246
default:
24247
continue;
24248
}
24249
if (ret < 0) {
24250
AERROR_INT("xmlSchemaValidateFacets",
24251
"validating against a list type facet");
24252
return (-1);
24253
} else if (ret > 0) {
24254
if (fireErrors)
24255
xmlSchemaFacetErr(actxt, ret, node,
24256
value, length, type, facetLink->facet, NULL, NULL, NULL);
24257
else
24258
return (ret);
24259
if (error == 0)
24260
error = ret;
24261
}
24262
ret = 0;
24263
}
24264
24265
pattern_and_enum:
24266
found = 0;
24267
/*
24268
* Process enumerations. Facet values are in the value space
24269
* of the defining type's base type. This seems to be a bug in the
24270
* XML Schema 1.0 spec. Use the whitespace type of the base type.
24271
* Only the first set of enumerations in the ancestor-or-self axis
24272
* is used for validation.
24273
*/
24274
ret = 0;
24275
tmpType = type;
24276
do {
24277
for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24278
if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24279
continue;
24280
found = 1;
24281
ret = xmlSchemaAreValuesEqual(facet->val, val);
24282
if (ret == 1)
24283
break;
24284
else if (ret < 0) {
24285
AERROR_INT("xmlSchemaValidateFacets",
24286
"validating against an enumeration facet");
24287
return (-1);
24288
}
24289
}
24290
if (ret != 0)
24291
break;
24292
/*
24293
* Break on the first set of enumerations. Any additional
24294
* enumerations which might be existent on the ancestors
24295
* of the current type are restricted by this set; thus
24296
* *must* *not* be taken into account.
24297
*/
24298
if (found)
24299
break;
24300
tmpType = tmpType->baseType;
24301
} while ((tmpType != NULL) &&
24302
(tmpType->type != XML_SCHEMA_TYPE_BASIC));
24303
if (found && (ret == 0)) {
24304
ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24305
if (fireErrors) {
24306
xmlSchemaFacetErr(actxt, ret, node,
24307
value, 0, type, NULL, NULL, NULL, NULL);
24308
} else
24309
return (ret);
24310
if (error == 0)
24311
error = ret;
24312
}
24313
24314
/*
24315
* Process patters. Pattern facets are ORed at type level
24316
* and ANDed if derived. Walk the base type axis.
24317
*/
24318
tmpType = type;
24319
facet = NULL;
24320
do {
24321
found = 0;
24322
for (facetLink = tmpType->facetSet; facetLink != NULL;
24323
facetLink = facetLink->next) {
24324
if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24325
continue;
24326
found = 1;
24327
/*
24328
* NOTE that for patterns, @value needs to be the
24329
* normalized value.
24330
*/
24331
ret = xmlRegexpExec(facetLink->facet->regexp, value);
24332
if (ret == 1)
24333
break;
24334
else if (ret < 0) {
24335
AERROR_INT("xmlSchemaValidateFacets",
24336
"validating against a pattern facet");
24337
return (-1);
24338
} else {
24339
/*
24340
* Save the last non-validating facet.
24341
*/
24342
facet = facetLink->facet;
24343
}
24344
}
24345
if (found && (ret != 1)) {
24346
ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24347
if (fireErrors) {
24348
xmlSchemaFacetErr(actxt, ret, node,
24349
value, 0, type, facet, NULL, NULL, NULL);
24350
} else
24351
return (ret);
24352
if (error == 0)
24353
error = ret;
24354
break;
24355
}
24356
tmpType = tmpType->baseType;
24357
} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24358
24359
return (error);
24360
}
24361
24362
static xmlChar *
24363
xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24364
const xmlChar *value)
24365
{
24366
switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24367
case XML_SCHEMA_WHITESPACE_COLLAPSE:
24368
return (xmlSchemaCollapseString(value));
24369
case XML_SCHEMA_WHITESPACE_REPLACE:
24370
return (xmlSchemaWhiteSpaceReplace(value));
24371
default:
24372
return (NULL);
24373
}
24374
}
24375
24376
static int
24377
xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24378
const xmlChar *value,
24379
xmlSchemaValPtr *val,
24380
int valNeeded)
24381
{
24382
int ret;
24383
xmlChar *stripped;
24384
const xmlChar *nsName;
24385
xmlChar *local, *prefix = NULL;
24386
24387
ret = xmlValidateQName(value, 1);
24388
if (ret != 0) {
24389
if (ret == -1) {
24390
VERROR_INT("xmlSchemaValidateQName",
24391
"calling xmlValidateQName()");
24392
return (-1);
24393
}
24394
return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24395
}
24396
/*
24397
* NOTE: xmlSplitQName2 will always return a duplicated
24398
* strings.
24399
*/
24400
/* TODO: Export and use xmlSchemaStrip instead */
24401
stripped = xmlSchemaCollapseString(value);
24402
local = xmlSplitQName2(stripped ? stripped : value, &prefix);
24403
xmlFree(stripped);
24404
if (local == NULL)
24405
local = xmlStrdup(value);
24406
/*
24407
* OPTIMIZE TODO: Use flags for:
24408
* - is there any namespace binding?
24409
* - is there a default namespace?
24410
*/
24411
nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24412
24413
if (prefix != NULL) {
24414
xmlFree(prefix);
24415
/*
24416
* A namespace must be found if the prefix is
24417
* NOT NULL.
24418
*/
24419
if (nsName == NULL) {
24420
ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24421
xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24422
WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24423
"The QName value '%s' has no "
24424
"corresponding namespace declaration in "
24425
"scope", value, NULL);
24426
if (local != NULL)
24427
xmlFree(local);
24428
return (ret);
24429
}
24430
}
24431
if (valNeeded && val) {
24432
if (nsName != NULL)
24433
*val = xmlSchemaNewQNameValue(
24434
BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24435
else
24436
*val = xmlSchemaNewQNameValue(NULL,
24437
BAD_CAST local);
24438
} else
24439
xmlFree(local);
24440
return (0);
24441
}
24442
24443
/*
24444
* cvc-simple-type
24445
*/
24446
static int
24447
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24448
xmlNodePtr node,
24449
xmlSchemaTypePtr type,
24450
const xmlChar *value,
24451
xmlSchemaValPtr *retVal,
24452
int fireErrors,
24453
int normalize,
24454
int isNormalized)
24455
{
24456
int ret = 0, valNeeded = (retVal) ? 1 : 0;
24457
xmlSchemaValPtr val = NULL;
24458
/* xmlSchemaWhitespaceValueType ws; */
24459
xmlChar *normValue = NULL;
24460
24461
#define NORMALIZE(atype) \
24462
if ((! isNormalized) && \
24463
(normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24464
normValue = xmlSchemaNormalizeValue(atype, value); \
24465
if (normValue != NULL) \
24466
value = normValue; \
24467
isNormalized = 1; \
24468
}
24469
24470
if ((retVal != NULL) && (*retVal != NULL)) {
24471
xmlSchemaFreeValue(*retVal);
24472
*retVal = NULL;
24473
}
24474
/*
24475
* 3.14.4 Simple Type Definition Validation Rules
24476
* Validation Rule: String Valid
24477
*/
24478
/*
24479
* 1 It is schema-valid with respect to that definition as defined
24480
* by Datatype Valid in [XML Schemas: Datatypes].
24481
*/
24482
/*
24483
* 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24484
* the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24485
* the string must be a `declared entity name`.
24486
*/
24487
/*
24488
* 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24489
* given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24490
* then every whitespace-delimited substring of the string must be a `declared
24491
* entity name`.
24492
*/
24493
/*
24494
* 2.3 otherwise no further condition applies.
24495
*/
24496
if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24497
valNeeded = 1;
24498
if (value == NULL)
24499
value = BAD_CAST "";
24500
if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24501
xmlSchemaTypePtr biType; /* The built-in type. */
24502
/*
24503
* SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24504
* a literal in the `lexical space` of {base type definition}"
24505
*/
24506
/*
24507
* Whitespace-normalize.
24508
*/
24509
NORMALIZE(type);
24510
if (type->type != XML_SCHEMA_TYPE_BASIC) {
24511
/*
24512
* Get the built-in type.
24513
*/
24514
biType = type->baseType;
24515
while ((biType != NULL) &&
24516
(biType->type != XML_SCHEMA_TYPE_BASIC))
24517
biType = biType->baseType;
24518
24519
if (biType == NULL) {
24520
AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24521
"could not get the built-in type");
24522
goto internal_error;
24523
}
24524
} else
24525
biType = type;
24526
/*
24527
* NOTATIONs need to be processed here, since they need
24528
* to lookup in the hashtable of NOTATION declarations of the schema.
24529
*/
24530
if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24531
switch (biType->builtInType) {
24532
case XML_SCHEMAS_NOTATION:
24533
ret = xmlSchemaValidateNotation(
24534
(xmlSchemaValidCtxtPtr) actxt,
24535
((xmlSchemaValidCtxtPtr) actxt)->schema,
24536
NULL, value, &val, valNeeded);
24537
break;
24538
case XML_SCHEMAS_QNAME:
24539
ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24540
value, &val, valNeeded);
24541
break;
24542
default:
24543
/* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24544
if (valNeeded)
24545
ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24546
value, &val, node);
24547
else
24548
ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24549
value, NULL, node);
24550
break;
24551
}
24552
} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24553
switch (biType->builtInType) {
24554
case XML_SCHEMAS_NOTATION:
24555
ret = xmlSchemaValidateNotation(NULL,
24556
((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24557
value, &val, valNeeded);
24558
break;
24559
default:
24560
/* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24561
if (valNeeded)
24562
ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24563
value, &val, node);
24564
else
24565
ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24566
value, NULL, node);
24567
break;
24568
}
24569
} else {
24570
/*
24571
* Validation via a public API is not implemented yet.
24572
*/
24573
TODO
24574
goto internal_error;
24575
}
24576
if (ret != 0) {
24577
if (ret < 0) {
24578
AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24579
"validating against a built-in type");
24580
goto internal_error;
24581
}
24582
if (WXS_IS_LIST(type))
24583
ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24584
else
24585
ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24586
}
24587
if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24588
/*
24589
* Check facets.
24590
*/
24591
ret = xmlSchemaValidateFacets(actxt, node, type,
24592
(xmlSchemaValType) biType->builtInType, value, val,
24593
0, fireErrors);
24594
if (ret != 0) {
24595
if (ret < 0) {
24596
AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24597
"validating facets of atomic simple type");
24598
goto internal_error;
24599
}
24600
if (WXS_IS_LIST(type))
24601
ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24602
else
24603
ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24604
}
24605
}
24606
else if (fireErrors && (ret > 0))
24607
xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24608
} else if (WXS_IS_LIST(type)) {
24609
24610
xmlSchemaTypePtr itemType;
24611
const xmlChar *cur, *end;
24612
xmlChar *tmpValue = NULL;
24613
unsigned long len = 0;
24614
xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24615
/* 1.2.2 if {variety} is `list` then the string must be a sequence
24616
* of white space separated tokens, each of which `match`es a literal
24617
* in the `lexical space` of {item type definition}
24618
*/
24619
/*
24620
* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24621
* the list type has an enum or pattern facet.
24622
*/
24623
NORMALIZE(type);
24624
/*
24625
* VAL TODO: Optimize validation of empty values.
24626
* VAL TODO: We do not have computed values for lists.
24627
*/
24628
itemType = WXS_LIST_ITEMTYPE(type);
24629
cur = value;
24630
do {
24631
while (IS_BLANK_CH(*cur))
24632
cur++;
24633
end = cur;
24634
while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24635
end++;
24636
if (end == cur)
24637
break;
24638
tmpValue = xmlStrndup(cur, end - cur);
24639
len++;
24640
24641
if (valNeeded)
24642
ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24643
tmpValue, &curVal, fireErrors, 0, 1);
24644
else
24645
ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24646
tmpValue, NULL, fireErrors, 0, 1);
24647
FREE_AND_NULL(tmpValue);
24648
if (curVal != NULL) {
24649
/*
24650
* Add to list of computed values.
24651
*/
24652
if (val == NULL)
24653
val = curVal;
24654
else
24655
xmlSchemaValueAppend(prevVal, curVal);
24656
prevVal = curVal;
24657
curVal = NULL;
24658
}
24659
if (ret != 0) {
24660
if (ret < 0) {
24661
AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24662
"validating an item of list simple type");
24663
goto internal_error;
24664
}
24665
ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24666
break;
24667
}
24668
cur = end;
24669
} while (*cur != 0);
24670
FREE_AND_NULL(tmpValue);
24671
if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24672
/*
24673
* Apply facets (pattern, enumeration).
24674
*/
24675
ret = xmlSchemaValidateFacets(actxt, node, type,
24676
XML_SCHEMAS_UNKNOWN, value, val,
24677
len, fireErrors);
24678
if (ret != 0) {
24679
if (ret < 0) {
24680
AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24681
"validating facets of list simple type");
24682
goto internal_error;
24683
}
24684
ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24685
}
24686
}
24687
if (fireErrors && (ret > 0)) {
24688
/*
24689
* Report the normalized value.
24690
*/
24691
normalize = 1;
24692
NORMALIZE(type);
24693
xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24694
}
24695
} else if (WXS_IS_UNION(type)) {
24696
xmlSchemaTypeLinkPtr memberLink;
24697
/*
24698
* TODO: For all datatypes `derived` by `union` whiteSpace does
24699
* not apply directly; however, the normalization behavior of `union`
24700
* types is controlled by the value of whiteSpace on that one of the
24701
* `memberTypes` against which the `union` is successfully validated.
24702
*
24703
* This means that the value is normalized by the first validating
24704
* member type, then the facets of the union type are applied. This
24705
* needs changing of the value!
24706
*/
24707
24708
/*
24709
* 1.2.3 if {variety} is `union` then the string must `match` a
24710
* literal in the `lexical space` of at least one member of
24711
* {member type definitions}
24712
*/
24713
memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24714
if (memberLink == NULL) {
24715
AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24716
"union simple type has no member types");
24717
goto internal_error;
24718
}
24719
/*
24720
* Always normalize union type values, since we currently
24721
* cannot store the whitespace information with the value
24722
* itself; otherwise a later value-comparison would be
24723
* not possible.
24724
*/
24725
while (memberLink != NULL) {
24726
if (valNeeded)
24727
ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24728
memberLink->type, value, &val, 0, 1, 0);
24729
else
24730
ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24731
memberLink->type, value, NULL, 0, 1, 0);
24732
if (ret <= 0)
24733
break;
24734
memberLink = memberLink->next;
24735
}
24736
if (ret != 0) {
24737
if (ret < 0) {
24738
AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24739
"validating members of union simple type");
24740
goto internal_error;
24741
}
24742
ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24743
}
24744
/*
24745
* Apply facets (pattern, enumeration).
24746
*/
24747
if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24748
/*
24749
* The normalization behavior of `union` types is controlled by
24750
* the value of whiteSpace on that one of the `memberTypes`
24751
* against which the `union` is successfully validated.
24752
*/
24753
NORMALIZE(memberLink->type);
24754
ret = xmlSchemaValidateFacets(actxt, node, type,
24755
XML_SCHEMAS_UNKNOWN, value, val,
24756
0, fireErrors);
24757
if (ret != 0) {
24758
if (ret < 0) {
24759
AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24760
"validating facets of union simple type");
24761
goto internal_error;
24762
}
24763
ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24764
}
24765
}
24766
if (fireErrors && (ret > 0))
24767
xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24768
}
24769
24770
if (normValue != NULL)
24771
xmlFree(normValue);
24772
if (ret == 0) {
24773
if (retVal != NULL)
24774
*retVal = val;
24775
else if (val != NULL)
24776
xmlSchemaFreeValue(val);
24777
} else if (val != NULL)
24778
xmlSchemaFreeValue(val);
24779
return (ret);
24780
internal_error:
24781
if (normValue != NULL)
24782
xmlFree(normValue);
24783
if (val != NULL)
24784
xmlSchemaFreeValue(val);
24785
return (-1);
24786
}
24787
24788
static int
24789
xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24790
const xmlChar *value,
24791
const xmlChar **nsName,
24792
const xmlChar **localName)
24793
{
24794
int ret = 0;
24795
24796
if ((nsName == NULL) || (localName == NULL))
24797
return (-1);
24798
*nsName = NULL;
24799
*localName = NULL;
24800
24801
ret = xmlValidateQName(value, 1);
24802
if (ret == -1)
24803
return (-1);
24804
if (ret > 0) {
24805
xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24806
XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24807
value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24808
return (1);
24809
}
24810
{
24811
xmlChar *local = NULL;
24812
xmlChar *prefix;
24813
24814
/*
24815
* NOTE: xmlSplitQName2 will return a duplicated
24816
* string.
24817
*/
24818
local = xmlSplitQName2(value, &prefix);
24819
if (local == NULL)
24820
*localName = xmlDictLookup(vctxt->dict, value, -1);
24821
else {
24822
*localName = xmlDictLookup(vctxt->dict, local, -1);
24823
xmlFree(local);
24824
}
24825
24826
*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24827
24828
if (prefix != NULL) {
24829
xmlFree(prefix);
24830
/*
24831
* A namespace must be found if the prefix is NOT NULL.
24832
*/
24833
if (*nsName == NULL) {
24834
xmlSchemaCustomErr(ACTXT_CAST vctxt,
24835
XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24836
WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24837
"The QName value '%s' has no "
24838
"corresponding namespace declaration in scope",
24839
value, NULL);
24840
return (2);
24841
}
24842
}
24843
}
24844
return (0);
24845
}
24846
24847
static int
24848
xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24849
xmlSchemaAttrInfoPtr iattr,
24850
xmlSchemaTypePtr *localType,
24851
xmlSchemaElementPtr elemDecl)
24852
{
24853
int ret = 0;
24854
/*
24855
* cvc-elt (3.3.4) : (4)
24856
* AND
24857
* Schema-Validity Assessment (Element) (cvc-assess-elt)
24858
* (1.2.1.2.1) - (1.2.1.2.4)
24859
* Handle 'xsi:type'.
24860
*/
24861
if (localType == NULL)
24862
return (-1);
24863
*localType = NULL;
24864
if (iattr == NULL)
24865
return (0);
24866
else {
24867
const xmlChar *nsName = NULL, *local = NULL;
24868
/*
24869
* TODO: We should report a *warning* that the type was overridden
24870
* by the instance.
24871
*/
24872
ACTIVATE_ATTRIBUTE(iattr);
24873
/*
24874
* (cvc-elt) (3.3.4) : (4.1)
24875
* (cvc-assess-elt) (1.2.1.2.2)
24876
*/
24877
ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24878
&nsName, &local);
24879
if (ret != 0) {
24880
if (ret < 0) {
24881
VERROR_INT("xmlSchemaValidateElementByDeclaration",
24882
"calling xmlSchemaQNameExpand() to validate the "
24883
"attribute 'xsi:type'");
24884
goto internal_error;
24885
}
24886
goto exit;
24887
}
24888
/*
24889
* (cvc-elt) (3.3.4) : (4.2)
24890
* (cvc-assess-elt) (1.2.1.2.3)
24891
*/
24892
*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24893
if (*localType == NULL) {
24894
xmlChar *str = NULL;
24895
24896
xmlSchemaCustomErr(ACTXT_CAST vctxt,
24897
XML_SCHEMAV_CVC_ELT_4_2, NULL,
24898
WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24899
"The QName value '%s' of the xsi:type attribute does not "
24900
"resolve to a type definition",
24901
xmlSchemaFormatQName(&str, nsName, local), NULL);
24902
FREE_AND_NULL(str);
24903
ret = vctxt->err;
24904
goto exit;
24905
}
24906
if (elemDecl != NULL) {
24907
int set = 0;
24908
24909
/*
24910
* SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24911
* "The `local type definition` must be validly
24912
* derived from the {type definition} given the union of
24913
* the {disallowed substitutions} and the {type definition}'s
24914
* {prohibited substitutions}, as defined in
24915
* Type Derivation OK (Complex) ($3.4.6)
24916
* (if it is a complex type definition),
24917
* or given {disallowed substitutions} as defined in Type
24918
* Derivation OK (Simple) ($3.14.6) (if it is a simple type
24919
* definition)."
24920
*
24921
* {disallowed substitutions}: the "block" on the element decl.
24922
* {prohibited substitutions}: the "block" on the type def.
24923
*/
24924
/*
24925
* OPTIMIZE TODO: We could map types already evaluated
24926
* to be validly derived from other types to avoid checking
24927
* this over and over for the same types.
24928
*/
24929
if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24930
(elemDecl->subtypes->flags &
24931
XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24932
set |= SUBSET_EXTENSION;
24933
24934
if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24935
(elemDecl->subtypes->flags &
24936
XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24937
set |= SUBSET_RESTRICTION;
24938
24939
/*
24940
* REMOVED and CHANGED since this produced a parser context
24941
* which adds to the string dict of the schema. So this would
24942
* change the schema and we don't want this. We don't need
24943
* the parser context anymore.
24944
*
24945
* if ((vctxt->pctxt == NULL) &&
24946
* (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24947
* return (-1);
24948
*/
24949
24950
if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24951
elemDecl->subtypes, set) != 0) {
24952
xmlChar *str = NULL;
24953
24954
xmlSchemaCustomErr(ACTXT_CAST vctxt,
24955
XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24956
"The type definition '%s', specified by xsi:type, is "
24957
"blocked or not validly derived from the type definition "
24958
"of the element declaration",
24959
xmlSchemaFormatQName(&str,
24960
(*localType)->targetNamespace,
24961
(*localType)->name),
24962
NULL);
24963
FREE_AND_NULL(str);
24964
ret = vctxt->err;
24965
*localType = NULL;
24966
}
24967
}
24968
}
24969
exit:
24970
ACTIVATE_ELEM;
24971
return (ret);
24972
internal_error:
24973
ACTIVATE_ELEM;
24974
return (-1);
24975
}
24976
24977
static int
24978
xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24979
{
24980
xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24981
xmlSchemaTypePtr actualType;
24982
24983
/*
24984
* cvc-elt (3.3.4) : 1
24985
*/
24986
if (elemDecl == NULL) {
24987
VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24988
"No matching declaration available");
24989
return (vctxt->err);
24990
}
24991
actualType = WXS_ELEM_TYPEDEF(elemDecl);
24992
/*
24993
* cvc-elt (3.3.4) : 2
24994
*/
24995
if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24996
VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24997
"The element declaration is abstract");
24998
return (vctxt->err);
24999
}
25000
if (actualType == NULL) {
25001
VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25002
"The type definition is absent");
25003
return (XML_SCHEMAV_CVC_TYPE_1);
25004
}
25005
if (vctxt->nbAttrInfos != 0) {
25006
int ret;
25007
xmlSchemaAttrInfoPtr iattr;
25008
/*
25009
* cvc-elt (3.3.4) : 3
25010
* Handle 'xsi:nil'.
25011
*/
25012
iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25013
XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25014
if (iattr) {
25015
ACTIVATE_ATTRIBUTE(iattr);
25016
/*
25017
* Validate the value.
25018
*/
25019
ret = xmlSchemaVCheckCVCSimpleType(
25020
ACTXT_CAST vctxt, NULL,
25021
xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25022
iattr->value, &(iattr->val), 1, 0, 0);
25023
ACTIVATE_ELEM;
25024
if (ret < 0) {
25025
VERROR_INT("xmlSchemaValidateElemDecl",
25026
"calling xmlSchemaVCheckCVCSimpleType() to "
25027
"validate the attribute 'xsi:nil'");
25028
return (-1);
25029
}
25030
if (ret == 0) {
25031
if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25032
/*
25033
* cvc-elt (3.3.4) : 3.1
25034
*/
25035
VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25036
"The element is not 'nillable'");
25037
/* Does not return an error on purpose. */
25038
} else {
25039
if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25040
/*
25041
* cvc-elt (3.3.4) : 3.2.2
25042
*/
25043
if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25044
(elemDecl->value != NULL)) {
25045
VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25046
"The element cannot be 'nilled' because "
25047
"there is a fixed value constraint defined "
25048
"for it");
25049
/* Does not return an error on purpose. */
25050
} else
25051
vctxt->inode->flags |=
25052
XML_SCHEMA_ELEM_INFO_NILLED;
25053
}
25054
}
25055
}
25056
}
25057
/*
25058
* cvc-elt (3.3.4) : 4
25059
* Handle 'xsi:type'.
25060
*/
25061
iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25062
XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25063
if (iattr) {
25064
xmlSchemaTypePtr localType = NULL;
25065
25066
ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25067
elemDecl);
25068
if (ret != 0) {
25069
if (ret == -1) {
25070
VERROR_INT("xmlSchemaValidateElemDecl",
25071
"calling xmlSchemaProcessXSIType() to "
25072
"process the attribute 'xsi:type'");
25073
return (-1);
25074
}
25075
/* Does not return an error on purpose. */
25076
}
25077
if (localType != NULL) {
25078
vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25079
actualType = localType;
25080
}
25081
}
25082
}
25083
/*
25084
* IDC: Register identity-constraint XPath matchers.
25085
*/
25086
if ((elemDecl->idcs != NULL) &&
25087
(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25088
return (-1);
25089
/*
25090
* No actual type definition.
25091
*/
25092
if (actualType == NULL) {
25093
VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25094
"The type definition is absent");
25095
return (XML_SCHEMAV_CVC_TYPE_1);
25096
}
25097
/*
25098
* Remember the actual type definition.
25099
*/
25100
vctxt->inode->typeDef = actualType;
25101
25102
return (0);
25103
}
25104
25105
static int
25106
xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25107
{
25108
xmlSchemaAttrInfoPtr iattr;
25109
int ret = 0, i;
25110
25111
/*
25112
* SPEC cvc-type (3.1.1)
25113
* "The attributes of must be empty, excepting those whose namespace
25114
* name is identical to http://www.w3.org/2001/XMLSchema-instance and
25115
* whose local name is one of type, nil, schemaLocation or
25116
* noNamespaceSchemaLocation."
25117
*/
25118
if (vctxt->nbAttrInfos == 0)
25119
return (0);
25120
for (i = 0; i < vctxt->nbAttrInfos; i++) {
25121
iattr = vctxt->attrInfos[i];
25122
if (! iattr->metaType) {
25123
ACTIVATE_ATTRIBUTE(iattr)
25124
xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25125
XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25126
ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25127
}
25128
}
25129
ACTIVATE_ELEM
25130
return (ret);
25131
}
25132
25133
/*
25134
* Cleanup currently used attribute infos.
25135
*/
25136
static void
25137
xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25138
{
25139
int i;
25140
xmlSchemaAttrInfoPtr attr;
25141
25142
if (vctxt->nbAttrInfos == 0)
25143
return;
25144
for (i = 0; i < vctxt->nbAttrInfos; i++) {
25145
attr = vctxt->attrInfos[i];
25146
if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25147
if (attr->localName != NULL)
25148
xmlFree((xmlChar *) attr->localName);
25149
if (attr->nsName != NULL)
25150
xmlFree((xmlChar *) attr->nsName);
25151
}
25152
if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25153
if (attr->value != NULL)
25154
xmlFree((xmlChar *) attr->value);
25155
}
25156
if (attr->val != NULL) {
25157
xmlSchemaFreeValue(attr->val);
25158
attr->val = NULL;
25159
}
25160
memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25161
}
25162
vctxt->nbAttrInfos = 0;
25163
}
25164
25165
/*
25166
* 3.4.4 Complex Type Definition Validation Rules
25167
* Element Locally Valid (Complex Type) (cvc-complex-type)
25168
* 3.2.4 Attribute Declaration Validation Rules
25169
* Validation Rule: Attribute Locally Valid (cvc-attribute)
25170
* Attribute Locally Valid (Use) (cvc-au)
25171
*
25172
* Only "assessed" attribute information items will be visible to
25173
* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25174
*/
25175
static int
25176
xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25177
{
25178
xmlSchemaTypePtr type = vctxt->inode->typeDef;
25179
xmlSchemaItemListPtr attrUseList;
25180
xmlSchemaAttributeUsePtr attrUse = NULL;
25181
xmlSchemaAttributePtr attrDecl = NULL;
25182
xmlSchemaAttrInfoPtr iattr, tmpiattr;
25183
int i, j, found, nbAttrs, nbUses;
25184
int xpathRes = 0, res, wildIDs = 0, fixed;
25185
xmlNodePtr defAttrOwnerElem = NULL;
25186
25187
/*
25188
* SPEC (cvc-attribute)
25189
* (1) "The declaration must not be `absent` (see Missing
25190
* Sub-components ($5.3) for how this can fail to be
25191
* the case)."
25192
* (2) "Its {type definition} must not be absent."
25193
*
25194
* NOTE (1) + (2): This is not handled here, since we currently do not
25195
* allow validation against schemas which have missing sub-components.
25196
*
25197
* SPEC (cvc-complex-type)
25198
* (3) "For each attribute information item in the element information
25199
* item's [attributes] excepting those whose [namespace name] is
25200
* identical to http://www.w3.org/2001/XMLSchema-instance and whose
25201
* [local name] is one of type, nil, schemaLocation or
25202
* noNamespaceSchemaLocation, the appropriate case among the following
25203
* must be true:
25204
*
25205
*/
25206
attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25207
/*
25208
* @nbAttrs is the number of attributes present in the instance.
25209
*/
25210
nbAttrs = vctxt->nbAttrInfos;
25211
if (attrUseList != NULL)
25212
nbUses = attrUseList->nbItems;
25213
else
25214
nbUses = 0;
25215
for (i = 0; i < nbUses; i++) {
25216
found = 0;
25217
attrUse = attrUseList->items[i];
25218
attrDecl = WXS_ATTRUSE_DECL(attrUse);
25219
for (j = 0; j < nbAttrs; j++) {
25220
iattr = vctxt->attrInfos[j];
25221
/*
25222
* SPEC (cvc-complex-type) (3)
25223
* Skip meta attributes.
25224
*/
25225
if (iattr->metaType)
25226
continue;
25227
if (iattr->localName[0] != attrDecl->name[0])
25228
continue;
25229
if (!xmlStrEqual(iattr->localName, attrDecl->name))
25230
continue;
25231
if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25232
continue;
25233
found = 1;
25234
/*
25235
* SPEC (cvc-complex-type)
25236
* (3.1) "If there is among the {attribute uses} an attribute
25237
* use with an {attribute declaration} whose {name} matches
25238
* the attribute information item's [local name] and whose
25239
* {target namespace} is identical to the attribute information
25240
* item's [namespace name] (where an `absent` {target namespace}
25241
* is taken to be identical to a [namespace name] with no value),
25242
* then the attribute information must be `valid` with respect
25243
* to that attribute use as per Attribute Locally Valid (Use)
25244
* ($3.5.4). In this case the {attribute declaration} of that
25245
* attribute use is the `context-determined declaration` for the
25246
* attribute information item with respect to Schema-Validity
25247
* Assessment (Attribute) ($3.2.4) and
25248
* Assessment Outcome (Attribute) ($3.2.5).
25249
*/
25250
iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25251
iattr->use = attrUse;
25252
/*
25253
* Context-determined declaration.
25254
*/
25255
iattr->decl = attrDecl;
25256
iattr->typeDef = attrDecl->subtypes;
25257
break;
25258
}
25259
25260
if (found)
25261
continue;
25262
25263
if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25264
/*
25265
* Handle non-existent, required attributes.
25266
*
25267
* SPEC (cvc-complex-type)
25268
* (4) "The {attribute declaration} of each attribute use in
25269
* the {attribute uses} whose {required} is true matches one
25270
* of the attribute information items in the element information
25271
* item's [attributes] as per clause 3.1 above."
25272
*/
25273
tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25274
if (tmpiattr == NULL) {
25275
VERROR_INT(
25276
"xmlSchemaVAttributesComplex",
25277
"calling xmlSchemaGetFreshAttrInfo()");
25278
return (-1);
25279
}
25280
tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25281
tmpiattr->use = attrUse;
25282
tmpiattr->decl = attrDecl;
25283
} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25284
((attrUse->defValue != NULL) ||
25285
(attrDecl->defValue != NULL))) {
25286
/*
25287
* Handle non-existent, optional, default/fixed attributes.
25288
*/
25289
tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25290
if (tmpiattr == NULL) {
25291
VERROR_INT(
25292
"xmlSchemaVAttributesComplex",
25293
"calling xmlSchemaGetFreshAttrInfo()");
25294
return (-1);
25295
}
25296
tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25297
tmpiattr->use = attrUse;
25298
tmpiattr->decl = attrDecl;
25299
tmpiattr->typeDef = attrDecl->subtypes;
25300
tmpiattr->localName = attrDecl->name;
25301
tmpiattr->nsName = attrDecl->targetNamespace;
25302
}
25303
}
25304
25305
if (vctxt->nbAttrInfos == 0)
25306
return (0);
25307
/*
25308
* Validate against the wildcard.
25309
*/
25310
if (type->attributeWildcard != NULL) {
25311
/*
25312
* SPEC (cvc-complex-type)
25313
* (3.2.1) "There must be an {attribute wildcard}."
25314
*/
25315
for (i = 0; i < nbAttrs; i++) {
25316
iattr = vctxt->attrInfos[i];
25317
/*
25318
* SPEC (cvc-complex-type) (3)
25319
* Skip meta attributes.
25320
*/
25321
if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25322
continue;
25323
/*
25324
* SPEC (cvc-complex-type)
25325
* (3.2.2) "The attribute information item must be `valid` with
25326
* respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25327
*
25328
* SPEC Item Valid (Wildcard) (cvc-wildcard)
25329
* "... its [namespace name] must be `valid` with respect to
25330
* the wildcard constraint, as defined in Wildcard allows
25331
* Namespace Name ($3.10.4)."
25332
*/
25333
if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25334
iattr->nsName) == 0) {
25335
/*
25336
* Handle processContents.
25337
*
25338
* SPEC (cvc-wildcard):
25339
* processContents | context-determined declaration:
25340
* "strict" "mustFind"
25341
* "lax" "none"
25342
* "skip" "skip"
25343
*/
25344
if (type->attributeWildcard->processContents ==
25345
XML_SCHEMAS_ANY_SKIP) {
25346
/*
25347
* context-determined declaration = "skip"
25348
*
25349
* SPEC PSVI Assessment Outcome (Attribute)
25350
* [validity] = "notKnown"
25351
* [validation attempted] = "none"
25352
*/
25353
iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25354
continue;
25355
}
25356
/*
25357
* Find an attribute declaration.
25358
*/
25359
iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25360
iattr->localName, iattr->nsName);
25361
if (iattr->decl != NULL) {
25362
iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25363
/*
25364
* SPEC (cvc-complex-type)
25365
* (5) "Let [Definition:] the wild IDs be the set of
25366
* all attribute information item to which clause 3.2
25367
* applied and whose `validation` resulted in a
25368
* `context-determined declaration` of mustFind or no
25369
* `context-determined declaration` at all, and whose
25370
* [local name] and [namespace name] resolve (as
25371
* defined by QName resolution (Instance) ($3.15.4)) to
25372
* an attribute declaration whose {type definition} is
25373
* or is derived from ID. Then all of the following
25374
* must be true:"
25375
*/
25376
iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25377
if (xmlSchemaIsDerivedFromBuiltInType(
25378
iattr->typeDef, XML_SCHEMAS_ID)) {
25379
/*
25380
* SPEC (5.1) "There must be no more than one
25381
* item in `wild IDs`."
25382
*/
25383
if (wildIDs != 0) {
25384
/* VAL TODO */
25385
iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25386
TODO
25387
continue;
25388
}
25389
wildIDs++;
25390
/*
25391
* SPEC (cvc-complex-type)
25392
* (5.2) "If `wild IDs` is non-empty, there must not
25393
* be any attribute uses among the {attribute uses}
25394
* whose {attribute declaration}'s {type definition}
25395
* is or is derived from ID."
25396
*/
25397
if (attrUseList != NULL) {
25398
for (j = 0; j < attrUseList->nbItems; j++) {
25399
if (xmlSchemaIsDerivedFromBuiltInType(
25400
WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25401
XML_SCHEMAS_ID)) {
25402
/* URGENT VAL TODO: implement */
25403
iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25404
TODO
25405
break;
25406
}
25407
}
25408
}
25409
}
25410
} else if (type->attributeWildcard->processContents ==
25411
XML_SCHEMAS_ANY_LAX) {
25412
iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25413
/*
25414
* SPEC PSVI Assessment Outcome (Attribute)
25415
* [validity] = "notKnown"
25416
* [validation attempted] = "none"
25417
*/
25418
} else {
25419
iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25420
}
25421
}
25422
}
25423
}
25424
25425
if (vctxt->nbAttrInfos == 0)
25426
return (0);
25427
25428
/*
25429
* Get the owner element; needed for creation of default attributes.
25430
* This fixes bug #341337, reported by David Grohmann.
25431
*/
25432
if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25433
xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25434
if (ielem && ielem->node && ielem->node->doc)
25435
defAttrOwnerElem = ielem->node;
25436
}
25437
/*
25438
* Validate values, create default attributes, evaluate IDCs.
25439
*/
25440
for (i = 0; i < vctxt->nbAttrInfos; i++) {
25441
iattr = vctxt->attrInfos[i];
25442
/*
25443
* VAL TODO: Note that we won't try to resolve IDCs to
25444
* "lax" and "skip" validated attributes. Check what to
25445
* do in this case.
25446
*/
25447
if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25448
(iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25449
continue;
25450
/*
25451
* VAL TODO: What to do if the type definition is missing?
25452
*/
25453
if (iattr->typeDef == NULL) {
25454
iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25455
continue;
25456
}
25457
25458
ACTIVATE_ATTRIBUTE(iattr);
25459
fixed = 0;
25460
xpathRes = 0;
25461
25462
if (vctxt->xpathStates != NULL) {
25463
/*
25464
* Evaluate IDCs.
25465
*/
25466
xpathRes = xmlSchemaXPathEvaluate(vctxt,
25467
XML_ATTRIBUTE_NODE);
25468
if (xpathRes == -1) {
25469
VERROR_INT("xmlSchemaVAttributesComplex",
25470
"calling xmlSchemaXPathEvaluate()");
25471
goto internal_error;
25472
}
25473
}
25474
25475
if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25476
/*
25477
* Default/fixed attributes.
25478
* We need the value only if we need to resolve IDCs or
25479
* will create default attributes.
25480
*/
25481
if ((xpathRes) || (defAttrOwnerElem)) {
25482
if (iattr->use->defValue != NULL) {
25483
iattr->value = (xmlChar *) iattr->use->defValue;
25484
iattr->val = iattr->use->defVal;
25485
} else {
25486
iattr->value = (xmlChar *) iattr->decl->defValue;
25487
iattr->val = iattr->decl->defVal;
25488
}
25489
/*
25490
* IDCs will consume the precomputed default value,
25491
* so we need to clone it.
25492
*/
25493
if (iattr->val == NULL) {
25494
VERROR_INT("xmlSchemaVAttributesComplex",
25495
"default/fixed value on an attribute use was "
25496
"not precomputed");
25497
goto internal_error;
25498
}
25499
iattr->val = xmlSchemaCopyValue(iattr->val);
25500
if (iattr->val == NULL) {
25501
VERROR_INT("xmlSchemaVAttributesComplex",
25502
"calling xmlSchemaCopyValue()");
25503
goto internal_error;
25504
}
25505
}
25506
/*
25507
* PSVI: Add the default attribute to the current element.
25508
* VAL TODO: Should we use the *normalized* value? This currently
25509
* uses the *initial* value.
25510
*/
25511
25512
if (defAttrOwnerElem) {
25513
xmlChar *normValue;
25514
const xmlChar *value;
25515
25516
value = iattr->value;
25517
/*
25518
* Normalize the value.
25519
*/
25520
normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25521
iattr->value);
25522
if (normValue != NULL)
25523
value = BAD_CAST normValue;
25524
25525
if (iattr->nsName == NULL) {
25526
if (xmlNewProp(defAttrOwnerElem,
25527
iattr->localName, value) == NULL) {
25528
VERROR_INT("xmlSchemaVAttributesComplex",
25529
"calling xmlNewProp()");
25530
if (normValue != NULL)
25531
xmlFree(normValue);
25532
goto internal_error;
25533
}
25534
} else {
25535
xmlNsPtr ns;
25536
25537
ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25538
defAttrOwnerElem, iattr->nsName);
25539
if (ns == NULL) {
25540
xmlChar prefix[12];
25541
int counter = 0;
25542
25543
/*
25544
* Create a namespace declaration on the validation
25545
* root node if no namespace declaration is in scope.
25546
*/
25547
do {
25548
snprintf((char *) prefix, 12, "p%d", counter++);
25549
ns = xmlSearchNs(defAttrOwnerElem->doc,
25550
defAttrOwnerElem, BAD_CAST prefix);
25551
if (counter > 1000) {
25552
VERROR_INT(
25553
"xmlSchemaVAttributesComplex",
25554
"could not compute a ns prefix for a "
25555
"default/fixed attribute");
25556
if (normValue != NULL)
25557
xmlFree(normValue);
25558
goto internal_error;
25559
}
25560
} while (ns != NULL);
25561
ns = xmlNewNs(vctxt->validationRoot,
25562
iattr->nsName, BAD_CAST prefix);
25563
}
25564
/*
25565
* TODO:
25566
* http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25567
* If we have QNames: do we need to ensure there's a
25568
* prefix defined for the QName?
25569
*/
25570
xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25571
}
25572
if (normValue != NULL)
25573
xmlFree(normValue);
25574
}
25575
/*
25576
* Go directly to IDC evaluation.
25577
*/
25578
goto eval_idcs;
25579
}
25580
/*
25581
* Validate the value.
25582
*/
25583
if (vctxt->value != NULL) {
25584
/*
25585
* Free last computed value; just for safety reasons.
25586
*/
25587
xmlSchemaFreeValue(vctxt->value);
25588
vctxt->value = NULL;
25589
}
25590
/*
25591
* Note that the attribute *use* can be unavailable, if
25592
* the attribute was a wild attribute.
25593
*/
25594
if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25595
((iattr->use != NULL) &&
25596
(iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25597
fixed = 1;
25598
else
25599
fixed = 0;
25600
/*
25601
* SPEC (cvc-attribute)
25602
* (3) "The item's `normalized value` must be locally `valid`
25603
* with respect to that {type definition} as per
25604
* String Valid ($3.14.4)."
25605
*
25606
* VAL TODO: Do we already have the
25607
* "normalized attribute value" here?
25608
*/
25609
if (xpathRes || fixed) {
25610
iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25611
/*
25612
* Request a computed value.
25613
*/
25614
res = xmlSchemaVCheckCVCSimpleType(
25615
ACTXT_CAST vctxt,
25616
iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25617
1, 1, 0);
25618
} else {
25619
res = xmlSchemaVCheckCVCSimpleType(
25620
ACTXT_CAST vctxt,
25621
iattr->node, iattr->typeDef, iattr->value, NULL,
25622
1, 0, 0);
25623
}
25624
25625
if (res != 0) {
25626
if (res == -1) {
25627
VERROR_INT("xmlSchemaVAttributesComplex",
25628
"calling xmlSchemaStreamValidateSimpleTypeValue()");
25629
goto internal_error;
25630
}
25631
iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25632
/*
25633
* SPEC PSVI Assessment Outcome (Attribute)
25634
* [validity] = "invalid"
25635
*/
25636
goto eval_idcs;
25637
}
25638
25639
if (fixed) {
25640
/*
25641
* SPEC Attribute Locally Valid (Use) (cvc-au)
25642
* "For an attribute information item to be `valid`
25643
* with respect to an attribute use its *normalized*
25644
* value must match the *canonical* lexical
25645
* representation of the attribute use's {value
25646
* constraint}value, if it is present and fixed."
25647
*
25648
* VAL TODO: The requirement for the *canonical* value
25649
* will be removed in XML Schema 1.1.
25650
*/
25651
/*
25652
* SPEC Attribute Locally Valid (cvc-attribute)
25653
* (4) "The item's *actual* value must match the *value* of
25654
* the {value constraint}, if it is present and fixed."
25655
*/
25656
if (iattr->val == NULL) {
25657
/* VAL TODO: A value was not precomputed. */
25658
TODO
25659
goto eval_idcs;
25660
}
25661
if ((iattr->use != NULL) &&
25662
(iattr->use->defValue != NULL)) {
25663
if (iattr->use->defVal == NULL) {
25664
/* VAL TODO: A default value was not precomputed. */
25665
TODO
25666
goto eval_idcs;
25667
}
25668
iattr->vcValue = iattr->use->defValue;
25669
/*
25670
if (xmlSchemaCompareValuesWhtsp(attr->val,
25671
(xmlSchemaWhitespaceValueType) ws,
25672
attr->use->defVal,
25673
(xmlSchemaWhitespaceValueType) ws) != 0) {
25674
*/
25675
if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25676
iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25677
} else {
25678
if (iattr->decl->defVal == NULL) {
25679
/* VAL TODO: A default value was not precomputed. */
25680
TODO
25681
goto eval_idcs;
25682
}
25683
iattr->vcValue = iattr->decl->defValue;
25684
/*
25685
if (xmlSchemaCompareValuesWhtsp(attr->val,
25686
(xmlSchemaWhitespaceValueType) ws,
25687
attrDecl->defVal,
25688
(xmlSchemaWhitespaceValueType) ws) != 0) {
25689
*/
25690
if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25691
iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25692
}
25693
/*
25694
* [validity] = "valid"
25695
*/
25696
}
25697
eval_idcs:
25698
/*
25699
* Evaluate IDCs.
25700
*/
25701
if (xpathRes) {
25702
if (xmlSchemaXPathProcessHistory(vctxt,
25703
vctxt->depth +1) == -1) {
25704
VERROR_INT("xmlSchemaVAttributesComplex",
25705
"calling xmlSchemaXPathEvaluate()");
25706
goto internal_error;
25707
}
25708
} else if (vctxt->xpathStates != NULL)
25709
xmlSchemaXPathPop(vctxt);
25710
}
25711
25712
/*
25713
* Report errors.
25714
*/
25715
for (i = 0; i < vctxt->nbAttrInfos; i++) {
25716
iattr = vctxt->attrInfos[i];
25717
if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25718
(iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25719
(iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25720
(iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25721
continue;
25722
ACTIVATE_ATTRIBUTE(iattr);
25723
switch (iattr->state) {
25724
case XML_SCHEMAS_ATTR_ERR_MISSING: {
25725
xmlChar *str = NULL;
25726
ACTIVATE_ELEM;
25727
xmlSchemaCustomErr(ACTXT_CAST vctxt,
25728
XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25729
"The attribute '%s' is required but missing",
25730
xmlSchemaFormatQName(&str,
25731
iattr->decl->targetNamespace,
25732
iattr->decl->name),
25733
NULL);
25734
FREE_AND_NULL(str)
25735
break;
25736
}
25737
case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25738
VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25739
"The type definition is absent");
25740
break;
25741
case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25742
xmlSchemaCustomErr(ACTXT_CAST vctxt,
25743
XML_SCHEMAV_CVC_AU, NULL, NULL,
25744
"The value '%s' does not match the fixed "
25745
"value constraint '%s'",
25746
iattr->value, iattr->vcValue);
25747
break;
25748
case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25749
VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25750
"No matching global attribute declaration available, but "
25751
"demanded by the strict wildcard");
25752
break;
25753
case XML_SCHEMAS_ATTR_UNKNOWN:
25754
if (iattr->metaType)
25755
break;
25756
/*
25757
* MAYBE VAL TODO: One might report different error messages
25758
* for the following errors.
25759
*/
25760
if (type->attributeWildcard == NULL) {
25761
xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25762
XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25763
} else {
25764
xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25765
XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25766
}
25767
break;
25768
default:
25769
break;
25770
}
25771
}
25772
25773
ACTIVATE_ELEM;
25774
return (0);
25775
internal_error:
25776
ACTIVATE_ELEM;
25777
return (-1);
25778
}
25779
25780
static int
25781
xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25782
int *skip)
25783
{
25784
xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25785
/*
25786
* The namespace of the element was already identified to be
25787
* matching the wildcard.
25788
*/
25789
if ((skip == NULL) || (wild == NULL) ||
25790
(wild->type != XML_SCHEMA_TYPE_ANY)) {
25791
VERROR_INT("xmlSchemaValidateElemWildcard",
25792
"bad arguments");
25793
return (-1);
25794
}
25795
*skip = 0;
25796
if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25797
/*
25798
* URGENT VAL TODO: Either we need to position the stream to the
25799
* next sibling, or walk the whole subtree.
25800
*/
25801
*skip = 1;
25802
return (0);
25803
}
25804
{
25805
xmlSchemaElementPtr decl = NULL;
25806
25807
decl = xmlSchemaGetElem(vctxt->schema,
25808
vctxt->inode->localName, vctxt->inode->nsName);
25809
if (decl != NULL) {
25810
vctxt->inode->decl = decl;
25811
return (0);
25812
}
25813
}
25814
if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25815
/* VAL TODO: Change to proper error code. */
25816
VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25817
"No matching global element declaration available, but "
25818
"demanded by the strict wildcard");
25819
return (vctxt->err);
25820
}
25821
if (vctxt->nbAttrInfos != 0) {
25822
xmlSchemaAttrInfoPtr iattr;
25823
/*
25824
* SPEC Validation Rule: Schema-Validity Assessment (Element)
25825
* (1.2.1.2.1) - (1.2.1.2.3 )
25826
*
25827
* Use the xsi:type attribute for the type definition.
25828
*/
25829
iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25830
XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25831
if (iattr != NULL) {
25832
if (xmlSchemaProcessXSIType(vctxt, iattr,
25833
&(vctxt->inode->typeDef), NULL) == -1) {
25834
VERROR_INT("xmlSchemaValidateElemWildcard",
25835
"calling xmlSchemaProcessXSIType() to "
25836
"process the attribute 'xsi:nil'");
25837
return (-1);
25838
}
25839
/*
25840
* Don't return an error on purpose.
25841
*/
25842
return (0);
25843
}
25844
}
25845
/*
25846
* SPEC Validation Rule: Schema-Validity Assessment (Element)
25847
*
25848
* Fallback to "anyType".
25849
*/
25850
vctxt->inode->typeDef =
25851
xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25852
return (0);
25853
}
25854
25855
/*
25856
* xmlSchemaCheckCOSValidDefault:
25857
*
25858
* This will be called if: not nilled, no content and a default/fixed
25859
* value is provided.
25860
*/
25861
25862
static int
25863
xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25864
const xmlChar *value,
25865
xmlSchemaValPtr *val)
25866
{
25867
int ret = 0;
25868
xmlSchemaNodeInfoPtr inode = vctxt->inode;
25869
25870
/*
25871
* cos-valid-default:
25872
* Schema Component Constraint: Element Default Valid (Immediate)
25873
* For a string to be a valid default with respect to a type
25874
* definition the appropriate case among the following must be true:
25875
*/
25876
if WXS_IS_COMPLEX(inode->typeDef) {
25877
/*
25878
* Complex type.
25879
*
25880
* SPEC (2.1) "its {content type} must be a simple type definition
25881
* or mixed."
25882
* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25883
* type}'s particle must be `emptiable` as defined by
25884
* Particle Emptiable ($3.9.6)."
25885
*/
25886
if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25887
((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25888
(! WXS_EMPTIABLE(inode->typeDef)))) {
25889
ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25890
/* NOTE that this covers (2.2.2) as well. */
25891
VERROR(ret, NULL,
25892
"For a string to be a valid default, the type definition "
25893
"must be a simple type or a complex type with simple content "
25894
"or mixed content and a particle emptiable");
25895
return(ret);
25896
}
25897
}
25898
/*
25899
* 1 If the type definition is a simple type definition, then the string
25900
* must be `valid` with respect to that definition as defined by String
25901
* Valid ($3.14.4).
25902
*
25903
* AND
25904
*
25905
* 2.2.1 If the {content type} is a simple type definition, then the
25906
* string must be `valid` with respect to that simple type definition
25907
* as defined by String Valid ($3.14.4).
25908
*/
25909
if (WXS_IS_SIMPLE(inode->typeDef)) {
25910
25911
ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25912
NULL, inode->typeDef, value, val, 1, 1, 0);
25913
25914
} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25915
25916
ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25917
NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25918
}
25919
if (ret < 0) {
25920
VERROR_INT("xmlSchemaCheckCOSValidDefault",
25921
"calling xmlSchemaVCheckCVCSimpleType()");
25922
}
25923
return (ret);
25924
}
25925
25926
static void
25927
xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
25928
const xmlChar * name ATTRIBUTE_UNUSED,
25929
void *transdata, void *inputdata)
25930
{
25931
xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
25932
xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
25933
inode->decl = item;
25934
}
25935
25936
static int
25937
xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25938
{
25939
vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25940
if (vctxt->inode == NULL) {
25941
VERROR_INT("xmlSchemaValidatorPushElem",
25942
"calling xmlSchemaGetFreshElemInfo()");
25943
return (-1);
25944
}
25945
vctxt->nbAttrInfos = 0;
25946
return (0);
25947
}
25948
25949
static int
25950
xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25951
xmlSchemaNodeInfoPtr inode,
25952
xmlSchemaTypePtr type,
25953
const xmlChar *value)
25954
{
25955
if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25956
return (xmlSchemaVCheckCVCSimpleType(
25957
ACTXT_CAST vctxt, NULL,
25958
type, value, &(inode->val), 1, 1, 0));
25959
else
25960
return (xmlSchemaVCheckCVCSimpleType(
25961
ACTXT_CAST vctxt, NULL,
25962
type, value, NULL, 1, 0, 0));
25963
}
25964
25965
25966
25967
/*
25968
* Process END of element.
25969
*/
25970
static int
25971
xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25972
{
25973
int ret = 0;
25974
xmlSchemaNodeInfoPtr inode = vctxt->inode;
25975
25976
if (vctxt->nbAttrInfos != 0)
25977
xmlSchemaClearAttrInfos(vctxt);
25978
if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25979
/*
25980
* This element was not expected;
25981
* we will not validate child elements of broken parents.
25982
* Skip validation of all content of the parent.
25983
*/
25984
vctxt->skipDepth = vctxt->depth -1;
25985
goto end_elem;
25986
}
25987
if ((inode->typeDef == NULL) ||
25988
(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25989
/*
25990
* 1. the type definition might be missing if the element was
25991
* error prone
25992
* 2. it might be abstract.
25993
*/
25994
goto end_elem;
25995
}
25996
/*
25997
* Check the content model.
25998
*/
25999
if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26000
(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26001
26002
/*
26003
* Workaround for "anyType".
26004
*/
26005
if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26006
goto character_content;
26007
26008
if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26009
xmlChar *values[10];
26010
int terminal, nbval = 10, nbneg;
26011
26012
if (inode->regexCtxt == NULL) {
26013
/*
26014
* Create the regex context.
26015
*/
26016
inode->regexCtxt =
26017
xmlRegNewExecCtxt(inode->typeDef->contModel,
26018
xmlSchemaVContentModelCallback, vctxt);
26019
if (inode->regexCtxt == NULL) {
26020
VERROR_INT("xmlSchemaValidatorPopElem",
26021
"failed to create a regex context");
26022
goto internal_error;
26023
}
26024
}
26025
26026
/*
26027
* Do not check further content if the node has been nilled
26028
*/
26029
if (INODE_NILLED(inode)) {
26030
ret = 0;
26031
goto skip_nilled;
26032
}
26033
26034
/*
26035
* Get hold of the still expected content, since a further
26036
* call to xmlRegExecPushString() will lose this information.
26037
*/
26038
xmlRegExecNextValues(inode->regexCtxt,
26039
&nbval, &nbneg, &values[0], &terminal);
26040
ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26041
if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26042
/*
26043
* Still missing something.
26044
*/
26045
ret = 1;
26046
inode->flags |=
26047
XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26048
xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26049
XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26050
"Missing child element(s)",
26051
nbval, nbneg, values);
26052
} else {
26053
/*
26054
* Content model is satisfied.
26055
*/
26056
ret = 0;
26057
}
26058
26059
}
26060
}
26061
26062
skip_nilled:
26063
26064
if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26065
goto end_elem;
26066
26067
character_content:
26068
26069
if (vctxt->value != NULL) {
26070
xmlSchemaFreeValue(vctxt->value);
26071
vctxt->value = NULL;
26072
}
26073
/*
26074
* Check character content.
26075
*/
26076
if (inode->decl == NULL) {
26077
/*
26078
* Speedup if no declaration exists.
26079
*/
26080
if (WXS_IS_SIMPLE(inode->typeDef)) {
26081
ret = xmlSchemaVCheckINodeDataType(vctxt,
26082
inode, inode->typeDef, inode->value);
26083
} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26084
ret = xmlSchemaVCheckINodeDataType(vctxt,
26085
inode, inode->typeDef->contentTypeDef,
26086
inode->value);
26087
}
26088
if (ret < 0) {
26089
VERROR_INT("xmlSchemaValidatorPopElem",
26090
"calling xmlSchemaVCheckCVCSimpleType()");
26091
goto internal_error;
26092
}
26093
goto end_elem;
26094
}
26095
/*
26096
* cvc-elt (3.3.4) : 5
26097
* The appropriate case among the following must be true:
26098
*/
26099
/*
26100
* cvc-elt (3.3.4) : 5.1
26101
* If the declaration has a {value constraint},
26102
* the item has neither element nor character [children] and
26103
* clause 3.2 has not applied, then all of the following must be true:
26104
*/
26105
if ((inode->decl->value != NULL) &&
26106
(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26107
(! INODE_NILLED(inode))) {
26108
/*
26109
* cvc-elt (3.3.4) : 5.1.1
26110
* If the `actual type definition` is a `local type definition`
26111
* then the canonical lexical representation of the {value constraint}
26112
* value must be a valid default for the `actual type definition` as
26113
* defined in Element Default Valid (Immediate) ($3.3.6).
26114
*/
26115
/*
26116
* NOTE: 'local' above means types acquired by xsi:type.
26117
* NOTE: Although the *canonical* value is stated, it is not
26118
* relevant if canonical or not. Additionally XML Schema 1.1
26119
* will removed this requirement as well.
26120
*/
26121
if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26122
26123
ret = xmlSchemaCheckCOSValidDefault(vctxt,
26124
inode->decl->value, &(inode->val));
26125
if (ret != 0) {
26126
if (ret < 0) {
26127
VERROR_INT("xmlSchemaValidatorPopElem",
26128
"calling xmlSchemaCheckCOSValidDefault()");
26129
goto internal_error;
26130
}
26131
goto end_elem;
26132
}
26133
/*
26134
* Stop here, to avoid redundant validation of the value
26135
* (see following).
26136
*/
26137
goto default_psvi;
26138
}
26139
/*
26140
* cvc-elt (3.3.4) : 5.1.2
26141
* The element information item with the canonical lexical
26142
* representation of the {value constraint} value used as its
26143
* `normalized value` must be `valid` with respect to the
26144
* `actual type definition` as defined by Element Locally Valid (Type)
26145
* ($3.3.4).
26146
*/
26147
if (WXS_IS_SIMPLE(inode->typeDef)) {
26148
ret = xmlSchemaVCheckINodeDataType(vctxt,
26149
inode, inode->typeDef, inode->decl->value);
26150
} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26151
ret = xmlSchemaVCheckINodeDataType(vctxt,
26152
inode, inode->typeDef->contentTypeDef,
26153
inode->decl->value);
26154
}
26155
if (ret != 0) {
26156
if (ret < 0) {
26157
VERROR_INT("xmlSchemaValidatorPopElem",
26158
"calling xmlSchemaVCheckCVCSimpleType()");
26159
goto internal_error;
26160
}
26161
goto end_elem;
26162
}
26163
26164
default_psvi:
26165
/*
26166
* PSVI: Create a text node on the instance element.
26167
*/
26168
if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26169
(inode->node != NULL)) {
26170
xmlNodePtr textChild;
26171
xmlChar *normValue;
26172
/*
26173
* VAL TODO: Normalize the value.
26174
*/
26175
normValue = xmlSchemaNormalizeValue(inode->typeDef,
26176
inode->decl->value);
26177
if (normValue != NULL) {
26178
textChild = xmlNewDocText(inode->node->doc,
26179
BAD_CAST normValue);
26180
xmlFree(normValue);
26181
} else
26182
textChild = xmlNewDocText(inode->node->doc,
26183
inode->decl->value);
26184
if (textChild == NULL) {
26185
VERROR_INT("xmlSchemaValidatorPopElem",
26186
"calling xmlNewDocText()");
26187
goto internal_error;
26188
} else
26189
xmlAddChild(inode->node, textChild);
26190
}
26191
26192
} else if (! INODE_NILLED(inode)) {
26193
/*
26194
* 5.2.1 The element information item must be `valid` with respect
26195
* to the `actual type definition` as defined by Element Locally
26196
* Valid (Type) ($3.3.4).
26197
*/
26198
if (WXS_IS_SIMPLE(inode->typeDef)) {
26199
/*
26200
* SPEC (cvc-type) (3.1)
26201
* "If the type definition is a simple type definition, ..."
26202
* (3.1.3) "If clause 3.2 of Element Locally Valid
26203
* (Element) ($3.3.4) did not apply, then the `normalized value`
26204
* must be `valid` with respect to the type definition as defined
26205
* by String Valid ($3.14.4).
26206
*/
26207
ret = xmlSchemaVCheckINodeDataType(vctxt,
26208
inode, inode->typeDef, inode->value);
26209
} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26210
/*
26211
* SPEC (cvc-type) (3.2) "If the type definition is a complex type
26212
* definition, then the element information item must be
26213
* `valid` with respect to the type definition as per
26214
* Element Locally Valid (Complex Type) ($3.4.4);"
26215
*
26216
* SPEC (cvc-complex-type) (2.2)
26217
* "If the {content type} is a simple type definition, ...
26218
* the `normalized value` of the element information item is
26219
* `valid` with respect to that simple type definition as
26220
* defined by String Valid ($3.14.4)."
26221
*/
26222
ret = xmlSchemaVCheckINodeDataType(vctxt,
26223
inode, inode->typeDef->contentTypeDef, inode->value);
26224
}
26225
if (ret != 0) {
26226
if (ret < 0) {
26227
VERROR_INT("xmlSchemaValidatorPopElem",
26228
"calling xmlSchemaVCheckCVCSimpleType()");
26229
goto internal_error;
26230
}
26231
goto end_elem;
26232
}
26233
/*
26234
* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26235
* not applied, all of the following must be true:
26236
*/
26237
if ((inode->decl->value != NULL) &&
26238
(inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26239
26240
/*
26241
* TODO: We will need a computed value, when comparison is
26242
* done on computed values.
26243
*/
26244
/*
26245
* 5.2.2.1 The element information item must have no element
26246
* information item [children].
26247
*/
26248
if (inode->flags &
26249
XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26250
ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26251
VERROR(ret, NULL,
26252
"The content must not contain element nodes since "
26253
"there is a fixed value constraint");
26254
goto end_elem;
26255
} else {
26256
/*
26257
* 5.2.2.2 The appropriate case among the following must
26258
* be true:
26259
*/
26260
if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26261
/*
26262
* 5.2.2.2.1 If the {content type} of the `actual type
26263
* definition` is mixed, then the *initial value* of the
26264
* item must match the canonical lexical representation
26265
* of the {value constraint} value.
26266
*
26267
* ... the *initial value* of an element information
26268
* item is the string composed of, in order, the
26269
* [character code] of each character information item in
26270
* the [children] of that element information item.
26271
*/
26272
if (! xmlStrEqual(inode->value, inode->decl->value)){
26273
/*
26274
* VAL TODO: Report invalid & expected values as well.
26275
* VAL TODO: Implement the canonical stuff.
26276
*/
26277
ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26278
xmlSchemaCustomErr(ACTXT_CAST vctxt,
26279
ret, NULL, NULL,
26280
"The initial value '%s' does not match the fixed "
26281
"value constraint '%s'",
26282
inode->value, inode->decl->value);
26283
goto end_elem;
26284
}
26285
} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26286
/*
26287
* 5.2.2.2.2 If the {content type} of the `actual type
26288
* definition` is a simple type definition, then the
26289
* *actual value* of the item must match the canonical
26290
* lexical representation of the {value constraint} value.
26291
*/
26292
/*
26293
* VAL TODO: *actual value* is the normalized value, impl.
26294
* this.
26295
* VAL TODO: Report invalid & expected values as well.
26296
* VAL TODO: Implement a comparison with the computed values.
26297
*/
26298
if (! xmlStrEqual(inode->value,
26299
inode->decl->value)) {
26300
ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26301
xmlSchemaCustomErr(ACTXT_CAST vctxt,
26302
ret, NULL, NULL,
26303
"The actual value '%s' does not match the fixed "
26304
"value constraint '%s'",
26305
inode->value,
26306
inode->decl->value);
26307
goto end_elem;
26308
}
26309
}
26310
}
26311
}
26312
}
26313
26314
end_elem:
26315
if (vctxt->depth < 0) {
26316
/* TODO: raise error? */
26317
return (0);
26318
}
26319
if (vctxt->depth == vctxt->skipDepth)
26320
vctxt->skipDepth = -1;
26321
/*
26322
* Evaluate the history of XPath state objects.
26323
*/
26324
if (inode->appliedXPath &&
26325
(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26326
goto internal_error;
26327
/*
26328
* MAYBE TODO:
26329
* SPEC (6) "The element information item must be `valid` with
26330
* respect to each of the {identity-constraint definitions} as per
26331
* Identity-constraint Satisfied ($3.11.4)."
26332
*/
26333
/*
26334
* PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26335
* need to be built in any case.
26336
* We will currently build IDC node-tables and bubble them only if
26337
* keyrefs do exist.
26338
*/
26339
26340
/*
26341
* Add the current IDC target-nodes to the IDC node-tables.
26342
*/
26343
if ((inode->idcMatchers != NULL) &&
26344
(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26345
{
26346
if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26347
goto internal_error;
26348
}
26349
/*
26350
* Validate IDC keyrefs.
26351
*/
26352
if (vctxt->inode->hasKeyrefs)
26353
if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26354
goto internal_error;
26355
/*
26356
* Merge/free the IDC table.
26357
*/
26358
if (inode->idcTable != NULL) {
26359
if ((vctxt->depth > 0) &&
26360
(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26361
{
26362
/*
26363
* Merge the IDC node table with the table of the parent node.
26364
*/
26365
if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26366
goto internal_error;
26367
}
26368
}
26369
/*
26370
* Clear the current ielem.
26371
* VAL TODO: Don't free the PSVI IDC tables if they are
26372
* requested for the PSVI.
26373
*/
26374
xmlSchemaClearElemInfo(vctxt, inode);
26375
/*
26376
* Skip further processing if we are on the validation root.
26377
*/
26378
if (vctxt->depth == 0) {
26379
vctxt->depth--;
26380
vctxt->inode = NULL;
26381
return (0);
26382
}
26383
/*
26384
* Reset the keyrefDepth if needed.
26385
*/
26386
if (vctxt->aidcs != NULL) {
26387
xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26388
do {
26389
if (aidc->keyrefDepth == vctxt->depth) {
26390
/*
26391
* A 'keyrefDepth' of a key/unique IDC matches the current
26392
* depth, this means that we are leaving the scope of the
26393
* top-most keyref IDC which refers to this IDC.
26394
*/
26395
aidc->keyrefDepth = -1;
26396
}
26397
aidc = aidc->next;
26398
} while (aidc != NULL);
26399
}
26400
vctxt->depth--;
26401
vctxt->inode = vctxt->elemInfos[vctxt->depth];
26402
/*
26403
* VAL TODO: 7 If the element information item is the `validation root`, it must be
26404
* `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26405
*/
26406
return (ret);
26407
26408
internal_error:
26409
vctxt->err = -1;
26410
return (-1);
26411
}
26412
26413
/*
26414
* 3.4.4 Complex Type Definition Validation Rules
26415
* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26416
*/
26417
static int
26418
xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26419
{
26420
xmlSchemaNodeInfoPtr pielem;
26421
xmlSchemaTypePtr ptype;
26422
int ret = 0;
26423
26424
if (vctxt->depth <= 0) {
26425
VERROR_INT("xmlSchemaValidateChildElem",
26426
"not intended for the validation root");
26427
return (-1);
26428
}
26429
pielem = vctxt->elemInfos[vctxt->depth -1];
26430
if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26431
pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26432
/*
26433
* Handle 'nilled' elements.
26434
*/
26435
if (INODE_NILLED(pielem)) {
26436
/*
26437
* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26438
*/
26439
ACTIVATE_PARENT_ELEM;
26440
ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26441
VERROR(ret, NULL,
26442
"Neither character nor element content is allowed, "
26443
"because the element was 'nilled'");
26444
ACTIVATE_ELEM;
26445
goto unexpected_elem;
26446
}
26447
26448
ptype = pielem->typeDef;
26449
26450
if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26451
/*
26452
* Workaround for "anyType": we have currently no content model
26453
* assigned for "anyType", so handle it explicitly.
26454
* "anyType" has an unbounded, lax "any" wildcard.
26455
*/
26456
vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26457
vctxt->inode->localName,
26458
vctxt->inode->nsName);
26459
26460
if (vctxt->inode->decl == NULL) {
26461
xmlSchemaAttrInfoPtr iattr;
26462
/*
26463
* Process "xsi:type".
26464
* SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26465
*/
26466
iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26467
XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26468
if (iattr != NULL) {
26469
ret = xmlSchemaProcessXSIType(vctxt, iattr,
26470
&(vctxt->inode->typeDef), NULL);
26471
if (ret != 0) {
26472
if (ret == -1) {
26473
VERROR_INT("xmlSchemaValidateChildElem",
26474
"calling xmlSchemaProcessXSIType() to "
26475
"process the attribute 'xsi:nil'");
26476
return (-1);
26477
}
26478
return (ret);
26479
}
26480
} else {
26481
/*
26482
* Fallback to "anyType".
26483
*
26484
* SPEC (cvc-assess-elt)
26485
* "If the item cannot be `strictly assessed`, [...]
26486
* an element information item's schema validity may be laxly
26487
* assessed if its `context-determined declaration` is not
26488
* skip by `validating` with respect to the `ur-type
26489
* definition` as per Element Locally Valid (Type) ($3.3.4)."
26490
*/
26491
vctxt->inode->typeDef =
26492
xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26493
}
26494
}
26495
return (0);
26496
}
26497
26498
switch (ptype->contentType) {
26499
case XML_SCHEMA_CONTENT_EMPTY:
26500
/*
26501
* SPEC (2.1) "If the {content type} is empty, then the
26502
* element information item has no character or element
26503
* information item [children]."
26504
*/
26505
ACTIVATE_PARENT_ELEM
26506
ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26507
VERROR(ret, NULL,
26508
"Element content is not allowed, "
26509
"because the content type is empty");
26510
ACTIVATE_ELEM
26511
goto unexpected_elem;
26512
break;
26513
26514
case XML_SCHEMA_CONTENT_MIXED:
26515
case XML_SCHEMA_CONTENT_ELEMENTS: {
26516
xmlRegExecCtxtPtr regexCtxt;
26517
xmlChar *values[10];
26518
int terminal, nbval = 10, nbneg;
26519
26520
/* VAL TODO: Optimized "anyType" validation.*/
26521
26522
if (ptype->contModel == NULL) {
26523
VERROR_INT("xmlSchemaValidateChildElem",
26524
"type has elem content but no content model");
26525
return (-1);
26526
}
26527
/*
26528
* Safety belt for evaluation if the cont. model was already
26529
* examined to be invalid.
26530
*/
26531
if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26532
VERROR_INT("xmlSchemaValidateChildElem",
26533
"validating elem, but elem content is already invalid");
26534
return (-1);
26535
}
26536
26537
regexCtxt = pielem->regexCtxt;
26538
if (regexCtxt == NULL) {
26539
/*
26540
* Create the regex context.
26541
*/
26542
regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26543
xmlSchemaVContentModelCallback, vctxt);
26544
if (regexCtxt == NULL) {
26545
VERROR_INT("xmlSchemaValidateChildElem",
26546
"failed to create a regex context");
26547
return (-1);
26548
}
26549
pielem->regexCtxt = regexCtxt;
26550
}
26551
26552
/*
26553
* SPEC (2.4) "If the {content type} is element-only or mixed,
26554
* then the sequence of the element information item's
26555
* element information item [children], if any, taken in
26556
* order, is `valid` with respect to the {content type}'s
26557
* particle, as defined in Element Sequence Locally Valid
26558
* (Particle) ($3.9.4)."
26559
*/
26560
ret = xmlRegExecPushString2(regexCtxt,
26561
vctxt->inode->localName,
26562
vctxt->inode->nsName,
26563
vctxt->inode);
26564
if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26565
VERROR_INT("xmlSchemaValidateChildElem",
26566
"calling xmlRegExecPushString2()");
26567
return (-1);
26568
}
26569
if (ret < 0) {
26570
xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26571
&values[0], &terminal);
26572
xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26573
XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26574
"This element is not expected",
26575
nbval, nbneg, values);
26576
ret = vctxt->err;
26577
goto unexpected_elem;
26578
} else
26579
ret = 0;
26580
}
26581
break;
26582
case XML_SCHEMA_CONTENT_SIMPLE:
26583
case XML_SCHEMA_CONTENT_BASIC:
26584
ACTIVATE_PARENT_ELEM
26585
if (WXS_IS_COMPLEX(ptype)) {
26586
/*
26587
* SPEC (cvc-complex-type) (2.2)
26588
* "If the {content type} is a simple type definition, then
26589
* the element information item has no element information
26590
* item [children], ..."
26591
*/
26592
ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26593
VERROR(ret, NULL, "Element content is not allowed, "
26594
"because the content type is a simple type definition");
26595
} else {
26596
/*
26597
* SPEC (cvc-type) (3.1.2) "The element information item must
26598
* have no element information item [children]."
26599
*/
26600
ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26601
VERROR(ret, NULL, "Element content is not allowed, "
26602
"because the type definition is simple");
26603
}
26604
ACTIVATE_ELEM
26605
ret = vctxt->err;
26606
goto unexpected_elem;
26607
break;
26608
26609
default:
26610
break;
26611
}
26612
return (ret);
26613
unexpected_elem:
26614
/*
26615
* Pop this element and set the skipDepth to skip
26616
* all further content of the parent element.
26617
*/
26618
vctxt->skipDepth = vctxt->depth;
26619
vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26620
pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26621
return (ret);
26622
}
26623
26624
#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26625
#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26626
#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26627
26628
static int
26629
xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26630
int nodeType, const xmlChar *value, int len,
26631
int mode, int *consumed)
26632
{
26633
/*
26634
* Unfortunately we have to duplicate the text sometimes.
26635
* OPTIMIZE: Maybe we could skip it, if:
26636
* 1. content type is simple
26637
* 2. whitespace is "collapse"
26638
* 3. it consists of whitespace only
26639
*
26640
* Process character content.
26641
*/
26642
if (consumed != NULL)
26643
*consumed = 0;
26644
if (INODE_NILLED(vctxt->inode)) {
26645
/*
26646
* SPEC cvc-elt (3.3.4 - 3.2.1)
26647
* "The element information item must have no character or
26648
* element information item [children]."
26649
*/
26650
VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26651
"Neither character nor element content is allowed "
26652
"because the element is 'nilled'");
26653
return (vctxt->err);
26654
}
26655
/*
26656
* SPEC (2.1) "If the {content type} is empty, then the
26657
* element information item has no character or element
26658
* information item [children]."
26659
*/
26660
if (vctxt->inode->typeDef->contentType ==
26661
XML_SCHEMA_CONTENT_EMPTY) {
26662
VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26663
"Character content is not allowed, "
26664
"because the content type is empty");
26665
return (vctxt->err);
26666
}
26667
26668
if (vctxt->inode->typeDef->contentType ==
26669
XML_SCHEMA_CONTENT_ELEMENTS) {
26670
if ((nodeType != XML_TEXT_NODE) ||
26671
(! xmlSchemaIsBlank((xmlChar *) value, len))) {
26672
/*
26673
* SPEC cvc-complex-type (2.3)
26674
* "If the {content type} is element-only, then the
26675
* element information item has no character information
26676
* item [children] other than those whose [character
26677
* code] is defined as a white space in [XML 1.0 (Second
26678
* Edition)]."
26679
*/
26680
VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26681
"Character content other than whitespace is not allowed "
26682
"because the content type is 'element-only'");
26683
return (vctxt->err);
26684
}
26685
return (0);
26686
}
26687
26688
if ((value == NULL) || (value[0] == 0))
26689
return (0);
26690
/*
26691
* Save the value.
26692
* NOTE that even if the content type is *mixed*, we need the
26693
* *initial value* for default/fixed value constraints.
26694
*/
26695
if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26696
((vctxt->inode->decl == NULL) ||
26697
(vctxt->inode->decl->value == NULL)))
26698
return (0);
26699
26700
if (vctxt->inode->value == NULL) {
26701
/*
26702
* Set the value.
26703
*/
26704
switch (mode) {
26705
case XML_SCHEMA_PUSH_TEXT_PERSIST:
26706
/*
26707
* When working on a tree.
26708
*/
26709
vctxt->inode->value = value;
26710
break;
26711
case XML_SCHEMA_PUSH_TEXT_CREATED:
26712
/*
26713
* When working with the reader.
26714
* The value will be freed by the element info.
26715
*/
26716
vctxt->inode->value = value;
26717
if (consumed != NULL)
26718
*consumed = 1;
26719
vctxt->inode->flags |=
26720
XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26721
break;
26722
case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26723
/*
26724
* When working with SAX.
26725
* The value will be freed by the element info.
26726
*/
26727
if (len != -1)
26728
vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26729
else
26730
vctxt->inode->value = BAD_CAST xmlStrdup(value);
26731
vctxt->inode->flags |=
26732
XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26733
break;
26734
default:
26735
break;
26736
}
26737
} else {
26738
if (len < 0)
26739
len = xmlStrlen(value);
26740
/*
26741
* Concat the value.
26742
*/
26743
if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26744
vctxt->inode->value = BAD_CAST xmlStrncat(
26745
(xmlChar *) vctxt->inode->value, value, len);
26746
} else {
26747
vctxt->inode->value =
26748
BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26749
vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26750
}
26751
}
26752
26753
return (0);
26754
}
26755
26756
static int
26757
xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26758
{
26759
int ret = 0;
26760
26761
if ((vctxt->skipDepth != -1) &&
26762
(vctxt->depth >= vctxt->skipDepth)) {
26763
VERROR_INT("xmlSchemaValidateElem",
26764
"in skip-state");
26765
goto internal_error;
26766
}
26767
if (vctxt->xsiAssemble) {
26768
/*
26769
* We will stop validation if there was an error during
26770
* dynamic schema construction.
26771
* Note that we simply set @skipDepth to 0, this could
26772
* mean that a streaming document via SAX would be
26773
* still read to the end but it won't be validated any more.
26774
* TODO: If we are sure how to stop the validation at once
26775
* for all input scenarios, then this should be changed to
26776
* instantly stop the validation.
26777
*/
26778
ret = xmlSchemaAssembleByXSI(vctxt);
26779
if (ret != 0) {
26780
if (ret == -1)
26781
goto internal_error;
26782
vctxt->skipDepth = 0;
26783
return(ret);
26784
}
26785
/*
26786
* Augment the IDC definitions for the main schema and all imported ones
26787
* NOTE: main schema is the first in the imported list
26788
*/
26789
xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
26790
vctxt);
26791
}
26792
if (vctxt->depth > 0) {
26793
/*
26794
* Validate this element against the content model
26795
* of the parent.
26796
*/
26797
ret = xmlSchemaValidateChildElem(vctxt);
26798
if (ret != 0) {
26799
if (ret < 0) {
26800
VERROR_INT("xmlSchemaValidateElem",
26801
"calling xmlSchemaStreamValidateChildElement()");
26802
goto internal_error;
26803
}
26804
goto exit;
26805
}
26806
if (vctxt->depth == vctxt->skipDepth)
26807
goto exit;
26808
if ((vctxt->inode->decl == NULL) &&
26809
(vctxt->inode->typeDef == NULL)) {
26810
VERROR_INT("xmlSchemaValidateElem",
26811
"the child element was valid but neither the "
26812
"declaration nor the type was set");
26813
goto internal_error;
26814
}
26815
} else {
26816
/*
26817
* Get the declaration of the validation root.
26818
*/
26819
vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26820
vctxt->inode->localName,
26821
vctxt->inode->nsName);
26822
if (vctxt->inode->decl == NULL) {
26823
ret = XML_SCHEMAV_CVC_ELT_1;
26824
VERROR(ret, NULL,
26825
"No matching global declaration available "
26826
"for the validation root");
26827
goto exit;
26828
}
26829
}
26830
26831
if (vctxt->inode->decl == NULL)
26832
goto type_validation;
26833
26834
if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26835
int skip;
26836
/*
26837
* Wildcards.
26838
*/
26839
ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26840
if (ret != 0) {
26841
if (ret < 0) {
26842
VERROR_INT("xmlSchemaValidateElem",
26843
"calling xmlSchemaValidateElemWildcard()");
26844
goto internal_error;
26845
}
26846
goto exit;
26847
}
26848
if (skip) {
26849
vctxt->skipDepth = vctxt->depth;
26850
goto exit;
26851
}
26852
/*
26853
* The declaration might be set by the wildcard validation,
26854
* when the processContents is "lax" or "strict".
26855
*/
26856
if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26857
/*
26858
* Clear the "decl" field to not confuse further processing.
26859
*/
26860
vctxt->inode->decl = NULL;
26861
goto type_validation;
26862
}
26863
}
26864
/*
26865
* Validate against the declaration.
26866
*/
26867
ret = xmlSchemaValidateElemDecl(vctxt);
26868
if (ret != 0) {
26869
if (ret < 0) {
26870
VERROR_INT("xmlSchemaValidateElem",
26871
"calling xmlSchemaValidateElemDecl()");
26872
goto internal_error;
26873
}
26874
goto exit;
26875
}
26876
/*
26877
* Validate against the type definition.
26878
*/
26879
type_validation:
26880
26881
if (vctxt->inode->typeDef == NULL) {
26882
vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26883
ret = XML_SCHEMAV_CVC_TYPE_1;
26884
VERROR(ret, NULL,
26885
"The type definition is absent");
26886
goto exit;
26887
}
26888
if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26889
vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26890
ret = XML_SCHEMAV_CVC_TYPE_2;
26891
VERROR(ret, NULL,
26892
"The type definition is abstract");
26893
goto exit;
26894
}
26895
/*
26896
* Evaluate IDCs. Do it here, since new IDC matchers are registered
26897
* during validation against the declaration. This must be done
26898
* _before_ attribute validation.
26899
*/
26900
if (vctxt->xpathStates != NULL) {
26901
ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26902
vctxt->inode->appliedXPath = 1;
26903
if (ret == -1) {
26904
VERROR_INT("xmlSchemaValidateElem",
26905
"calling xmlSchemaXPathEvaluate()");
26906
goto internal_error;
26907
}
26908
}
26909
/*
26910
* Validate attributes.
26911
*/
26912
if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26913
if ((vctxt->nbAttrInfos != 0) ||
26914
(vctxt->inode->typeDef->attrUses != NULL)) {
26915
26916
ret = xmlSchemaVAttributesComplex(vctxt);
26917
}
26918
} else if (vctxt->nbAttrInfos != 0) {
26919
26920
ret = xmlSchemaVAttributesSimple(vctxt);
26921
}
26922
/*
26923
* Clear registered attributes.
26924
*/
26925
if (vctxt->nbAttrInfos != 0)
26926
xmlSchemaClearAttrInfos(vctxt);
26927
if (ret == -1) {
26928
VERROR_INT("xmlSchemaValidateElem",
26929
"calling attributes validation");
26930
goto internal_error;
26931
}
26932
/*
26933
* Don't return an error if attributes are invalid on purpose.
26934
*/
26935
ret = 0;
26936
26937
exit:
26938
if (ret != 0)
26939
vctxt->skipDepth = vctxt->depth;
26940
return (ret);
26941
internal_error:
26942
return (-1);
26943
}
26944
26945
#ifdef XML_SCHEMA_READER_ENABLED
26946
static int
26947
xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26948
{
26949
const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26950
int depth, nodeType, ret = 0, consumed;
26951
xmlSchemaNodeInfoPtr ielem;
26952
26953
vctxt->depth = -1;
26954
ret = xmlTextReaderRead(vctxt->reader);
26955
/*
26956
* Move to the document element.
26957
*/
26958
while (ret == 1) {
26959
nodeType = xmlTextReaderNodeType(vctxt->reader);
26960
if (nodeType == XML_ELEMENT_NODE)
26961
goto root_found;
26962
ret = xmlTextReaderRead(vctxt->reader);
26963
}
26964
goto exit;
26965
26966
root_found:
26967
26968
do {
26969
depth = xmlTextReaderDepth(vctxt->reader);
26970
nodeType = xmlTextReaderNodeType(vctxt->reader);
26971
26972
if (nodeType == XML_ELEMENT_NODE) {
26973
26974
vctxt->depth++;
26975
if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26976
VERROR_INT("xmlSchemaVReaderWalk",
26977
"calling xmlSchemaValidatorPushElem()");
26978
goto internal_error;
26979
}
26980
ielem = vctxt->inode;
26981
ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26982
ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26983
ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26984
/*
26985
* Is the element empty?
26986
*/
26987
ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26988
if (ret == -1) {
26989
VERROR_INT("xmlSchemaVReaderWalk",
26990
"calling xmlTextReaderIsEmptyElement()");
26991
goto internal_error;
26992
}
26993
if (ret) {
26994
ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26995
}
26996
/*
26997
* Register attributes.
26998
*/
26999
vctxt->nbAttrInfos = 0;
27000
ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27001
if (ret == -1) {
27002
VERROR_INT("xmlSchemaVReaderWalk",
27003
"calling xmlTextReaderMoveToFirstAttribute()");
27004
goto internal_error;
27005
}
27006
if (ret == 1) {
27007
do {
27008
/*
27009
* VAL TODO: How do we know that the reader works on a
27010
* node tree, to be able to pass a node here?
27011
*/
27012
if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27013
(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27014
xmlTextReaderNamespaceUri(vctxt->reader), 1,
27015
xmlTextReaderValue(vctxt->reader), 1) == -1) {
27016
27017
VERROR_INT("xmlSchemaVReaderWalk",
27018
"calling xmlSchemaValidatorPushAttribute()");
27019
goto internal_error;
27020
}
27021
ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27022
if (ret == -1) {
27023
VERROR_INT("xmlSchemaVReaderWalk",
27024
"calling xmlTextReaderMoveToFirstAttribute()");
27025
goto internal_error;
27026
}
27027
} while (ret == 1);
27028
/*
27029
* Back to element position.
27030
*/
27031
ret = xmlTextReaderMoveToElement(vctxt->reader);
27032
if (ret == -1) {
27033
VERROR_INT("xmlSchemaVReaderWalk",
27034
"calling xmlTextReaderMoveToElement()");
27035
goto internal_error;
27036
}
27037
}
27038
/*
27039
* Validate the element.
27040
*/
27041
ret= xmlSchemaValidateElem(vctxt);
27042
if (ret != 0) {
27043
if (ret == -1) {
27044
VERROR_INT("xmlSchemaVReaderWalk",
27045
"calling xmlSchemaValidateElem()");
27046
goto internal_error;
27047
}
27048
goto exit;
27049
}
27050
if (vctxt->depth == vctxt->skipDepth) {
27051
int curDepth;
27052
/*
27053
* Skip all content.
27054
*/
27055
if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27056
ret = xmlTextReaderRead(vctxt->reader);
27057
curDepth = xmlTextReaderDepth(vctxt->reader);
27058
while ((ret == 1) && (curDepth != depth)) {
27059
ret = xmlTextReaderRead(vctxt->reader);
27060
curDepth = xmlTextReaderDepth(vctxt->reader);
27061
}
27062
if (ret < 0) {
27063
/*
27064
* VAL TODO: A reader error occurred; what to do here?
27065
*/
27066
ret = 1;
27067
goto exit;
27068
}
27069
}
27070
goto leave_elem;
27071
}
27072
/*
27073
* READER VAL TODO: Is an END_ELEM really never called
27074
* if the elem is empty?
27075
*/
27076
if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27077
goto leave_elem;
27078
} else if (nodeType == END_ELEM) {
27079
/*
27080
* Process END of element.
27081
*/
27082
leave_elem:
27083
ret = xmlSchemaValidatorPopElem(vctxt);
27084
if (ret != 0) {
27085
if (ret < 0) {
27086
VERROR_INT("xmlSchemaVReaderWalk",
27087
"calling xmlSchemaValidatorPopElem()");
27088
goto internal_error;
27089
}
27090
goto exit;
27091
}
27092
if (vctxt->depth >= 0)
27093
ielem = vctxt->inode;
27094
else
27095
ielem = NULL;
27096
} else if ((nodeType == XML_TEXT_NODE) ||
27097
(nodeType == XML_CDATA_SECTION_NODE) ||
27098
(nodeType == WHTSP) ||
27099
(nodeType == SIGN_WHTSP)) {
27100
/*
27101
* Process character content.
27102
*/
27103
xmlChar *value;
27104
27105
if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27106
nodeType = XML_TEXT_NODE;
27107
27108
value = xmlTextReaderValue(vctxt->reader);
27109
ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27110
-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27111
if (! consumed)
27112
xmlFree(value);
27113
if (ret == -1) {
27114
VERROR_INT("xmlSchemaVReaderWalk",
27115
"calling xmlSchemaVPushText()");
27116
goto internal_error;
27117
}
27118
} else if ((nodeType == XML_ENTITY_NODE) ||
27119
(nodeType == XML_ENTITY_REF_NODE)) {
27120
/*
27121
* VAL TODO: What to do with entities?
27122
*/
27123
TODO
27124
}
27125
/*
27126
* Read next node.
27127
*/
27128
ret = xmlTextReaderRead(vctxt->reader);
27129
} while (ret == 1);
27130
27131
exit:
27132
return (ret);
27133
internal_error:
27134
return (-1);
27135
}
27136
#endif
27137
27138
/************************************************************************
27139
* *
27140
* SAX validation handlers *
27141
* *
27142
************************************************************************/
27143
27144
/*
27145
* Process text content.
27146
*/
27147
static void
27148
xmlSchemaSAXHandleText(void *ctx,
27149
const xmlChar * ch,
27150
int len)
27151
{
27152
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27153
27154
if (vctxt->depth < 0)
27155
return;
27156
if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27157
return;
27158
if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27159
vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27160
if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27161
XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27162
VERROR_INT("xmlSchemaSAXHandleCDataSection",
27163
"calling xmlSchemaVPushText()");
27164
vctxt->err = -1;
27165
xmlStopParser(vctxt->parserCtxt);
27166
}
27167
}
27168
27169
/*
27170
* Process CDATA content.
27171
*/
27172
static void
27173
xmlSchemaSAXHandleCDataSection(void *ctx,
27174
const xmlChar * ch,
27175
int len)
27176
{
27177
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27178
27179
if (vctxt->depth < 0)
27180
return;
27181
if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27182
return;
27183
if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27184
vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27185
if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27186
XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27187
VERROR_INT("xmlSchemaSAXHandleCDataSection",
27188
"calling xmlSchemaVPushText()");
27189
vctxt->err = -1;
27190
xmlStopParser(vctxt->parserCtxt);
27191
}
27192
}
27193
27194
static void
27195
xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27196
const xmlChar * name ATTRIBUTE_UNUSED)
27197
{
27198
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27199
27200
if (vctxt->depth < 0)
27201
return;
27202
if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27203
return;
27204
/* SAX VAL TODO: What to do here? */
27205
TODO
27206
}
27207
27208
static void
27209
xmlSchemaSAXHandleStartElementNs(void *ctx,
27210
const xmlChar * localname,
27211
const xmlChar * prefix ATTRIBUTE_UNUSED,
27212
const xmlChar * URI,
27213
int nb_namespaces,
27214
const xmlChar ** namespaces,
27215
int nb_attributes,
27216
int nb_defaulted ATTRIBUTE_UNUSED,
27217
const xmlChar ** attributes)
27218
{
27219
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27220
int ret;
27221
xmlSchemaNodeInfoPtr ielem;
27222
int i, j;
27223
27224
/*
27225
* SAX VAL TODO: What to do with nb_defaulted?
27226
*/
27227
/*
27228
* Skip elements if inside a "skip" wildcard or invalid.
27229
*/
27230
vctxt->depth++;
27231
if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27232
return;
27233
/*
27234
* Push the element.
27235
*/
27236
if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27237
VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27238
"calling xmlSchemaValidatorPushElem()");
27239
goto internal_error;
27240
}
27241
ielem = vctxt->inode;
27242
/*
27243
* TODO: Is this OK?
27244
*/
27245
ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27246
ielem->localName = localname;
27247
ielem->nsName = URI;
27248
ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27249
/*
27250
* Register namespaces on the elem info.
27251
*/
27252
if (nb_namespaces != 0) {
27253
/*
27254
* Although the parser builds its own namespace list,
27255
* we have no access to it, so we'll use an own one.
27256
*/
27257
for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27258
/*
27259
* Store prefix and namespace name.
27260
*/
27261
if (ielem->nsBindings == NULL) {
27262
ielem->nsBindings =
27263
(const xmlChar **) xmlMalloc(10 *
27264
sizeof(const xmlChar *));
27265
if (ielem->nsBindings == NULL) {
27266
xmlSchemaVErrMemory(vctxt,
27267
"allocating namespace bindings for SAX validation",
27268
NULL);
27269
goto internal_error;
27270
}
27271
ielem->nbNsBindings = 0;
27272
ielem->sizeNsBindings = 5;
27273
} else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27274
ielem->sizeNsBindings *= 2;
27275
ielem->nsBindings =
27276
(const xmlChar **) xmlRealloc(
27277
(void *) ielem->nsBindings,
27278
ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27279
if (ielem->nsBindings == NULL) {
27280
xmlSchemaVErrMemory(vctxt,
27281
"re-allocating namespace bindings for SAX validation",
27282
NULL);
27283
goto internal_error;
27284
}
27285
}
27286
27287
ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27288
if (namespaces[j+1][0] == 0) {
27289
/*
27290
* Handle xmlns="".
27291
*/
27292
ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27293
} else
27294
ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27295
namespaces[j+1];
27296
ielem->nbNsBindings++;
27297
}
27298
}
27299
/*
27300
* Register attributes.
27301
* SAX VAL TODO: We are not adding namespace declaration
27302
* attributes yet.
27303
*/
27304
if (nb_attributes != 0) {
27305
int valueLen, k, l;
27306
xmlChar *value;
27307
27308
for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27309
/*
27310
* Duplicate the value, changing any &#38; to a literal ampersand.
27311
*
27312
* libxml2 differs from normal SAX here in that it escapes all ampersands
27313
* as &#38; instead of delivering the raw converted string. Changing the
27314
* behavior at this point would break applications that use this API, so
27315
* we are forced to work around it.
27316
*/
27317
valueLen = attributes[j+4] - attributes[j+3];
27318
value = xmlMallocAtomic(valueLen + 1);
27319
if (value == NULL) {
27320
xmlSchemaVErrMemory(vctxt,
27321
"allocating string for decoded attribute",
27322
NULL);
27323
goto internal_error;
27324
}
27325
for (k = 0, l = 0; k < valueLen; l++) {
27326
if (k < valueLen - 4 &&
27327
attributes[j+3][k+0] == '&' &&
27328
attributes[j+3][k+1] == '#' &&
27329
attributes[j+3][k+2] == '3' &&
27330
attributes[j+3][k+3] == '8' &&
27331
attributes[j+3][k+4] == ';') {
27332
value[l] = '&';
27333
k += 5;
27334
} else {
27335
value[l] = attributes[j+3][k];
27336
k++;
27337
}
27338
}
27339
value[l] = '\0';
27340
/*
27341
* TODO: Set the node line.
27342
*/
27343
ret = xmlSchemaValidatorPushAttribute(vctxt,
27344
NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27345
value, 1);
27346
if (ret == -1) {
27347
VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27348
"calling xmlSchemaValidatorPushAttribute()");
27349
goto internal_error;
27350
}
27351
}
27352
}
27353
/*
27354
* Validate the element.
27355
*/
27356
ret = xmlSchemaValidateElem(vctxt);
27357
if (ret != 0) {
27358
if (ret == -1) {
27359
VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27360
"calling xmlSchemaValidateElem()");
27361
goto internal_error;
27362
}
27363
goto exit;
27364
}
27365
27366
exit:
27367
return;
27368
internal_error:
27369
vctxt->err = -1;
27370
xmlStopParser(vctxt->parserCtxt);
27371
return;
27372
}
27373
27374
static void
27375
xmlSchemaSAXHandleEndElementNs(void *ctx,
27376
const xmlChar * localname ATTRIBUTE_UNUSED,
27377
const xmlChar * prefix ATTRIBUTE_UNUSED,
27378
const xmlChar * URI ATTRIBUTE_UNUSED)
27379
{
27380
xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27381
int res;
27382
27383
/*
27384
* Skip elements if inside a "skip" wildcard or if invalid.
27385
*/
27386
if (vctxt->skipDepth != -1) {
27387
if (vctxt->depth > vctxt->skipDepth) {
27388
vctxt->depth--;
27389
return;
27390
} else
27391
vctxt->skipDepth = -1;
27392
}
27393
/*
27394
* SAX VAL TODO: Just a temporary check.
27395
*/
27396
if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27397
(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27398
VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27399
"elem pop mismatch");
27400
}
27401
res = xmlSchemaValidatorPopElem(vctxt);
27402
if (res != 0) {
27403
if (res < 0) {
27404
VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27405
"calling xmlSchemaValidatorPopElem()");
27406
goto internal_error;
27407
}
27408
goto exit;
27409
}
27410
exit:
27411
return;
27412
internal_error:
27413
vctxt->err = -1;
27414
xmlStopParser(vctxt->parserCtxt);
27415
return;
27416
}
27417
27418
/************************************************************************
27419
* *
27420
* Validation interfaces *
27421
* *
27422
************************************************************************/
27423
27424
/**
27425
* xmlSchemaNewValidCtxt:
27426
* @schema: a precompiled XML Schemas
27427
*
27428
* Create an XML Schemas validation context based on the given schema.
27429
*
27430
* Returns the validation context or NULL in case of error
27431
*/
27432
xmlSchemaValidCtxtPtr
27433
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27434
{
27435
xmlSchemaValidCtxtPtr ret;
27436
27437
ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27438
if (ret == NULL) {
27439
xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27440
return (NULL);
27441
}
27442
memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27443
ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27444
ret->dict = xmlDictCreate();
27445
ret->nodeQNames = xmlSchemaItemListCreate();
27446
ret->schema = schema;
27447
return (ret);
27448
}
27449
27450
/**
27451
* xmlSchemaValidateSetFilename:
27452
* @vctxt: the schema validation context
27453
* @filename: the file name
27454
*
27455
* Workaround to provide file error reporting information when this is
27456
* not provided by current APIs
27457
*/
27458
void
27459
xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27460
if (vctxt == NULL)
27461
return;
27462
if (vctxt->filename != NULL)
27463
xmlFree(vctxt->filename);
27464
if (filename != NULL)
27465
vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27466
else
27467
vctxt->filename = NULL;
27468
}
27469
27470
/**
27471
* xmlSchemaClearValidCtxt:
27472
* @vctxt: the schema validation context
27473
*
27474
* Free the resources associated to the schema validation context;
27475
* leaves some fields alive intended for reuse of the context.
27476
*/
27477
static void
27478
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27479
{
27480
if (vctxt == NULL)
27481
return;
27482
27483
/*
27484
* TODO: Should we clear the flags?
27485
* Might be problematic if one reuses the context
27486
* and assumes that the options remain the same.
27487
*/
27488
vctxt->flags = 0;
27489
vctxt->validationRoot = NULL;
27490
vctxt->doc = NULL;
27491
#ifdef LIBXML_READER_ENABLED
27492
vctxt->reader = NULL;
27493
#endif
27494
vctxt->hasKeyrefs = 0;
27495
27496
if (vctxt->value != NULL) {
27497
xmlSchemaFreeValue(vctxt->value);
27498
vctxt->value = NULL;
27499
}
27500
/*
27501
* Augmented IDC information.
27502
*/
27503
if (vctxt->aidcs != NULL) {
27504
xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27505
do {
27506
next = cur->next;
27507
xmlFree(cur);
27508
cur = next;
27509
} while (cur != NULL);
27510
vctxt->aidcs = NULL;
27511
}
27512
27513
if (vctxt->idcNodes != NULL) {
27514
int i;
27515
xmlSchemaPSVIIDCNodePtr item;
27516
27517
for (i = 0; i < vctxt->nbIdcNodes; i++) {
27518
item = vctxt->idcNodes[i];
27519
xmlFree(item->keys);
27520
xmlFree(item);
27521
}
27522
xmlFree(vctxt->idcNodes);
27523
vctxt->idcNodes = NULL;
27524
vctxt->nbIdcNodes = 0;
27525
vctxt->sizeIdcNodes = 0;
27526
}
27527
27528
if (vctxt->idcKeys != NULL) {
27529
int i;
27530
for (i = 0; i < vctxt->nbIdcKeys; i++)
27531
xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27532
xmlFree(vctxt->idcKeys);
27533
vctxt->idcKeys = NULL;
27534
vctxt->nbIdcKeys = 0;
27535
vctxt->sizeIdcKeys = 0;
27536
}
27537
27538
/*
27539
* Note that we won't delete the XPath state pool here.
27540
*/
27541
if (vctxt->xpathStates != NULL) {
27542
xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27543
vctxt->xpathStates = NULL;
27544
}
27545
/*
27546
* Attribute info.
27547
*/
27548
if (vctxt->nbAttrInfos != 0) {
27549
xmlSchemaClearAttrInfos(vctxt);
27550
}
27551
/*
27552
* Element info.
27553
*/
27554
if (vctxt->elemInfos != NULL) {
27555
int i;
27556
xmlSchemaNodeInfoPtr ei;
27557
27558
for (i = 0; i < vctxt->sizeElemInfos; i++) {
27559
ei = vctxt->elemInfos[i];
27560
if (ei == NULL)
27561
break;
27562
xmlSchemaClearElemInfo(vctxt, ei);
27563
}
27564
}
27565
xmlSchemaItemListClear(vctxt->nodeQNames);
27566
/* Recreate the dict. */
27567
xmlDictFree(vctxt->dict);
27568
/*
27569
* TODO: Is is save to recreate it? Do we have a scenario
27570
* where the user provides the dict?
27571
*/
27572
vctxt->dict = xmlDictCreate();
27573
27574
if (vctxt->filename != NULL) {
27575
xmlFree(vctxt->filename);
27576
vctxt->filename = NULL;
27577
}
27578
27579
/*
27580
* Note that some cleanup functions can move items to the cache,
27581
* so the cache shouldn't be freed too early.
27582
*/
27583
if (vctxt->idcMatcherCache != NULL) {
27584
xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27585
27586
while (matcher) {
27587
tmp = matcher;
27588
matcher = matcher->nextCached;
27589
xmlSchemaIDCFreeMatcherList(tmp);
27590
}
27591
vctxt->idcMatcherCache = NULL;
27592
}
27593
}
27594
27595
/**
27596
* xmlSchemaFreeValidCtxt:
27597
* @ctxt: the schema validation context
27598
*
27599
* Free the resources associated to the schema validation context
27600
*/
27601
void
27602
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27603
{
27604
if (ctxt == NULL)
27605
return;
27606
if (ctxt->value != NULL)
27607
xmlSchemaFreeValue(ctxt->value);
27608
if (ctxt->pctxt != NULL)
27609
xmlSchemaFreeParserCtxt(ctxt->pctxt);
27610
if (ctxt->idcNodes != NULL) {
27611
int i;
27612
xmlSchemaPSVIIDCNodePtr item;
27613
27614
for (i = 0; i < ctxt->nbIdcNodes; i++) {
27615
item = ctxt->idcNodes[i];
27616
xmlFree(item->keys);
27617
xmlFree(item);
27618
}
27619
xmlFree(ctxt->idcNodes);
27620
}
27621
if (ctxt->idcKeys != NULL) {
27622
int i;
27623
for (i = 0; i < ctxt->nbIdcKeys; i++)
27624
xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27625
xmlFree(ctxt->idcKeys);
27626
}
27627
27628
if (ctxt->xpathStates != NULL) {
27629
xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27630
ctxt->xpathStates = NULL;
27631
}
27632
if (ctxt->xpathStatePool != NULL) {
27633
xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27634
ctxt->xpathStatePool = NULL;
27635
}
27636
27637
/*
27638
* Augmented IDC information.
27639
*/
27640
if (ctxt->aidcs != NULL) {
27641
xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27642
do {
27643
next = cur->next;
27644
xmlFree(cur);
27645
cur = next;
27646
} while (cur != NULL);
27647
}
27648
if (ctxt->attrInfos != NULL) {
27649
int i;
27650
xmlSchemaAttrInfoPtr attr;
27651
27652
/* Just a paranoid call to the cleanup. */
27653
if (ctxt->nbAttrInfos != 0)
27654
xmlSchemaClearAttrInfos(ctxt);
27655
for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27656
attr = ctxt->attrInfos[i];
27657
xmlFree(attr);
27658
}
27659
xmlFree(ctxt->attrInfos);
27660
}
27661
if (ctxt->elemInfos != NULL) {
27662
int i;
27663
xmlSchemaNodeInfoPtr ei;
27664
27665
for (i = 0; i < ctxt->sizeElemInfos; i++) {
27666
ei = ctxt->elemInfos[i];
27667
if (ei == NULL)
27668
break;
27669
xmlSchemaClearElemInfo(ctxt, ei);
27670
xmlFree(ei);
27671
}
27672
xmlFree(ctxt->elemInfos);
27673
}
27674
if (ctxt->nodeQNames != NULL)
27675
xmlSchemaItemListFree(ctxt->nodeQNames);
27676
if (ctxt->dict != NULL)
27677
xmlDictFree(ctxt->dict);
27678
if (ctxt->filename != NULL)
27679
xmlFree(ctxt->filename);
27680
xmlFree(ctxt);
27681
}
27682
27683
/**
27684
* xmlSchemaIsValid:
27685
* @ctxt: the schema validation context
27686
*
27687
* Check if any error was detected during validation.
27688
*
27689
* Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27690
* of internal error.
27691
*/
27692
int
27693
xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27694
{
27695
if (ctxt == NULL)
27696
return(-1);
27697
return(ctxt->err == 0);
27698
}
27699
27700
/**
27701
* xmlSchemaSetValidErrors:
27702
* @ctxt: a schema validation context
27703
* @err: the error function
27704
* @warn: the warning function
27705
* @ctx: the functions context
27706
*
27707
* Set the error and warning callback information
27708
*/
27709
void
27710
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27711
xmlSchemaValidityErrorFunc err,
27712
xmlSchemaValidityWarningFunc warn, void *ctx)
27713
{
27714
if (ctxt == NULL)
27715
return;
27716
ctxt->error = err;
27717
ctxt->warning = warn;
27718
ctxt->errCtxt = ctx;
27719
if (ctxt->pctxt != NULL)
27720
xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27721
}
27722
27723
/**
27724
* xmlSchemaSetValidStructuredErrors:
27725
* @ctxt: a schema validation context
27726
* @serror: the structured error function
27727
* @ctx: the functions context
27728
*
27729
* Set the structured error callback
27730
*/
27731
void
27732
xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27733
xmlStructuredErrorFunc serror, void *ctx)
27734
{
27735
if (ctxt == NULL)
27736
return;
27737
ctxt->serror = serror;
27738
ctxt->error = NULL;
27739
ctxt->warning = NULL;
27740
ctxt->errCtxt = ctx;
27741
if (ctxt->pctxt != NULL)
27742
xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27743
}
27744
27745
/**
27746
* xmlSchemaGetValidErrors:
27747
* @ctxt: a XML-Schema validation context
27748
* @err: the error function result
27749
* @warn: the warning function result
27750
* @ctx: the functions context result
27751
*
27752
* Get the error and warning callback information
27753
*
27754
* Returns -1 in case of error and 0 otherwise
27755
*/
27756
int
27757
xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27758
xmlSchemaValidityErrorFunc * err,
27759
xmlSchemaValidityWarningFunc * warn, void **ctx)
27760
{
27761
if (ctxt == NULL)
27762
return (-1);
27763
if (err != NULL)
27764
*err = ctxt->error;
27765
if (warn != NULL)
27766
*warn = ctxt->warning;
27767
if (ctx != NULL)
27768
*ctx = ctxt->errCtxt;
27769
return (0);
27770
}
27771
27772
27773
/**
27774
* xmlSchemaSetValidOptions:
27775
* @ctxt: a schema validation context
27776
* @options: a combination of xmlSchemaValidOption
27777
*
27778
* Sets the options to be used during the validation.
27779
*
27780
* Returns 0 in case of success, -1 in case of an
27781
* API error.
27782
*/
27783
int
27784
xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27785
int options)
27786
27787
{
27788
int i;
27789
27790
if (ctxt == NULL)
27791
return (-1);
27792
/*
27793
* WARNING: Change the start value if adding to the
27794
* xmlSchemaValidOption.
27795
* TODO: Is there an other, more easy to maintain,
27796
* way?
27797
*/
27798
for (i = 1; i < (int) sizeof(int) * 8; i++) {
27799
if (options & 1<<i)
27800
return (-1);
27801
}
27802
ctxt->options = options;
27803
return (0);
27804
}
27805
27806
/**
27807
* xmlSchemaValidCtxtGetOptions:
27808
* @ctxt: a schema validation context
27809
*
27810
* Get the validation context options.
27811
*
27812
* Returns the option combination or -1 on error.
27813
*/
27814
int
27815
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27816
27817
{
27818
if (ctxt == NULL)
27819
return (-1);
27820
else
27821
return (ctxt->options);
27822
}
27823
27824
static int
27825
xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27826
{
27827
xmlAttrPtr attr;
27828
int ret = 0;
27829
xmlSchemaNodeInfoPtr ielem = NULL;
27830
xmlNodePtr node, valRoot;
27831
const xmlChar *nsName;
27832
27833
/* DOC VAL TODO: Move this to the start function. */
27834
if (vctxt->validationRoot != NULL)
27835
valRoot = vctxt->validationRoot;
27836
else
27837
valRoot = xmlDocGetRootElement(vctxt->doc);
27838
if (valRoot == NULL) {
27839
/* VAL TODO: Error code? */
27840
VERROR(1, NULL, "The document has no document element");
27841
return (1);
27842
}
27843
vctxt->depth = -1;
27844
vctxt->validationRoot = valRoot;
27845
node = valRoot;
27846
while (node != NULL) {
27847
if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27848
goto next_sibling;
27849
if (node->type == XML_ELEMENT_NODE) {
27850
27851
/*
27852
* Init the node-info.
27853
*/
27854
vctxt->depth++;
27855
if (xmlSchemaValidatorPushElem(vctxt) == -1)
27856
goto internal_error;
27857
ielem = vctxt->inode;
27858
ielem->node = node;
27859
ielem->nodeLine = node->line;
27860
ielem->localName = node->name;
27861
if (node->ns != NULL)
27862
ielem->nsName = node->ns->href;
27863
ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27864
/*
27865
* Register attributes.
27866
* DOC VAL TODO: We do not register namespace declaration
27867
* attributes yet.
27868
*/
27869
vctxt->nbAttrInfos = 0;
27870
if (node->properties != NULL) {
27871
attr = node->properties;
27872
do {
27873
if (attr->ns != NULL)
27874
nsName = attr->ns->href;
27875
else
27876
nsName = NULL;
27877
ret = xmlSchemaValidatorPushAttribute(vctxt,
27878
(xmlNodePtr) attr,
27879
/*
27880
* Note that we give it the line number of the
27881
* parent element.
27882
*/
27883
ielem->nodeLine,
27884
attr->name, nsName, 0,
27885
xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27886
if (ret == -1) {
27887
VERROR_INT("xmlSchemaDocWalk",
27888
"calling xmlSchemaValidatorPushAttribute()");
27889
goto internal_error;
27890
}
27891
attr = attr->next;
27892
} while (attr);
27893
}
27894
/*
27895
* Validate the element.
27896
*/
27897
ret = xmlSchemaValidateElem(vctxt);
27898
if (ret != 0) {
27899
if (ret == -1) {
27900
VERROR_INT("xmlSchemaDocWalk",
27901
"calling xmlSchemaValidateElem()");
27902
goto internal_error;
27903
}
27904
/*
27905
* Don't stop validation; just skip the content
27906
* of this element.
27907
*/
27908
goto leave_node;
27909
}
27910
if ((vctxt->skipDepth != -1) &&
27911
(vctxt->depth >= vctxt->skipDepth))
27912
goto leave_node;
27913
} else if ((node->type == XML_TEXT_NODE) ||
27914
(node->type == XML_CDATA_SECTION_NODE)) {
27915
/*
27916
* Process character content.
27917
*/
27918
if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27919
ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27920
ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27921
-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27922
if (ret < 0) {
27923
VERROR_INT("xmlSchemaVDocWalk",
27924
"calling xmlSchemaVPushText()");
27925
goto internal_error;
27926
}
27927
/*
27928
* DOC VAL TODO: Should we skip further validation of the
27929
* element content here?
27930
*/
27931
} else if ((node->type == XML_ENTITY_NODE) ||
27932
(node->type == XML_ENTITY_REF_NODE)) {
27933
/*
27934
* DOC VAL TODO: What to do with entities?
27935
*/
27936
VERROR_INT("xmlSchemaVDocWalk",
27937
"there is at least one entity reference in the node-tree "
27938
"currently being validated. Processing of entities with "
27939
"this XML Schema processor is not supported (yet). Please "
27940
"substitute entities before validation.");
27941
goto internal_error;
27942
} else {
27943
goto leave_node;
27944
/*
27945
* DOC VAL TODO: XInclude nodes, etc.
27946
*/
27947
}
27948
/*
27949
* Walk the doc.
27950
*/
27951
if (node->children != NULL) {
27952
node = node->children;
27953
continue;
27954
}
27955
leave_node:
27956
if (node->type == XML_ELEMENT_NODE) {
27957
/*
27958
* Leaving the scope of an element.
27959
*/
27960
if (node != vctxt->inode->node) {
27961
VERROR_INT("xmlSchemaVDocWalk",
27962
"element position mismatch");
27963
goto internal_error;
27964
}
27965
ret = xmlSchemaValidatorPopElem(vctxt);
27966
if (ret != 0) {
27967
if (ret < 0) {
27968
VERROR_INT("xmlSchemaVDocWalk",
27969
"calling xmlSchemaValidatorPopElem()");
27970
goto internal_error;
27971
}
27972
}
27973
if (node == valRoot)
27974
goto exit;
27975
}
27976
next_sibling:
27977
if (node->next != NULL)
27978
node = node->next;
27979
else {
27980
node = node->parent;
27981
goto leave_node;
27982
}
27983
}
27984
27985
exit:
27986
return (ret);
27987
internal_error:
27988
return (-1);
27989
}
27990
27991
static int
27992
xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27993
/*
27994
* Some initialization.
27995
*/
27996
vctxt->err = 0;
27997
vctxt->nberrors = 0;
27998
vctxt->depth = -1;
27999
vctxt->skipDepth = -1;
28000
vctxt->hasKeyrefs = 0;
28001
#ifdef ENABLE_IDC_NODE_TABLES_TEST
28002
vctxt->createIDCNodeTables = 1;
28003
#else
28004
vctxt->createIDCNodeTables = 0;
28005
#endif
28006
/*
28007
* Create a schema + parser if necessary.
28008
*/
28009
if (vctxt->schema == NULL) {
28010
xmlSchemaParserCtxtPtr pctxt;
28011
28012
vctxt->xsiAssemble = 1;
28013
/*
28014
* If not schema was given then we will create a schema
28015
* dynamically using XSI schema locations.
28016
*
28017
* Create the schema parser context.
28018
*/
28019
if ((vctxt->pctxt == NULL) &&
28020
(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28021
return (-1);
28022
pctxt = vctxt->pctxt;
28023
pctxt->xsiAssemble = 1;
28024
/*
28025
* Create the schema.
28026
*/
28027
vctxt->schema = xmlSchemaNewSchema(pctxt);
28028
if (vctxt->schema == NULL)
28029
return (-1);
28030
/*
28031
* Create the schema construction context.
28032
*/
28033
pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28034
if (pctxt->constructor == NULL)
28035
return(-1);
28036
pctxt->constructor->mainSchema = vctxt->schema;
28037
/*
28038
* Take ownership of the constructor to be able to free it.
28039
*/
28040
pctxt->ownsConstructor = 1;
28041
}
28042
/*
28043
* Augment the IDC definitions for the main schema and all imported ones
28044
* NOTE: main schema if the first in the imported list
28045
*/
28046
xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28047
vctxt);
28048
28049
return(0);
28050
}
28051
28052
static void
28053
xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28054
if (vctxt->xsiAssemble) {
28055
if (vctxt->schema != NULL) {
28056
xmlSchemaFree(vctxt->schema);
28057
vctxt->schema = NULL;
28058
}
28059
}
28060
xmlSchemaClearValidCtxt(vctxt);
28061
}
28062
28063
static int
28064
xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28065
{
28066
int ret = 0;
28067
28068
if (xmlSchemaPreRun(vctxt) < 0)
28069
return(-1);
28070
28071
if (vctxt->doc != NULL) {
28072
/*
28073
* Tree validation.
28074
*/
28075
ret = xmlSchemaVDocWalk(vctxt);
28076
#ifdef LIBXML_READER_ENABLED
28077
} else if (vctxt->reader != NULL) {
28078
/*
28079
* XML Reader validation.
28080
*/
28081
#ifdef XML_SCHEMA_READER_ENABLED
28082
ret = xmlSchemaVReaderWalk(vctxt);
28083
#endif
28084
#endif
28085
} else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28086
/*
28087
* SAX validation.
28088
*/
28089
ret = xmlParseDocument(vctxt->parserCtxt);
28090
} else {
28091
VERROR_INT("xmlSchemaVStart",
28092
"no instance to validate");
28093
ret = -1;
28094
}
28095
28096
xmlSchemaPostRun(vctxt);
28097
if (ret == 0)
28098
ret = vctxt->err;
28099
return (ret);
28100
}
28101
28102
/**
28103
* xmlSchemaValidateOneElement:
28104
* @ctxt: a schema validation context
28105
* @elem: an element node
28106
*
28107
* Validate a branch of a tree, starting with the given @elem.
28108
*
28109
* Returns 0 if the element and its subtree is valid, a positive error
28110
* code number otherwise and -1 in case of an internal or API error.
28111
*/
28112
int
28113
xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28114
{
28115
if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28116
return (-1);
28117
28118
if (ctxt->schema == NULL)
28119
return (-1);
28120
28121
ctxt->doc = elem->doc;
28122
ctxt->node = elem;
28123
ctxt->validationRoot = elem;
28124
return(xmlSchemaVStart(ctxt));
28125
}
28126
28127
/**
28128
* xmlSchemaValidateDoc:
28129
* @ctxt: a schema validation context
28130
* @doc: a parsed document tree
28131
*
28132
* Validate a document tree in memory.
28133
*
28134
* Returns 0 if the document is schemas valid, a positive error code
28135
* number otherwise and -1 in case of internal or API error.
28136
*/
28137
int
28138
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28139
{
28140
if ((ctxt == NULL) || (doc == NULL))
28141
return (-1);
28142
28143
ctxt->doc = doc;
28144
ctxt->node = xmlDocGetRootElement(doc);
28145
if (ctxt->node == NULL) {
28146
xmlSchemaCustomErr(ACTXT_CAST ctxt,
28147
XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28148
(xmlNodePtr) doc, NULL,
28149
"The document has no document element", NULL, NULL);
28150
return (ctxt->err);
28151
}
28152
ctxt->validationRoot = ctxt->node;
28153
return (xmlSchemaVStart(ctxt));
28154
}
28155
28156
28157
/************************************************************************
28158
* *
28159
* Function and data for SAX streaming API *
28160
* *
28161
************************************************************************/
28162
typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28163
typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28164
28165
struct _xmlSchemaSplitSAXData {
28166
xmlSAXHandlerPtr user_sax;
28167
void *user_data;
28168
xmlSchemaValidCtxtPtr ctxt;
28169
xmlSAXHandlerPtr schemas_sax;
28170
};
28171
28172
#define XML_SAX_PLUG_MAGIC 0xdc43ba21
28173
28174
struct _xmlSchemaSAXPlug {
28175
unsigned int magic;
28176
28177
/* the original callbacks information */
28178
xmlSAXHandlerPtr *user_sax_ptr;
28179
xmlSAXHandlerPtr user_sax;
28180
void **user_data_ptr;
28181
void *user_data;
28182
28183
/* the block plugged back and validation information */
28184
xmlSAXHandler schemas_sax;
28185
xmlSchemaValidCtxtPtr ctxt;
28186
};
28187
28188
/* All those functions just bounces to the user provided SAX handlers */
28189
static void
28190
internalSubsetSplit(void *ctx, const xmlChar *name,
28191
const xmlChar *ExternalID, const xmlChar *SystemID)
28192
{
28193
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28194
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28195
(ctxt->user_sax->internalSubset != NULL))
28196
ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28197
SystemID);
28198
}
28199
28200
static int
28201
isStandaloneSplit(void *ctx)
28202
{
28203
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28204
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28205
(ctxt->user_sax->isStandalone != NULL))
28206
return(ctxt->user_sax->isStandalone(ctxt->user_data));
28207
return(0);
28208
}
28209
28210
static int
28211
hasInternalSubsetSplit(void *ctx)
28212
{
28213
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28214
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28215
(ctxt->user_sax->hasInternalSubset != NULL))
28216
return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28217
return(0);
28218
}
28219
28220
static int
28221
hasExternalSubsetSplit(void *ctx)
28222
{
28223
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28224
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28225
(ctxt->user_sax->hasExternalSubset != NULL))
28226
return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28227
return(0);
28228
}
28229
28230
static void
28231
externalSubsetSplit(void *ctx, const xmlChar *name,
28232
const xmlChar *ExternalID, const xmlChar *SystemID)
28233
{
28234
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28235
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28236
(ctxt->user_sax->externalSubset != NULL))
28237
ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28238
SystemID);
28239
}
28240
28241
static xmlParserInputPtr
28242
resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28243
{
28244
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28245
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28246
(ctxt->user_sax->resolveEntity != NULL))
28247
return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28248
systemId));
28249
return(NULL);
28250
}
28251
28252
static xmlEntityPtr
28253
getEntitySplit(void *ctx, const xmlChar *name)
28254
{
28255
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28256
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28257
(ctxt->user_sax->getEntity != NULL))
28258
return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28259
return(NULL);
28260
}
28261
28262
static xmlEntityPtr
28263
getParameterEntitySplit(void *ctx, const xmlChar *name)
28264
{
28265
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28266
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28267
(ctxt->user_sax->getParameterEntity != NULL))
28268
return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28269
return(NULL);
28270
}
28271
28272
28273
static void
28274
entityDeclSplit(void *ctx, const xmlChar *name, int type,
28275
const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28276
{
28277
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28278
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28279
(ctxt->user_sax->entityDecl != NULL))
28280
ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28281
systemId, content);
28282
}
28283
28284
static void
28285
attributeDeclSplit(void *ctx, const xmlChar * elem,
28286
const xmlChar * name, int type, int def,
28287
const xmlChar * defaultValue, xmlEnumerationPtr tree)
28288
{
28289
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28290
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28291
(ctxt->user_sax->attributeDecl != NULL)) {
28292
ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28293
def, defaultValue, tree);
28294
} else {
28295
xmlFreeEnumeration(tree);
28296
}
28297
}
28298
28299
static void
28300
elementDeclSplit(void *ctx, const xmlChar *name, int type,
28301
xmlElementContentPtr content)
28302
{
28303
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28304
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28305
(ctxt->user_sax->elementDecl != NULL))
28306
ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28307
}
28308
28309
static void
28310
notationDeclSplit(void *ctx, const xmlChar *name,
28311
const xmlChar *publicId, const xmlChar *systemId)
28312
{
28313
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28314
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28315
(ctxt->user_sax->notationDecl != NULL))
28316
ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28317
systemId);
28318
}
28319
28320
static void
28321
unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28322
const xmlChar *publicId, const xmlChar *systemId,
28323
const xmlChar *notationName)
28324
{
28325
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28326
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28327
(ctxt->user_sax->unparsedEntityDecl != NULL))
28328
ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28329
systemId, notationName);
28330
}
28331
28332
static void
28333
setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28334
{
28335
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28336
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28337
(ctxt->user_sax->setDocumentLocator != NULL))
28338
ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28339
}
28340
28341
static void
28342
startDocumentSplit(void *ctx)
28343
{
28344
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28345
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28346
(ctxt->user_sax->startDocument != NULL))
28347
ctxt->user_sax->startDocument(ctxt->user_data);
28348
}
28349
28350
static void
28351
endDocumentSplit(void *ctx)
28352
{
28353
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28354
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28355
(ctxt->user_sax->endDocument != NULL))
28356
ctxt->user_sax->endDocument(ctxt->user_data);
28357
}
28358
28359
static void
28360
processingInstructionSplit(void *ctx, const xmlChar *target,
28361
const xmlChar *data)
28362
{
28363
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28364
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28365
(ctxt->user_sax->processingInstruction != NULL))
28366
ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28367
}
28368
28369
static void
28370
commentSplit(void *ctx, const xmlChar *value)
28371
{
28372
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28373
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28374
(ctxt->user_sax->comment != NULL))
28375
ctxt->user_sax->comment(ctxt->user_data, value);
28376
}
28377
28378
/*
28379
* Varargs error callbacks to the user application, harder ...
28380
*/
28381
28382
static void
28383
warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28384
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28385
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28386
(ctxt->user_sax->warning != NULL)) {
28387
TODO
28388
}
28389
}
28390
static void
28391
errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28392
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28393
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28394
(ctxt->user_sax->error != NULL)) {
28395
TODO
28396
}
28397
}
28398
static void
28399
fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28400
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28401
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28402
(ctxt->user_sax->fatalError != NULL)) {
28403
TODO
28404
}
28405
}
28406
28407
/*
28408
* Those are function where both the user handler and the schemas handler
28409
* need to be called.
28410
*/
28411
static void
28412
charactersSplit(void *ctx, const xmlChar *ch, int len)
28413
{
28414
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28415
if (ctxt == NULL)
28416
return;
28417
if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28418
ctxt->user_sax->characters(ctxt->user_data, ch, len);
28419
if (ctxt->ctxt != NULL)
28420
xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28421
}
28422
28423
static void
28424
ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28425
{
28426
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28427
if (ctxt == NULL)
28428
return;
28429
if ((ctxt->user_sax != NULL) &&
28430
(ctxt->user_sax->ignorableWhitespace != NULL))
28431
ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28432
if (ctxt->ctxt != NULL)
28433
xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28434
}
28435
28436
static void
28437
cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28438
{
28439
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28440
if (ctxt == NULL)
28441
return;
28442
if ((ctxt->user_sax != NULL) &&
28443
(ctxt->user_sax->cdataBlock != NULL))
28444
ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28445
if (ctxt->ctxt != NULL)
28446
xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28447
}
28448
28449
static void
28450
referenceSplit(void *ctx, const xmlChar *name)
28451
{
28452
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28453
if (ctxt == NULL)
28454
return;
28455
if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28456
(ctxt->user_sax->reference != NULL))
28457
ctxt->user_sax->reference(ctxt->user_data, name);
28458
if (ctxt->ctxt != NULL)
28459
xmlSchemaSAXHandleReference(ctxt->user_data, name);
28460
}
28461
28462
static void
28463
startElementNsSplit(void *ctx, const xmlChar * localname,
28464
const xmlChar * prefix, const xmlChar * URI,
28465
int nb_namespaces, const xmlChar ** namespaces,
28466
int nb_attributes, int nb_defaulted,
28467
const xmlChar ** attributes) {
28468
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28469
if (ctxt == NULL)
28470
return;
28471
if ((ctxt->user_sax != NULL) &&
28472
(ctxt->user_sax->startElementNs != NULL))
28473
ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28474
URI, nb_namespaces, namespaces,
28475
nb_attributes, nb_defaulted,
28476
attributes);
28477
if (ctxt->ctxt != NULL)
28478
xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28479
URI, nb_namespaces, namespaces,
28480
nb_attributes, nb_defaulted,
28481
attributes);
28482
}
28483
28484
static void
28485
endElementNsSplit(void *ctx, const xmlChar * localname,
28486
const xmlChar * prefix, const xmlChar * URI) {
28487
xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28488
if (ctxt == NULL)
28489
return;
28490
if ((ctxt->user_sax != NULL) &&
28491
(ctxt->user_sax->endElementNs != NULL))
28492
ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28493
if (ctxt->ctxt != NULL)
28494
xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28495
}
28496
28497
/**
28498
* xmlSchemaSAXPlug:
28499
* @ctxt: a schema validation context
28500
* @sax: a pointer to the original xmlSAXHandlerPtr
28501
* @user_data: a pointer to the original SAX user data pointer
28502
*
28503
* Plug a SAX based validation layer in a SAX parsing event flow.
28504
* The original @saxptr and @dataptr data are replaced by new pointers
28505
* but the calls to the original will be maintained.
28506
*
28507
* Returns a pointer to a data structure needed to unplug the validation layer
28508
* or NULL in case of errors.
28509
*/
28510
xmlSchemaSAXPlugPtr
28511
xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28512
xmlSAXHandlerPtr *sax, void **user_data)
28513
{
28514
xmlSchemaSAXPlugPtr ret;
28515
xmlSAXHandlerPtr old_sax;
28516
28517
if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28518
return(NULL);
28519
28520
/*
28521
* We only allow to plug into SAX2 event streams
28522
*/
28523
old_sax = *sax;
28524
if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28525
return(NULL);
28526
if ((old_sax != NULL) &&
28527
(old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28528
((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28529
return(NULL);
28530
28531
/*
28532
* everything seems right allocate the local data needed for that layer
28533
*/
28534
ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28535
if (ret == NULL) {
28536
return(NULL);
28537
}
28538
memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28539
ret->magic = XML_SAX_PLUG_MAGIC;
28540
ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28541
ret->ctxt = ctxt;
28542
ret->user_sax_ptr = sax;
28543
ret->user_sax = old_sax;
28544
if (old_sax == NULL) {
28545
/*
28546
* go direct, no need for the split block and functions.
28547
*/
28548
ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28549
ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28550
/*
28551
* Note that we use the same text-function for both, to prevent
28552
* the parser from testing for ignorable whitespace.
28553
*/
28554
ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28555
ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28556
28557
ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28558
ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28559
28560
ret->user_data = ctxt;
28561
*user_data = ctxt;
28562
} else {
28563
/*
28564
* for each callback unused by Schemas initialize it to the Split
28565
* routine only if non NULL in the user block, this can speed up
28566
* things at the SAX level.
28567
*/
28568
if (old_sax->internalSubset != NULL)
28569
ret->schemas_sax.internalSubset = internalSubsetSplit;
28570
if (old_sax->isStandalone != NULL)
28571
ret->schemas_sax.isStandalone = isStandaloneSplit;
28572
if (old_sax->hasInternalSubset != NULL)
28573
ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28574
if (old_sax->hasExternalSubset != NULL)
28575
ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28576
if (old_sax->resolveEntity != NULL)
28577
ret->schemas_sax.resolveEntity = resolveEntitySplit;
28578
if (old_sax->getEntity != NULL)
28579
ret->schemas_sax.getEntity = getEntitySplit;
28580
if (old_sax->entityDecl != NULL)
28581
ret->schemas_sax.entityDecl = entityDeclSplit;
28582
if (old_sax->notationDecl != NULL)
28583
ret->schemas_sax.notationDecl = notationDeclSplit;
28584
if (old_sax->attributeDecl != NULL)
28585
ret->schemas_sax.attributeDecl = attributeDeclSplit;
28586
if (old_sax->elementDecl != NULL)
28587
ret->schemas_sax.elementDecl = elementDeclSplit;
28588
if (old_sax->unparsedEntityDecl != NULL)
28589
ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28590
if (old_sax->setDocumentLocator != NULL)
28591
ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28592
if (old_sax->startDocument != NULL)
28593
ret->schemas_sax.startDocument = startDocumentSplit;
28594
if (old_sax->endDocument != NULL)
28595
ret->schemas_sax.endDocument = endDocumentSplit;
28596
if (old_sax->processingInstruction != NULL)
28597
ret->schemas_sax.processingInstruction = processingInstructionSplit;
28598
if (old_sax->comment != NULL)
28599
ret->schemas_sax.comment = commentSplit;
28600
if (old_sax->warning != NULL)
28601
ret->schemas_sax.warning = warningSplit;
28602
if (old_sax->error != NULL)
28603
ret->schemas_sax.error = errorSplit;
28604
if (old_sax->fatalError != NULL)
28605
ret->schemas_sax.fatalError = fatalErrorSplit;
28606
if (old_sax->getParameterEntity != NULL)
28607
ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28608
if (old_sax->externalSubset != NULL)
28609
ret->schemas_sax.externalSubset = externalSubsetSplit;
28610
28611
/*
28612
* the 6 schemas callback have to go to the splitter functions
28613
* Note that we use the same text-function for ignorableWhitespace
28614
* if possible, to prevent the parser from testing for ignorable
28615
* whitespace.
28616
*/
28617
ret->schemas_sax.characters = charactersSplit;
28618
if ((old_sax->ignorableWhitespace != NULL) &&
28619
(old_sax->ignorableWhitespace != old_sax->characters))
28620
ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28621
else
28622
ret->schemas_sax.ignorableWhitespace = charactersSplit;
28623
ret->schemas_sax.cdataBlock = cdataBlockSplit;
28624
ret->schemas_sax.reference = referenceSplit;
28625
ret->schemas_sax.startElementNs = startElementNsSplit;
28626
ret->schemas_sax.endElementNs = endElementNsSplit;
28627
28628
ret->user_data_ptr = user_data;
28629
ret->user_data = *user_data;
28630
*user_data = ret;
28631
}
28632
28633
/*
28634
* plug the pointers back.
28635
*/
28636
*sax = &(ret->schemas_sax);
28637
ctxt->sax = *sax;
28638
ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28639
xmlSchemaPreRun(ctxt);
28640
return(ret);
28641
}
28642
28643
/**
28644
* xmlSchemaSAXUnplug:
28645
* @plug: a data structure returned by xmlSchemaSAXPlug
28646
*
28647
* Unplug a SAX based validation layer in a SAX parsing event flow.
28648
* The original pointers used in the call are restored.
28649
*
28650
* Returns 0 in case of success and -1 in case of failure.
28651
*/
28652
int
28653
xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28654
{
28655
xmlSAXHandlerPtr *sax;
28656
void **user_data;
28657
28658
if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28659
return(-1);
28660
plug->magic = 0;
28661
28662
xmlSchemaPostRun(plug->ctxt);
28663
/* restore the data */
28664
sax = plug->user_sax_ptr;
28665
*sax = plug->user_sax;
28666
if (plug->user_sax != NULL) {
28667
user_data = plug->user_data_ptr;
28668
*user_data = plug->user_data;
28669
}
28670
28671
/* free and return */
28672
xmlFree(plug);
28673
return(0);
28674
}
28675
28676
/**
28677
* xmlSchemaValidateSetLocator:
28678
* @vctxt: a schema validation context
28679
* @f: the locator function pointer
28680
* @ctxt: the locator context
28681
*
28682
* Allows to set a locator function to the validation context,
28683
* which will be used to provide file and line information since
28684
* those are not provided as part of the SAX validation flow
28685
* Setting @f to NULL disable the locator.
28686
*/
28687
28688
void
28689
xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28690
xmlSchemaValidityLocatorFunc f,
28691
void *ctxt)
28692
{
28693
if (vctxt == NULL) return;
28694
vctxt->locFunc = f;
28695
vctxt->locCtxt = ctxt;
28696
}
28697
28698
/**
28699
* xmlSchemaValidateStreamLocator:
28700
* @ctx: the xmlTextReaderPtr used
28701
* @file: returned file information
28702
* @line: returned line information
28703
*
28704
* Internal locator function for the readers
28705
*
28706
* Returns 0 in case the Schema validation could be (de)activated and
28707
* -1 in case of error.
28708
*/
28709
static int
28710
xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28711
unsigned long *line) {
28712
xmlParserCtxtPtr ctxt;
28713
28714
if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28715
return(-1);
28716
28717
if (file != NULL)
28718
*file = NULL;
28719
if (line != NULL)
28720
*line = 0;
28721
28722
ctxt = (xmlParserCtxtPtr) ctx;
28723
if (ctxt->input != NULL) {
28724
if (file != NULL)
28725
*file = ctxt->input->filename;
28726
if (line != NULL)
28727
*line = ctxt->input->line;
28728
return(0);
28729
}
28730
return(-1);
28731
}
28732
28733
/**
28734
* xmlSchemaValidateStreamInternal:
28735
* @ctxt: a schema validation context
28736
* @pctxt: a parser context
28737
*
28738
* Returns 0 if the document is schemas valid, a positive error code
28739
* number otherwise and -1 in case of internal or API error.
28740
*/
28741
static int
28742
xmlSchemaValidateStreamInternal(xmlSchemaValidCtxtPtr ctxt,
28743
xmlParserCtxtPtr pctxt) {
28744
xmlSchemaSAXPlugPtr plug = NULL;
28745
int ret;
28746
28747
pctxt->linenumbers = 1;
28748
xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
28749
28750
ctxt->parserCtxt = pctxt;
28751
ctxt->input = pctxt->input->buf;
28752
28753
/*
28754
* Plug the validation and launch the parsing
28755
*/
28756
plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28757
if (plug == NULL) {
28758
ret = -1;
28759
goto done;
28760
}
28761
ctxt->input = pctxt->input->buf;
28762
ctxt->sax = pctxt->sax;
28763
ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28764
ret = xmlSchemaVStart(ctxt);
28765
28766
if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28767
ret = ctxt->parserCtxt->errNo;
28768
if (ret == 0)
28769
ret = 1;
28770
}
28771
28772
done:
28773
ctxt->parserCtxt = NULL;
28774
ctxt->sax = NULL;
28775
ctxt->input = NULL;
28776
if (plug != NULL) {
28777
xmlSchemaSAXUnplug(plug);
28778
}
28779
return (ret);
28780
}
28781
28782
/**
28783
* xmlSchemaValidateStream:
28784
* @ctxt: a schema validation context
28785
* @input: the input to use for reading the data
28786
* @enc: an optional encoding information
28787
* @sax: a SAX handler for the resulting events
28788
* @user_data: the context to provide to the SAX handler.
28789
*
28790
* Validate an input based on a flow of SAX event from the parser
28791
* and forward the events to the @sax handler with the provided @user_data
28792
* the user provided @sax handler must be a SAX2 one.
28793
*
28794
* Returns 0 if the document is schemas valid, a positive error code
28795
* number otherwise and -1 in case of internal or API error.
28796
*/
28797
int
28798
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28799
xmlParserInputBufferPtr input, xmlCharEncoding enc,
28800
xmlSAXHandlerPtr sax, void *user_data)
28801
{
28802
xmlParserCtxtPtr pctxt = NULL;
28803
xmlParserInputPtr inputStream = NULL;
28804
int ret;
28805
28806
if ((ctxt == NULL) || (input == NULL))
28807
return (-1);
28808
28809
/*
28810
* prepare the parser
28811
*/
28812
if (sax != NULL) {
28813
pctxt = xmlNewSAXParserCtxt(sax, user_data);
28814
if (pctxt == NULL)
28815
return (-1);
28816
} else {
28817
pctxt = xmlNewParserCtxt();
28818
if (pctxt == NULL)
28819
return (-1);
28820
/* We really want pctxt->sax to be NULL here. */
28821
xmlFree(pctxt->sax);
28822
pctxt->sax = NULL;
28823
}
28824
#if 0
28825
if (options)
28826
xmlCtxtUseOptions(pctxt, options);
28827
#endif
28828
28829
inputStream = xmlNewIOInputStream(pctxt, input, enc);
28830
if (inputStream == NULL) {
28831
ret = -1;
28832
goto done;
28833
}
28834
inputPush(pctxt, inputStream);
28835
28836
ctxt->enc = enc;
28837
28838
ret = xmlSchemaValidateStreamInternal(ctxt, pctxt);
28839
28840
done:
28841
/* cleanup */
28842
if (pctxt != NULL) {
28843
xmlFreeParserCtxt(pctxt);
28844
}
28845
return (ret);
28846
}
28847
28848
/**
28849
* xmlSchemaValidateFile:
28850
* @ctxt: a schema validation context
28851
* @filename: the URI of the instance
28852
* @options: a future set of options, currently unused
28853
*
28854
* Do a schemas validation of the given resource, it will use the
28855
* SAX streamable validation internally.
28856
*
28857
* Returns 0 if the document is valid, a positive error code
28858
* number otherwise and -1 in case of an internal or API error.
28859
*/
28860
int
28861
xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28862
const char * filename,
28863
int options ATTRIBUTE_UNUSED)
28864
{
28865
int ret;
28866
xmlParserCtxtPtr pctxt = NULL;
28867
28868
if ((ctxt == NULL) || (filename == NULL))
28869
return (-1);
28870
28871
pctxt = xmlCreateURLParserCtxt(filename, 0);
28872
if (pctxt == NULL)
28873
return (-1);
28874
/* We really want pctxt->sax to be NULL here. */
28875
xmlFree(pctxt->sax);
28876
pctxt->sax = NULL;
28877
ret = xmlSchemaValidateStreamInternal(ctxt, pctxt);
28878
xmlFreeParserCtxt(pctxt);
28879
return (ret);
28880
}
28881
28882
/**
28883
* xmlSchemaValidCtxtGetParserCtxt:
28884
* @ctxt: a schema validation context
28885
*
28886
* allow access to the parser context of the schema validation context
28887
*
28888
* Returns the parser context of the schema validation context or NULL
28889
* in case of error.
28890
*/
28891
xmlParserCtxtPtr
28892
xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28893
{
28894
if (ctxt == NULL)
28895
return(NULL);
28896
return (ctxt->parserCtxt);
28897
}
28898
28899
#endif /* LIBXML_SCHEMAS_ENABLED */
28900
28901