Annotation of embedaddon/libxml2/xmlschemas.c, revision 1.1.1.2
1.1 misho 1: /*
2: * schemas.c : implementation of the XML Schema handling and
3: * schema validity checking
4: *
5: * See Copyright for the status of this software.
6: *
7: * Daniel Veillard <veillard@redhat.com>
8: */
9:
10: /*
11: * TODO:
12: * - when types are redefined in includes, check that all
13: * types in the redef list are equal
14: * -> need a type equality operation.
15: * - if we don't intend to use the schema for schemas, we
16: * need to validate all schema attributes (ref, type, name)
17: * against their types.
18: * - Eliminate item creation for: ??
19: *
20: * URGENT TODO:
21: * - For xsi-driven schema acquisition, augment the IDCs after every
22: * acquisition episode (xmlSchemaAugmentIDC).
23: *
24: * NOTES:
25: * - Elimated 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: #define IN_LIBXML
48: #include "libxml.h"
49:
50: #ifdef LIBXML_SCHEMAS_ENABLED
51:
52: #include <string.h>
53: #include <libxml/xmlmemory.h>
54: #include <libxml/parser.h>
55: #include <libxml/parserInternals.h>
56: #include <libxml/hash.h>
57: #include <libxml/uri.h>
58: #include <libxml/xmlschemas.h>
59: #include <libxml/schemasInternals.h>
60: #include <libxml/xmlschemastypes.h>
61: #include <libxml/xmlautomata.h>
62: #include <libxml/xmlregexp.h>
63: #include <libxml/dict.h>
64: #include <libxml/encoding.h>
65: #include <libxml/xmlIO.h>
66: #ifdef LIBXML_PATTERN_ENABLED
67: #include <libxml/pattern.h>
68: #endif
69: #ifdef LIBXML_READER_ENABLED
70: #include <libxml/xmlreader.h>
71: #endif
72:
73: /* #define DEBUG 1 */
74:
75: /* #define DEBUG_CONTENT 1 */
76:
77: /* #define DEBUG_TYPE 1 */
78:
79: /* #define DEBUG_CONTENT_REGEXP 1 */
80:
81: /* #define DEBUG_AUTOMATA 1 */
82:
83: /* #define DEBUG_IDC */
84:
85: /* #define DEBUG_IDC_NODE_TABLE */
86:
87: /* #define WXS_ELEM_DECL_CONS_ENABLED */
88:
89: #ifdef DEBUG_IDC
90: #ifndef DEBUG_IDC_NODE_TABLE
91: #define DEBUG_IDC_NODE_TABLE
92: #endif
93: #endif
94:
95: /* #define ENABLE_PARTICLE_RESTRICTION 1 */
96:
97: #define ENABLE_REDEFINE
98:
99: /* #define ENABLE_NAMED_LOCALS */
100:
101: /* #define ENABLE_IDC_NODE_TABLES_TEST */
102:
103: #define DUMP_CONTENT_MODEL
104:
105: #ifdef LIBXML_READER_ENABLED
106: /* #define XML_SCHEMA_READER_ENABLED */
107: #endif
108:
109: #define UNBOUNDED (1 << 30)
110: #define TODO \
111: xmlGenericError(xmlGenericErrorContext, \
112: "Unimplemented block at %s:%d\n", \
113: __FILE__, __LINE__);
114:
115: #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
116:
117: /*
118: * The XML Schemas namespaces
119: */
120: static const xmlChar *xmlSchemaNs = (const xmlChar *)
121: "http://www.w3.org/2001/XMLSchema";
122:
123: static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
124: "http://www.w3.org/2001/XMLSchema-instance";
125:
126: static const xmlChar *xmlNamespaceNs = (const xmlChar *)
127: "http://www.w3.org/2000/xmlns/";
128:
129: /*
130: * Come casting macros.
131: */
132: #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
133: #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
134: #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
135: #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
136: #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
137: #define WXS_PTC_CAST (xmlSchemaParticlePtr)
138: #define WXS_TYPE_CAST (xmlSchemaTypePtr)
139: #define WXS_ELEM_CAST (xmlSchemaElementPtr)
140: #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
141: #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
142: #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
143: #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
144: #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
145: #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
146: #define WXS_IDC_CAST (xmlSchemaIDCPtr)
147: #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
148: #define WXS_LIST_CAST (xmlSchemaItemListPtr)
149:
150: /*
151: * Macros to query common properties of components.
152: */
153: #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
154:
155: #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
156: /*
157: * Macros for element declarations.
158: */
159: #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
160:
161: #define WXS_SUBST_HEAD(item) (item)->refDecl
162: /*
163: * Macros for attribute declarations.
164: */
165: #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
166: /*
167: * Macros for attribute uses.
168: */
169: #define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
170:
171: #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
172:
173: #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
174:
175: #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
176: /*
177: * Macros for attribute groups.
178: */
179: #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
180: #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
181: /*
182: * Macros for particles.
183: */
184: #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
185:
186: #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
187:
188: #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
189:
190: #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
191: /*
192: * Macros for model groups definitions.
193: */
194: #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
195: /*
196: * Macros for model groups.
197: */
198: #define WXS_IS_MODEL_GROUP(i) \
199: (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
200: ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
201: ((i)->type == XML_SCHEMA_TYPE_ALL))
202:
203: #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
204: /*
205: * Macros for schema buckets.
206: */
207: #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
208: ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
209:
210: #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
211: ((t) == XML_SCHEMA_SCHEMA_IMPORT))
212:
213: #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
214:
215: #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
216: /*
217: * Macros for complex/simple types.
218: */
219: #define WXS_IS_ANYTYPE(i) \
220: (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
221: ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
222:
223: #define WXS_IS_COMPLEX(i) \
224: (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
225: ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
226:
227: #define WXS_IS_SIMPLE(item) \
228: ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
229: ((item->type == XML_SCHEMA_TYPE_BASIC) && \
230: (item->builtInType != XML_SCHEMAS_ANYTYPE)))
231:
232: #define WXS_IS_ANY_SIMPLE_TYPE(i) \
233: (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
234: ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
235:
236: #define WXS_IS_RESTRICTION(t) \
237: ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
238:
239: #define WXS_IS_EXTENSION(t) \
240: ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
241:
242: #define WXS_IS_TYPE_NOT_FIXED(i) \
243: (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
244: (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
245:
246: #define WXS_IS_TYPE_NOT_FIXED_1(item) \
247: (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
248: (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
249:
250: #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
251:
252: #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
253: /*
254: * Macros for exclusively for complex types.
255: */
256: #define WXS_HAS_COMPLEX_CONTENT(item) \
257: ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
258: (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
259: (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
260:
261: #define WXS_HAS_SIMPLE_CONTENT(item) \
262: ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
263: (item->contentType == XML_SCHEMA_CONTENT_BASIC))
264:
265: #define WXS_HAS_MIXED_CONTENT(item) \
266: (item->contentType == XML_SCHEMA_CONTENT_MIXED)
267:
268: #define WXS_EMPTIABLE(t) \
269: (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
270:
271: #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
272:
273: #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
274:
275: #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
276: /*
277: * Macros for exclusively for simple types.
278: */
279: #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
280:
281: #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
282:
283: #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
284:
285: #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
286: /*
287: * Misc parser context macros.
288: */
289: #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
290:
291: #define WXS_HAS_BUCKETS(ctx) \
292: ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
293: (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
294:
295: #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
296:
297: #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
298:
299: #define WXS_SCHEMA(ctx) (ctx)->schema
300:
301: #define WXS_ADD_LOCAL(ctx, item) \
302: xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
303:
304: #define WXS_ADD_GLOBAL(ctx, item) \
305: xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
306:
307: #define WXS_ADD_PENDING(ctx, item) \
308: xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
309: /*
310: * xmlSchemaItemList macros.
311: */
312: #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
313: /*
314: * Misc macros.
315: */
316: #define IS_SCHEMA(node, type) \
317: ((node != NULL) && (node->ns != NULL) && \
318: (xmlStrEqual(node->name, (const xmlChar *) type)) && \
319: (xmlStrEqual(node->ns->href, xmlSchemaNs)))
320:
321: #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
322:
323: /*
324: * Since we put the default/fixed values into the dict, we can
325: * use pointer comparison for those values.
326: * REMOVED: (xmlStrEqual((v1), (v2)))
327: */
328: #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
329:
330: #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
331:
332: #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
333:
334: #define HFAILURE if (res == -1) goto exit_failure;
335:
336: #define HERROR if (res != 0) goto exit_error;
337:
338: #define HSTOP(ctx) if ((ctx)->stop) goto exit;
339: /*
340: * Some flags used for various schema constraints.
341: */
342: #define SUBSET_RESTRICTION 1<<0
343: #define SUBSET_EXTENSION 1<<1
344: #define SUBSET_SUBSTITUTION 1<<2
345: #define SUBSET_LIST 1<<3
346: #define SUBSET_UNION 1<<4
347:
348: typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
349: typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
350:
351: typedef struct _xmlSchemaItemList xmlSchemaItemList;
352: typedef xmlSchemaItemList *xmlSchemaItemListPtr;
353: struct _xmlSchemaItemList {
354: void **items; /* used for dynamic addition of schemata */
355: int nbItems; /* used for dynamic addition of schemata */
356: int sizeItems; /* used for dynamic addition of schemata */
357: };
358:
359: #define XML_SCHEMA_CTXT_PARSER 1
360: #define XML_SCHEMA_CTXT_VALIDATOR 2
361:
362: typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
363: typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
364: struct _xmlSchemaAbstractCtxt {
365: int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
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: };
477:
478: /**
479: * xmlSchemaAnnotItem:
480: *
481: * The abstract base type for annotated schema components.
482: * (Extends xmlSchemaBasicItem)
483: */
484: typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
485: typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
486: struct _xmlSchemaAnnotItem {
487: xmlSchemaTypeType type;
488: xmlSchemaAnnotPtr annot;
489: };
490:
491: /**
492: * xmlSchemaTreeItem:
493: *
494: * The abstract base type for tree-like structured schema components.
495: * (Extends xmlSchemaAnnotItem)
496: */
497: typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
498: typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
499: struct _xmlSchemaTreeItem {
500: xmlSchemaTypeType type;
501: xmlSchemaAnnotPtr annot;
502: xmlSchemaTreeItemPtr next;
503: xmlSchemaTreeItemPtr children;
504: };
505:
506:
507: #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
508: /**
509: * xmlSchemaAttributeUsePtr:
510: *
511: * The abstract base type for tree-like structured schema components.
512: * (Extends xmlSchemaTreeItem)
513: */
514: typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
515: typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
516: struct _xmlSchemaAttributeUse {
517: xmlSchemaTypeType type;
518: xmlSchemaAnnotPtr annot;
519: xmlSchemaAttributeUsePtr next; /* The next attr. use. */
520: /*
521: * The attr. decl. OR a QName-ref. to an attr. decl. OR
522: * a QName-ref. to an attribute group definition.
523: */
524: xmlSchemaAttributePtr attrDecl;
525:
526: int flags;
527: xmlNodePtr node;
528: int occurs; /* required, optional */
529: const xmlChar * defValue;
530: xmlSchemaValPtr defVal;
531: };
532:
533: /**
534: * xmlSchemaAttributeUseProhibPtr:
535: *
536: * A helper component to reflect attribute prohibitions.
537: * (Extends xmlSchemaBasicItem)
538: */
539: typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
540: typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
541: struct _xmlSchemaAttributeUseProhib {
542: xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
543: xmlNodePtr node;
544: const xmlChar *name;
545: const xmlChar *targetNamespace;
546: int isRef;
547: };
548:
549: /**
550: * xmlSchemaRedef:
551: */
552: typedef struct _xmlSchemaRedef xmlSchemaRedef;
553: typedef xmlSchemaRedef *xmlSchemaRedefPtr;
554: struct _xmlSchemaRedef {
555: xmlSchemaRedefPtr next;
556: xmlSchemaBasicItemPtr item; /* The redefining component. */
557: xmlSchemaBasicItemPtr reference; /* The referencing component. */
558: xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
559: const xmlChar *refName; /* The name of the to-be-redefined component. */
560: const xmlChar *refTargetNs; /* The target namespace of the
561: to-be-redefined comp. */
562: xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
563: };
564:
565: /**
566: * xmlSchemaConstructionCtxt:
567: */
568: typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
569: typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
570: struct _xmlSchemaConstructionCtxt {
571: xmlSchemaPtr mainSchema; /* The main schema. */
572: xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
573: xmlDictPtr dict;
574: xmlSchemaItemListPtr buckets; /* List of schema buckets. */
575: /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
576: xmlSchemaBucketPtr bucket; /* The current schema bucket */
577: xmlSchemaItemListPtr pending; /* All Components of all schemas that
578: need to be fixed. */
579: xmlHashTablePtr substGroups;
580: xmlSchemaRedefPtr redefs;
581: xmlSchemaRedefPtr lastRedef;
582: };
583:
584: #define XML_SCHEMAS_PARSE_ERROR 1
585: #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
586:
587: struct _xmlSchemaParserCtxt {
588: int type;
589: void *errCtxt; /* user specific error context */
590: xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
591: xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
592: int err;
593: int nberrors;
594: xmlStructuredErrorFunc serror;
595:
596: xmlSchemaConstructionCtxtPtr constructor;
597: int ownsConstructor; /* TODO: Move this to parser *flags*. */
598:
599: /* xmlSchemaPtr topschema; */
600: /* xmlHashTablePtr namespaces; */
601:
602: xmlSchemaPtr schema; /* The main schema in use */
603: int counter;
604:
605: const xmlChar *URL;
606: xmlDocPtr doc;
607: int preserve; /* Whether the doc should be freed */
608:
609: const char *buffer;
610: int size;
611:
612: /*
613: * Used to build complex element content models
614: */
615: xmlAutomataPtr am;
616: xmlAutomataStatePtr start;
617: xmlAutomataStatePtr end;
618: xmlAutomataStatePtr state;
619:
620: xmlDictPtr dict; /* dictionnary for interned string names */
621: xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
622: int options;
623: xmlSchemaValidCtxtPtr vctxt;
624: int isS4S;
625: int isRedefine;
626: int xsiAssemble;
627: int stop; /* If the parser should stop; i.e. a critical error. */
628: const xmlChar *targetNamespace;
629: xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
630:
631: xmlSchemaRedefPtr redef; /* Used for redefinitions. */
632: int redefCounter; /* Used for redefinitions. */
633: xmlSchemaItemListPtr attrProhibs;
634: };
635:
636: /**
637: * xmlSchemaQNameRef:
638: *
639: * A component reference item (not a schema component)
640: * (Extends xmlSchemaBasicItem)
641: */
642: typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
643: typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
644: struct _xmlSchemaQNameRef {
645: xmlSchemaTypeType type;
646: xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
647: xmlSchemaTypeType itemType;
648: const xmlChar *name;
649: const xmlChar *targetNamespace;
650: xmlNodePtr node;
651: };
652:
653: /**
654: * xmlSchemaParticle:
655: *
656: * A particle component.
657: * (Extends xmlSchemaTreeItem)
658: */
659: typedef struct _xmlSchemaParticle xmlSchemaParticle;
660: typedef xmlSchemaParticle *xmlSchemaParticlePtr;
661: struct _xmlSchemaParticle {
662: xmlSchemaTypeType type;
663: xmlSchemaAnnotPtr annot;
664: xmlSchemaTreeItemPtr next; /* next particle */
665: xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
666: a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
667: etc.) */
668: int minOccurs;
669: int maxOccurs;
670: xmlNodePtr node;
671: };
672:
673: /**
674: * xmlSchemaModelGroup:
675: *
676: * A model group component.
677: * (Extends xmlSchemaTreeItem)
678: */
679: typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
680: typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
681: struct _xmlSchemaModelGroup {
682: xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
683: xmlSchemaAnnotPtr annot;
684: xmlSchemaTreeItemPtr next; /* not used */
685: xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
686: xmlNodePtr node;
687: };
688:
689: #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
690: #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
691: /**
692: * xmlSchemaModelGroupDef:
693: *
694: * A model group definition component.
695: * (Extends xmlSchemaTreeItem)
696: */
697: typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
698: typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
699: struct _xmlSchemaModelGroupDef {
700: xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
701: xmlSchemaAnnotPtr annot;
702: xmlSchemaTreeItemPtr next; /* not used */
703: xmlSchemaTreeItemPtr children; /* the "model group" */
704: const xmlChar *name;
705: const xmlChar *targetNamespace;
706: xmlNodePtr node;
707: int flags;
708: };
709:
710: typedef struct _xmlSchemaIDC xmlSchemaIDC;
711: typedef xmlSchemaIDC *xmlSchemaIDCPtr;
712:
713: /**
714: * xmlSchemaIDCSelect:
715: *
716: * The identity-constraint "field" and "selector" item, holding the
717: * XPath expression.
718: */
719: typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
720: typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
721: struct _xmlSchemaIDCSelect {
722: xmlSchemaIDCSelectPtr next;
723: xmlSchemaIDCPtr idc;
724: int index; /* an index position if significant for IDC key-sequences */
725: const xmlChar *xpath; /* the XPath expression */
726: void *xpathComp; /* the compiled XPath expression */
727: };
728:
729: /**
730: * xmlSchemaIDC:
731: *
732: * The identity-constraint definition component.
733: * (Extends xmlSchemaAnnotItem)
734: */
735:
736: struct _xmlSchemaIDC {
737: xmlSchemaTypeType type;
738: xmlSchemaAnnotPtr annot;
739: xmlSchemaIDCPtr next;
740: xmlNodePtr node;
741: const xmlChar *name;
742: const xmlChar *targetNamespace;
743: xmlSchemaIDCSelectPtr selector;
744: xmlSchemaIDCSelectPtr fields;
745: int nbFields;
746: xmlSchemaQNameRefPtr ref;
747: };
748:
749: /**
750: * xmlSchemaIDCAug:
751: *
752: * The augmented IDC information used for validation.
753: */
754: typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
755: typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
756: struct _xmlSchemaIDCAug {
757: xmlSchemaIDCAugPtr next; /* next in a list */
758: xmlSchemaIDCPtr def; /* the IDC definition */
759: int keyrefDepth; /* the lowest tree level to which IDC
760: tables need to be bubbled upwards */
761: };
762:
763: /**
764: * xmlSchemaPSVIIDCKeySequence:
765: *
766: * The key sequence of a node table item.
767: */
768: typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
769: typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
770: struct _xmlSchemaPSVIIDCKey {
771: xmlSchemaTypePtr type;
772: xmlSchemaValPtr val;
773: };
774:
775: /**
776: * xmlSchemaPSVIIDCNode:
777: *
778: * The node table item of a node table.
779: */
780: typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
781: typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
782: struct _xmlSchemaPSVIIDCNode {
783: xmlNodePtr node;
784: xmlSchemaPSVIIDCKeyPtr *keys;
785: int nodeLine;
786: int nodeQNameID;
787:
788: };
789:
790: /**
791: * xmlSchemaPSVIIDCBinding:
792: *
793: * The identity-constraint binding item of the [identity-constraint table].
794: */
795: typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
796: typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
797: struct _xmlSchemaPSVIIDCBinding {
798: xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
799: xmlSchemaIDCPtr definition; /* the IDC definition */
800: xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
801: int nbNodes; /* number of entries in the node table */
802: int sizeNodes; /* size of the node table */
803: xmlSchemaItemListPtr dupls;
804: };
805:
806:
807: #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
808: #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
809:
810: #define XPATH_STATE_OBJ_MATCHES -2
811: #define XPATH_STATE_OBJ_BLOCKED -3
812:
813: typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
814: typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
815:
816: /**
817: * xmlSchemaIDCStateObj:
818: *
819: * The state object used to evaluate XPath expressions.
820: */
821: typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
822: typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
823: struct _xmlSchemaIDCStateObj {
824: int type;
825: xmlSchemaIDCStateObjPtr next; /* next if in a list */
826: int depth; /* depth of creation */
827: int *history; /* list of (depth, state-id) tuples */
828: int nbHistory;
829: int sizeHistory;
830: xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
831: matcher */
832: xmlSchemaIDCSelectPtr sel;
833: void *xpathCtxt;
834: };
835:
836: #define IDC_MATCHER 0
837:
838: /**
839: * xmlSchemaIDCMatcher:
840: *
841: * Used to evaluate IDC selectors (and fields).
842: */
843: struct _xmlSchemaIDCMatcher {
844: int type;
845: int depth; /* the tree depth at creation time */
846: xmlSchemaIDCMatcherPtr next; /* next in the list */
847: xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
848: xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
849: int idcType;
850: xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
851: elements */
852: int sizeKeySeqs;
853: xmlSchemaItemListPtr targets; /* list of target-node
854: (xmlSchemaPSVIIDCNodePtr) entries */
855: };
856:
857: /*
858: * Element info flags.
859: */
860: #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
861: #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
862: #define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
863: #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
864:
865: #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
866: #define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
867: #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
868:
869: #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
870: #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
871: #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
872: #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
873:
874: /**
875: * xmlSchemaNodeInfo:
876: *
877: * Holds information of an element node.
878: */
879: struct _xmlSchemaNodeInfo {
880: int nodeType;
881: xmlNodePtr node;
882: int nodeLine;
883: const xmlChar *localName;
884: const xmlChar *nsName;
885: const xmlChar *value;
886: xmlSchemaValPtr val; /* the pre-computed value if any */
887: xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
888:
889: int flags; /* combination of node info flags */
890:
891: int valNeeded;
892: int normVal;
893:
894: xmlSchemaElementPtr decl; /* the element/attribute declaration */
895: int depth;
896: xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
897: for the scope element*/
898: xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
899: element */
900: xmlRegExecCtxtPtr regexCtxt;
901:
902: const xmlChar **nsBindings; /* Namespace bindings on this element */
903: int nbNsBindings;
904: int sizeNsBindings;
905:
906: int hasKeyrefs;
907: int appliedXPath; /* Indicates that an XPath has been applied. */
908: };
909:
910: #define XML_SCHEMAS_ATTR_UNKNOWN 1
911: #define XML_SCHEMAS_ATTR_ASSESSED 2
912: #define XML_SCHEMAS_ATTR_PROHIBITED 3
913: #define XML_SCHEMAS_ATTR_ERR_MISSING 4
914: #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
915: #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
916: #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
917: #define XML_SCHEMAS_ATTR_DEFAULT 8
918: #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
919: #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
920: #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
921: #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
922: #define XML_SCHEMAS_ATTR_WILD_SKIP 13
923: #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
924: #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
925: #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
926: #define XML_SCHEMAS_ATTR_META 17
927: /*
928: * @metaType values of xmlSchemaAttrInfo.
929: */
930: #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
931: #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
932: #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
933: #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
934: #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
935:
936: typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
937: typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
938: struct _xmlSchemaAttrInfo {
939: int nodeType;
940: xmlNodePtr node;
941: int nodeLine;
942: const xmlChar *localName;
943: const xmlChar *nsName;
944: const xmlChar *value;
945: xmlSchemaValPtr val; /* the pre-computed value if any */
946: xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
947: int flags; /* combination of node info flags */
948:
949: xmlSchemaAttributePtr decl; /* the attribute declaration */
950: xmlSchemaAttributeUsePtr use; /* the attribute use */
951: int state;
952: int metaType;
953: const xmlChar *vcValue; /* the value constraint value */
954: xmlSchemaNodeInfoPtr parent;
955: };
956:
957:
958: #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
959: /**
960: * xmlSchemaValidCtxt:
961: *
962: * A Schemas validation context
963: */
964: struct _xmlSchemaValidCtxt {
965: int type;
966: void *errCtxt; /* user specific data block */
967: xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
968: xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
969: xmlStructuredErrorFunc serror;
970:
971: xmlSchemaPtr schema; /* The schema in use */
972: xmlDocPtr doc;
973: xmlParserInputBufferPtr input;
974: xmlCharEncoding enc;
975: xmlSAXHandlerPtr sax;
976: xmlParserCtxtPtr parserCtxt;
977: void *user_data; /* TODO: What is this for? */
978:
979: int err;
980: int nberrors;
981:
982: xmlNodePtr node;
983: xmlNodePtr cur;
984: /* xmlSchemaTypePtr type; */
985:
986: xmlRegExecCtxtPtr regexp;
987: xmlSchemaValPtr value;
988:
989: int valueWS;
990: int options;
991: xmlNodePtr validationRoot;
992: xmlSchemaParserCtxtPtr pctxt;
993: int xsiAssemble;
994:
995: int depth;
996: xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
997: int sizeElemInfos;
998: xmlSchemaNodeInfoPtr inode; /* the current element information */
999:
1000: xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1001:
1002: xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1003: xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1004: xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1005:
1006: xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1007: int nbIdcNodes;
1008: int sizeIdcNodes;
1009:
1010: xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1011: int nbIdcKeys;
1012: int sizeIdcKeys;
1013:
1014: int flags;
1015:
1016: xmlDictPtr dict;
1017:
1018: #ifdef LIBXML_READER_ENABLED
1019: xmlTextReaderPtr reader;
1020: #endif
1021:
1022: xmlSchemaAttrInfoPtr *attrInfos;
1023: int nbAttrInfos;
1024: int sizeAttrInfos;
1025:
1026: int skipDepth;
1027: xmlSchemaItemListPtr nodeQNames;
1028: int hasKeyrefs;
1029: int createIDCNodeTables;
1030: int psviExposeIDCNodeTables;
1031: };
1032:
1033: /**
1034: * xmlSchemaSubstGroup:
1035: *
1036: *
1037: */
1038: typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1039: typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1040: struct _xmlSchemaSubstGroup {
1041: xmlSchemaElementPtr head;
1042: xmlSchemaItemListPtr members;
1043: };
1044:
1045: /************************************************************************
1046: * *
1047: * Some predeclarations *
1048: * *
1049: ************************************************************************/
1050:
1051: static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1052: xmlSchemaPtr schema,
1053: xmlNodePtr node);
1054: static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1055: xmlSchemaPtr schema,
1056: xmlNodePtr node);
1057: static int
1058: xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1059: xmlSchemaAbstractCtxtPtr ctxt);
1060: static const xmlChar *
1061: xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1062: static int
1063: xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1064: xmlNodePtr node);
1065: static int
1066: xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1067: xmlSchemaParserCtxtPtr ctxt);
1068: static void
1069: xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1070: static xmlSchemaWhitespaceValueType
1071: xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1072: static xmlSchemaTreeItemPtr
1073: xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1074: xmlNodePtr node, xmlSchemaTypeType type,
1075: int withParticle);
1076: static const xmlChar *
1077: xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1078: static xmlSchemaTypeLinkPtr
1079: xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1080: static void
1081: xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1082: const char *funcName,
1083: const char *message);
1084: static int
1085: xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1086: xmlSchemaTypePtr type,
1087: xmlSchemaTypePtr baseType,
1088: int subset);
1089: static void
1090: xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1091: xmlSchemaParserCtxtPtr ctxt);
1092: static void
1093: xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1094: static xmlSchemaQNameRefPtr
1095: xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1096: xmlSchemaPtr schema,
1097: xmlNodePtr node);
1098:
1099: /************************************************************************
1100: * *
1101: * Helper functions *
1102: * *
1103: ************************************************************************/
1104:
1105: /**
1106: * xmlSchemaItemTypeToStr:
1107: * @type: the type of the schema item
1108: *
1109: * Returns the component name of a schema item.
1110: */
1111: static const xmlChar *
1112: xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1113: {
1114: switch (type) {
1115: case XML_SCHEMA_TYPE_BASIC:
1116: return(BAD_CAST "simple type definition");
1117: case XML_SCHEMA_TYPE_SIMPLE:
1118: return(BAD_CAST "simple type definition");
1119: case XML_SCHEMA_TYPE_COMPLEX:
1120: return(BAD_CAST "complex type definition");
1121: case XML_SCHEMA_TYPE_ELEMENT:
1122: return(BAD_CAST "element declaration");
1123: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1124: return(BAD_CAST "attribute use");
1125: case XML_SCHEMA_TYPE_ATTRIBUTE:
1126: return(BAD_CAST "attribute declaration");
1127: case XML_SCHEMA_TYPE_GROUP:
1128: return(BAD_CAST "model group definition");
1129: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1130: return(BAD_CAST "attribute group definition");
1131: case XML_SCHEMA_TYPE_NOTATION:
1132: return(BAD_CAST "notation declaration");
1133: case XML_SCHEMA_TYPE_SEQUENCE:
1134: return(BAD_CAST "model group (sequence)");
1135: case XML_SCHEMA_TYPE_CHOICE:
1136: return(BAD_CAST "model group (choice)");
1137: case XML_SCHEMA_TYPE_ALL:
1138: return(BAD_CAST "model group (all)");
1139: case XML_SCHEMA_TYPE_PARTICLE:
1140: return(BAD_CAST "particle");
1141: case XML_SCHEMA_TYPE_IDC_UNIQUE:
1142: return(BAD_CAST "unique identity-constraint");
1143: /* return(BAD_CAST "IDC (unique)"); */
1144: case XML_SCHEMA_TYPE_IDC_KEY:
1145: return(BAD_CAST "key identity-constraint");
1146: /* return(BAD_CAST "IDC (key)"); */
1147: case XML_SCHEMA_TYPE_IDC_KEYREF:
1148: return(BAD_CAST "keyref identity-constraint");
1149: /* return(BAD_CAST "IDC (keyref)"); */
1150: case XML_SCHEMA_TYPE_ANY:
1151: return(BAD_CAST "wildcard (any)");
1152: case XML_SCHEMA_EXTRA_QNAMEREF:
1153: return(BAD_CAST "[helper component] QName reference");
1154: case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1155: return(BAD_CAST "[helper component] attribute use prohibition");
1156: default:
1157: return(BAD_CAST "Not a schema component");
1158: }
1159: }
1160:
1161: /**
1162: * xmlSchemaGetComponentTypeStr:
1163: * @type: the type of the schema item
1164: *
1165: * Returns the component name of a schema item.
1166: */
1167: static const xmlChar *
1168: xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1169: {
1170: switch (item->type) {
1171: case XML_SCHEMA_TYPE_BASIC:
1172: if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1173: return(BAD_CAST "complex type definition");
1174: else
1175: return(BAD_CAST "simple type definition");
1176: default:
1177: return(xmlSchemaItemTypeToStr(item->type));
1178: }
1179: }
1180:
1181: /**
1182: * xmlSchemaGetComponentNode:
1183: * @item: a schema component
1184: *
1185: * Returns node associated with the schema component.
1186: * NOTE that such a node need not be available; plus, a component's
1187: * node need not to reflect the component directly, since there is no
1188: * one-to-one relationship between the XML Schema representation and
1189: * the component representation.
1190: */
1191: static xmlNodePtr
1192: xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1193: {
1194: switch (item->type) {
1195: case XML_SCHEMA_TYPE_ELEMENT:
1196: return (((xmlSchemaElementPtr) item)->node);
1197: case XML_SCHEMA_TYPE_ATTRIBUTE:
1198: return (((xmlSchemaAttributePtr) item)->node);
1199: case XML_SCHEMA_TYPE_COMPLEX:
1200: case XML_SCHEMA_TYPE_SIMPLE:
1201: return (((xmlSchemaTypePtr) item)->node);
1202: case XML_SCHEMA_TYPE_ANY:
1203: case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1204: return (((xmlSchemaWildcardPtr) item)->node);
1205: case XML_SCHEMA_TYPE_PARTICLE:
1206: return (((xmlSchemaParticlePtr) item)->node);
1207: case XML_SCHEMA_TYPE_SEQUENCE:
1208: case XML_SCHEMA_TYPE_CHOICE:
1209: case XML_SCHEMA_TYPE_ALL:
1210: return (((xmlSchemaModelGroupPtr) item)->node);
1211: case XML_SCHEMA_TYPE_GROUP:
1212: return (((xmlSchemaModelGroupDefPtr) item)->node);
1213: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1214: return (((xmlSchemaAttributeGroupPtr) item)->node);
1215: case XML_SCHEMA_TYPE_IDC_UNIQUE:
1216: case XML_SCHEMA_TYPE_IDC_KEY:
1217: case XML_SCHEMA_TYPE_IDC_KEYREF:
1218: return (((xmlSchemaIDCPtr) item)->node);
1219: case XML_SCHEMA_EXTRA_QNAMEREF:
1220: return(((xmlSchemaQNameRefPtr) item)->node);
1221: /* TODO: What to do with NOTATIONs?
1222: case XML_SCHEMA_TYPE_NOTATION:
1223: return (((xmlSchemaNotationPtr) item)->node);
1224: */
1225: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1226: return (((xmlSchemaAttributeUsePtr) item)->node);
1227: default:
1228: return (NULL);
1229: }
1230: }
1231:
1232: #if 0
1233: /**
1234: * xmlSchemaGetNextComponent:
1235: * @item: a schema component
1236: *
1237: * Returns the next sibling of the schema component.
1238: */
1239: static xmlSchemaBasicItemPtr
1240: xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1241: {
1242: switch (item->type) {
1243: case XML_SCHEMA_TYPE_ELEMENT:
1244: return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1245: case XML_SCHEMA_TYPE_ATTRIBUTE:
1246: return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1247: case XML_SCHEMA_TYPE_COMPLEX:
1248: case XML_SCHEMA_TYPE_SIMPLE:
1249: return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1250: case XML_SCHEMA_TYPE_ANY:
1251: case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1252: return (NULL);
1253: case XML_SCHEMA_TYPE_PARTICLE:
1254: return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1255: case XML_SCHEMA_TYPE_SEQUENCE:
1256: case XML_SCHEMA_TYPE_CHOICE:
1257: case XML_SCHEMA_TYPE_ALL:
1258: return (NULL);
1259: case XML_SCHEMA_TYPE_GROUP:
1260: return (NULL);
1261: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1262: return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1263: case XML_SCHEMA_TYPE_IDC_UNIQUE:
1264: case XML_SCHEMA_TYPE_IDC_KEY:
1265: case XML_SCHEMA_TYPE_IDC_KEYREF:
1266: return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1267: default:
1268: return (NULL);
1269: }
1270: }
1271: #endif
1272:
1273:
1274: /**
1275: * xmlSchemaFormatQName:
1276: * @buf: the string buffer
1277: * @namespaceName: the namespace name
1278: * @localName: the local name
1279: *
1280: * Returns the given QName in the format "{namespaceName}localName" or
1281: * just "localName" if @namespaceName is NULL.
1282: *
1283: * Returns the localName if @namespaceName is NULL, a formatted
1284: * string otherwise.
1285: */
1286: static const xmlChar*
1287: xmlSchemaFormatQName(xmlChar **buf,
1288: const xmlChar *namespaceName,
1289: const xmlChar *localName)
1290: {
1291: FREE_AND_NULL(*buf)
1292: if (namespaceName != NULL) {
1293: *buf = xmlStrdup(BAD_CAST "{");
1294: *buf = xmlStrcat(*buf, namespaceName);
1295: *buf = xmlStrcat(*buf, BAD_CAST "}");
1296: }
1297: if (localName != NULL) {
1298: if (namespaceName == NULL)
1299: return(localName);
1300: *buf = xmlStrcat(*buf, localName);
1301: } else {
1302: *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1303: }
1304: return ((const xmlChar *) *buf);
1305: }
1306:
1307: static const xmlChar*
1308: xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1309: {
1310: if (ns != NULL)
1311: return (xmlSchemaFormatQName(buf, ns->href, localName));
1312: else
1313: return (xmlSchemaFormatQName(buf, NULL, localName));
1314: }
1315:
1316: static const xmlChar *
1317: xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1318: {
1319: switch (item->type) {
1320: case XML_SCHEMA_TYPE_ELEMENT:
1321: return (((xmlSchemaElementPtr) item)->name);
1322: case XML_SCHEMA_TYPE_ATTRIBUTE:
1323: return (((xmlSchemaAttributePtr) item)->name);
1324: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1325: return (((xmlSchemaAttributeGroupPtr) item)->name);
1326: case XML_SCHEMA_TYPE_BASIC:
1327: case XML_SCHEMA_TYPE_SIMPLE:
1328: case XML_SCHEMA_TYPE_COMPLEX:
1329: return (((xmlSchemaTypePtr) item)->name);
1330: case XML_SCHEMA_TYPE_GROUP:
1331: return (((xmlSchemaModelGroupDefPtr) item)->name);
1332: case XML_SCHEMA_TYPE_IDC_KEY:
1333: case XML_SCHEMA_TYPE_IDC_UNIQUE:
1334: case XML_SCHEMA_TYPE_IDC_KEYREF:
1335: return (((xmlSchemaIDCPtr) item)->name);
1336: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1337: if (WXS_ATTRUSE_DECL(item) != NULL) {
1338: return(xmlSchemaGetComponentName(
1339: WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1340: } else
1341: return(NULL);
1342: case XML_SCHEMA_EXTRA_QNAMEREF:
1343: return (((xmlSchemaQNameRefPtr) item)->name);
1344: case XML_SCHEMA_TYPE_NOTATION:
1345: return (((xmlSchemaNotationPtr) item)->name);
1346: default:
1347: /*
1348: * Other components cannot have names.
1349: */
1350: break;
1351: }
1352: return (NULL);
1353: }
1354:
1355: #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1356: #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1357: /*
1358: static const xmlChar *
1359: xmlSchemaGetQNameRefName(void *ref)
1360: {
1361: return(((xmlSchemaQNameRefPtr) ref)->name);
1362: }
1363:
1364: static const xmlChar *
1365: xmlSchemaGetQNameRefTargetNs(void *ref)
1366: {
1367: return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1368: }
1369: */
1370:
1371: static const xmlChar *
1372: xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1373: {
1374: switch (item->type) {
1375: case XML_SCHEMA_TYPE_ELEMENT:
1376: return (((xmlSchemaElementPtr) item)->targetNamespace);
1377: case XML_SCHEMA_TYPE_ATTRIBUTE:
1378: return (((xmlSchemaAttributePtr) item)->targetNamespace);
1379: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1380: return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1381: case XML_SCHEMA_TYPE_BASIC:
1382: return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1383: case XML_SCHEMA_TYPE_SIMPLE:
1384: case XML_SCHEMA_TYPE_COMPLEX:
1385: return (((xmlSchemaTypePtr) item)->targetNamespace);
1386: case XML_SCHEMA_TYPE_GROUP:
1387: return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1388: case XML_SCHEMA_TYPE_IDC_KEY:
1389: case XML_SCHEMA_TYPE_IDC_UNIQUE:
1390: case XML_SCHEMA_TYPE_IDC_KEYREF:
1391: return (((xmlSchemaIDCPtr) item)->targetNamespace);
1392: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1393: if (WXS_ATTRUSE_DECL(item) != NULL) {
1394: return(xmlSchemaGetComponentTargetNs(
1395: WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1396: }
1397: /* TODO: Will returning NULL break something? */
1398: break;
1399: case XML_SCHEMA_EXTRA_QNAMEREF:
1400: return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1401: case XML_SCHEMA_TYPE_NOTATION:
1402: return (((xmlSchemaNotationPtr) item)->targetNamespace);
1403: default:
1404: /*
1405: * Other components cannot have names.
1406: */
1407: break;
1408: }
1409: return (NULL);
1410: }
1411:
1412: static const xmlChar*
1413: xmlSchemaGetComponentQName(xmlChar **buf,
1414: void *item)
1415: {
1416: return (xmlSchemaFormatQName(buf,
1417: xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1418: xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1419: }
1420:
1421: static const xmlChar*
1422: xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1423: {
1424: xmlChar *str = NULL;
1425:
1426: *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1427: *buf = xmlStrcat(*buf, BAD_CAST " '");
1428: *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1429: (xmlSchemaBasicItemPtr) item));
1430: *buf = xmlStrcat(*buf, BAD_CAST "'");
1431: FREE_AND_NULL(str);
1432: return(*buf);
1433: }
1434:
1435: static const xmlChar*
1436: xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1437: {
1438: return(xmlSchemaGetComponentDesignation(buf, idc));
1439: }
1440:
1441: /**
1442: * xmlSchemaWildcardPCToString:
1443: * @pc: the type of processContents
1444: *
1445: * Returns a string representation of the type of
1446: * processContents.
1447: */
1448: static const xmlChar *
1449: xmlSchemaWildcardPCToString(int pc)
1450: {
1451: switch (pc) {
1452: case XML_SCHEMAS_ANY_SKIP:
1453: return (BAD_CAST "skip");
1454: case XML_SCHEMAS_ANY_LAX:
1455: return (BAD_CAST "lax");
1456: case XML_SCHEMAS_ANY_STRICT:
1457: return (BAD_CAST "strict");
1458: default:
1459: return (BAD_CAST "invalid process contents");
1460: }
1461: }
1462:
1463: /**
1464: * xmlSchemaGetCanonValueWhtspExt:
1465: * @val: the precomputed value
1466: * @retValue: the returned value
1467: * @ws: the whitespace type of the value
1468: *
1469: * Get a the cononical representation of the value.
1470: * The caller has to free the returned retValue.
1471: *
1472: * Returns 0 if the value could be built and -1 in case of
1473: * API errors or if the value type is not supported yet.
1474: */
1475: static int
1476: xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1477: xmlSchemaWhitespaceValueType ws,
1478: xmlChar **retValue)
1479: {
1480: int list;
1481: xmlSchemaValType valType;
1482: const xmlChar *value, *value2 = NULL;
1483:
1484:
1485: if ((retValue == NULL) || (val == NULL))
1486: return (-1);
1487: list = xmlSchemaValueGetNext(val) ? 1 : 0;
1488: *retValue = NULL;
1489: do {
1490: value = NULL;
1491: valType = xmlSchemaGetValType(val);
1492: switch (valType) {
1493: case XML_SCHEMAS_STRING:
1494: case XML_SCHEMAS_NORMSTRING:
1495: case XML_SCHEMAS_ANYSIMPLETYPE:
1496: value = xmlSchemaValueGetAsString(val);
1497: if (value != NULL) {
1498: if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1499: value2 = xmlSchemaCollapseString(value);
1500: else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1501: value2 = xmlSchemaWhiteSpaceReplace(value);
1502: if (value2 != NULL)
1503: value = value2;
1504: }
1505: break;
1506: default:
1507: if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1508: if (value2 != NULL)
1509: xmlFree((xmlChar *) value2);
1510: goto internal_error;
1511: }
1512: value = value2;
1513: }
1514: if (*retValue == NULL)
1515: if (value == NULL) {
1516: if (! list)
1517: *retValue = xmlStrdup(BAD_CAST "");
1518: } else
1519: *retValue = xmlStrdup(value);
1520: else if (value != NULL) {
1521: /* List. */
1522: *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1523: *retValue = xmlStrcat((xmlChar *) *retValue, value);
1524: }
1525: FREE_AND_NULL(value2)
1526: val = xmlSchemaValueGetNext(val);
1527: } while (val != NULL);
1528:
1529: return (0);
1530: internal_error:
1531: if (*retValue != NULL)
1532: xmlFree((xmlChar *) (*retValue));
1533: if (value2 != NULL)
1534: xmlFree((xmlChar *) value2);
1535: return (-1);
1536: }
1537:
1538: /**
1539: * xmlSchemaFormatItemForReport:
1540: * @buf: the string buffer
1541: * @itemDes: the designation of the item
1542: * @itemName: the name of the item
1543: * @item: the item as an object
1544: * @itemNode: the node of the item
1545: * @local: the local name
1546: * @parsing: if the function is used during the parse
1547: *
1548: * Returns a representation of the given item used
1549: * for error reports.
1550: *
1551: * The following order is used to build the resulting
1552: * designation if the arguments are not NULL:
1553: * 1a. If itemDes not NULL -> itemDes
1554: * 1b. If (itemDes not NULL) and (itemName not NULL)
1555: * -> itemDes + itemName
1556: * 2. If the preceding was NULL and (item not NULL) -> item
1557: * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1558: *
1559: * If the itemNode is an attribute node, the name of the attribute
1560: * will be appended to the result.
1561: *
1562: * Returns the formatted string and sets @buf to the resulting value.
1563: */
1564: static xmlChar*
1565: xmlSchemaFormatItemForReport(xmlChar **buf,
1566: const xmlChar *itemDes,
1567: xmlSchemaBasicItemPtr item,
1568: xmlNodePtr itemNode)
1569: {
1570: xmlChar *str = NULL;
1571: int named = 1;
1572:
1573: if (*buf != NULL) {
1574: xmlFree(*buf);
1575: *buf = NULL;
1576: }
1577:
1578: if (itemDes != NULL) {
1579: *buf = xmlStrdup(itemDes);
1580: } else if (item != NULL) {
1581: switch (item->type) {
1582: case XML_SCHEMA_TYPE_BASIC: {
1583: xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1584:
1585: if (WXS_IS_ATOMIC(type))
1586: *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1587: else if (WXS_IS_LIST(type))
1588: *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1589: else if (WXS_IS_UNION(type))
1590: *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1591: else
1592: *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1593: *buf = xmlStrcat(*buf, type->name);
1594: *buf = xmlStrcat(*buf, BAD_CAST "'");
1595: }
1596: break;
1597: case XML_SCHEMA_TYPE_SIMPLE: {
1598: xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1599:
1600: if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1601: *buf = xmlStrdup(BAD_CAST"");
1602: } else {
1603: *buf = xmlStrdup(BAD_CAST "local ");
1604: }
1605: if (WXS_IS_ATOMIC(type))
1606: *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1607: else if (WXS_IS_LIST(type))
1608: *buf = xmlStrcat(*buf, BAD_CAST "list type");
1609: else if (WXS_IS_UNION(type))
1610: *buf = xmlStrcat(*buf, BAD_CAST "union type");
1611: else
1612: *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1613: if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1614: *buf = xmlStrcat(*buf, BAD_CAST " '");
1615: *buf = xmlStrcat(*buf, type->name);
1616: *buf = xmlStrcat(*buf, BAD_CAST "'");
1617: }
1618: }
1619: break;
1620: case XML_SCHEMA_TYPE_COMPLEX: {
1621: xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1622:
1623: if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1624: *buf = xmlStrdup(BAD_CAST "");
1625: else
1626: *buf = xmlStrdup(BAD_CAST "local ");
1627: *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1628: if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1629: *buf = xmlStrcat(*buf, BAD_CAST " '");
1630: *buf = xmlStrcat(*buf, type->name);
1631: *buf = xmlStrcat(*buf, BAD_CAST "'");
1632: }
1633: }
1634: break;
1635: case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1636: xmlSchemaAttributeUsePtr ause;
1637:
1638: ause = WXS_ATTR_USE_CAST item;
1639: *buf = xmlStrdup(BAD_CAST "attribute use ");
1640: if (WXS_ATTRUSE_DECL(ause) != NULL) {
1641: *buf = xmlStrcat(*buf, BAD_CAST "'");
1642: *buf = xmlStrcat(*buf,
1643: xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1644: FREE_AND_NULL(str)
1645: *buf = xmlStrcat(*buf, BAD_CAST "'");
1646: } else {
1647: *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1648: }
1649: }
1650: break;
1651: case XML_SCHEMA_TYPE_ATTRIBUTE: {
1652: xmlSchemaAttributePtr attr;
1653:
1654: attr = (xmlSchemaAttributePtr) item;
1655: *buf = xmlStrdup(BAD_CAST "attribute decl.");
1656: *buf = xmlStrcat(*buf, BAD_CAST " '");
1657: *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1658: attr->targetNamespace, attr->name));
1659: FREE_AND_NULL(str)
1660: *buf = xmlStrcat(*buf, BAD_CAST "'");
1661: }
1662: break;
1663: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1664: xmlSchemaGetComponentDesignation(buf, item);
1665: break;
1666: case XML_SCHEMA_TYPE_ELEMENT: {
1667: xmlSchemaElementPtr elem;
1668:
1669: elem = (xmlSchemaElementPtr) item;
1670: *buf = xmlStrdup(BAD_CAST "element decl.");
1671: *buf = xmlStrcat(*buf, BAD_CAST " '");
1672: *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1673: elem->targetNamespace, elem->name));
1674: *buf = xmlStrcat(*buf, BAD_CAST "'");
1675: }
1676: break;
1677: case XML_SCHEMA_TYPE_IDC_UNIQUE:
1678: case XML_SCHEMA_TYPE_IDC_KEY:
1679: case XML_SCHEMA_TYPE_IDC_KEYREF:
1680: if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1681: *buf = xmlStrdup(BAD_CAST "unique '");
1682: else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1683: *buf = xmlStrdup(BAD_CAST "key '");
1684: else
1685: *buf = xmlStrdup(BAD_CAST "keyRef '");
1686: *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1687: *buf = xmlStrcat(*buf, BAD_CAST "'");
1688: break;
1689: case XML_SCHEMA_TYPE_ANY:
1690: case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1691: *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1692: ((xmlSchemaWildcardPtr) item)->processContents));
1693: *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1694: break;
1695: case XML_SCHEMA_FACET_MININCLUSIVE:
1696: case XML_SCHEMA_FACET_MINEXCLUSIVE:
1697: case XML_SCHEMA_FACET_MAXINCLUSIVE:
1698: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1699: case XML_SCHEMA_FACET_TOTALDIGITS:
1700: case XML_SCHEMA_FACET_FRACTIONDIGITS:
1701: case XML_SCHEMA_FACET_PATTERN:
1702: case XML_SCHEMA_FACET_ENUMERATION:
1703: case XML_SCHEMA_FACET_WHITESPACE:
1704: case XML_SCHEMA_FACET_LENGTH:
1705: case XML_SCHEMA_FACET_MAXLENGTH:
1706: case XML_SCHEMA_FACET_MINLENGTH:
1707: *buf = xmlStrdup(BAD_CAST "facet '");
1708: *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1709: *buf = xmlStrcat(*buf, BAD_CAST "'");
1710: break;
1711: case XML_SCHEMA_TYPE_GROUP: {
1712: *buf = xmlStrdup(BAD_CAST "model group def.");
1713: *buf = xmlStrcat(*buf, BAD_CAST " '");
1714: *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1715: *buf = xmlStrcat(*buf, BAD_CAST "'");
1716: FREE_AND_NULL(str)
1717: }
1718: break;
1719: case XML_SCHEMA_TYPE_SEQUENCE:
1720: case XML_SCHEMA_TYPE_CHOICE:
1721: case XML_SCHEMA_TYPE_ALL:
1722: case XML_SCHEMA_TYPE_PARTICLE:
1723: *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1724: break;
1725: case XML_SCHEMA_TYPE_NOTATION: {
1726: *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1727: *buf = xmlStrcat(*buf, BAD_CAST " '");
1728: *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1729: *buf = xmlStrcat(*buf, BAD_CAST "'");
1730: FREE_AND_NULL(str);
1731: }
1732: default:
1733: named = 0;
1734: }
1735: } else
1736: named = 0;
1737:
1738: if ((named == 0) && (itemNode != NULL)) {
1739: xmlNodePtr elem;
1740:
1741: if (itemNode->type == XML_ATTRIBUTE_NODE)
1742: elem = itemNode->parent;
1743: else
1744: elem = itemNode;
1745: *buf = xmlStrdup(BAD_CAST "Element '");
1746: if (elem->ns != NULL) {
1747: *buf = xmlStrcat(*buf,
1748: xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1749: FREE_AND_NULL(str)
1750: } else
1751: *buf = xmlStrcat(*buf, elem->name);
1752: *buf = xmlStrcat(*buf, BAD_CAST "'");
1753:
1754: }
1755: if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1756: *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1757: if (itemNode->ns != NULL) {
1758: *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1759: itemNode->ns->href, itemNode->name));
1760: FREE_AND_NULL(str)
1761: } else
1762: *buf = xmlStrcat(*buf, itemNode->name);
1763: *buf = xmlStrcat(*buf, BAD_CAST "'");
1764: }
1765: FREE_AND_NULL(str)
1766:
1767: return (*buf);
1768: }
1769:
1770: /**
1771: * xmlSchemaFormatFacetEnumSet:
1772: * @buf: the string buffer
1773: * @type: the type holding the enumeration facets
1774: *
1775: * Builds a string consisting of all enumeration elements.
1776: *
1777: * Returns a string of all enumeration elements.
1778: */
1779: static const xmlChar *
1780: xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1781: xmlChar **buf, xmlSchemaTypePtr type)
1782: {
1783: xmlSchemaFacetPtr facet;
1784: xmlSchemaWhitespaceValueType ws;
1785: xmlChar *value = NULL;
1786: int res, found = 0;
1787:
1788: if (*buf != NULL)
1789: xmlFree(*buf);
1790: *buf = NULL;
1791:
1792: do {
1793: /*
1794: * Use the whitespace type of the base type.
1795: */
1796: ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1797: for (facet = type->facets; facet != NULL; facet = facet->next) {
1798: if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1799: continue;
1800: found = 1;
1801: res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1802: ws, &value);
1803: if (res == -1) {
1804: xmlSchemaInternalErr(actxt,
1805: "xmlSchemaFormatFacetEnumSet",
1806: "compute the canonical lexical representation");
1807: if (*buf != NULL)
1808: xmlFree(*buf);
1809: *buf = NULL;
1810: return (NULL);
1811: }
1812: if (*buf == NULL)
1813: *buf = xmlStrdup(BAD_CAST "'");
1814: else
1815: *buf = xmlStrcat(*buf, BAD_CAST ", '");
1816: *buf = xmlStrcat(*buf, BAD_CAST value);
1817: *buf = xmlStrcat(*buf, BAD_CAST "'");
1818: if (value != NULL) {
1819: xmlFree((xmlChar *)value);
1820: value = NULL;
1821: }
1822: }
1823: /*
1824: * The enumeration facet of a type restricts the enumeration
1825: * facet of the ancestor type; i.e., such restricted enumerations
1826: * do not belong to the set of the given type. Thus we break
1827: * on the first found enumeration.
1828: */
1829: if (found)
1830: break;
1831: type = type->baseType;
1832: } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1833:
1834: return ((const xmlChar *) *buf);
1835: }
1836:
1837: /************************************************************************
1838: * *
1839: * Error functions *
1840: * *
1841: ************************************************************************/
1842:
1843: #if 0
1844: static void
1845: xmlSchemaErrMemory(const char *msg)
1846: {
1847: __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1848: msg);
1849: }
1850: #endif
1851:
1852: static void
1853: xmlSchemaPSimpleErr(const char *msg)
1854: {
1855: __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1856: msg);
1857: }
1858:
1859: /**
1860: * xmlSchemaPErrMemory:
1861: * @node: a context node
1862: * @extra: extra informations
1863: *
1864: * Handle an out of memory condition
1865: */
1866: static void
1867: xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1868: const char *extra, xmlNodePtr node)
1869: {
1870: if (ctxt != NULL)
1871: ctxt->nberrors++;
1872: __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1873: extra);
1874: }
1875:
1876: /**
1877: * xmlSchemaPErr:
1878: * @ctxt: the parsing context
1879: * @node: the context node
1880: * @error: the error code
1881: * @msg: the error message
1882: * @str1: extra data
1883: * @str2: extra data
1884: *
1885: * Handle a parser error
1886: */
1887: static void
1888: xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1889: const char *msg, const xmlChar * str1, const xmlChar * str2)
1890: {
1891: xmlGenericErrorFunc channel = NULL;
1892: xmlStructuredErrorFunc schannel = NULL;
1893: void *data = NULL;
1894:
1895: if (ctxt != NULL) {
1896: ctxt->nberrors++;
1897: ctxt->err = error;
1898: channel = ctxt->error;
1899: data = ctxt->errCtxt;
1900: schannel = ctxt->serror;
1901: }
1902: __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1903: error, XML_ERR_ERROR, NULL, 0,
1904: (const char *) str1, (const char *) str2, NULL, 0, 0,
1905: msg, str1, str2);
1906: }
1907:
1908: /**
1909: * xmlSchemaPErr2:
1910: * @ctxt: the parsing context
1911: * @node: the context node
1912: * @node: the current child
1913: * @error: the error code
1914: * @msg: the error message
1915: * @str1: extra data
1916: * @str2: extra data
1917: *
1918: * Handle a parser error
1919: */
1920: static void
1921: xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1922: xmlNodePtr child, int error,
1923: const char *msg, const xmlChar * str1, const xmlChar * str2)
1924: {
1925: if (child != NULL)
1926: xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1927: else
1928: xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1929: }
1930:
1931:
1932: /**
1933: * xmlSchemaPErrExt:
1934: * @ctxt: the parsing context
1935: * @node: the context node
1936: * @error: the error code
1937: * @strData1: extra data
1938: * @strData2: extra data
1939: * @strData3: extra data
1940: * @msg: the message
1941: * @str1: extra parameter for the message display
1942: * @str2: extra parameter for the message display
1943: * @str3: extra parameter for the message display
1944: * @str4: extra parameter for the message display
1945: * @str5: extra parameter for the message display
1946: *
1947: * Handle a parser error
1948: */
1949: static void
1950: xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1951: const xmlChar * strData1, const xmlChar * strData2,
1952: const xmlChar * strData3, const char *msg, const xmlChar * str1,
1953: const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1954: const xmlChar * str5)
1955: {
1956:
1957: xmlGenericErrorFunc channel = NULL;
1958: xmlStructuredErrorFunc schannel = NULL;
1959: void *data = NULL;
1960:
1961: if (ctxt != NULL) {
1962: ctxt->nberrors++;
1963: ctxt->err = error;
1964: channel = ctxt->error;
1965: data = ctxt->errCtxt;
1966: schannel = ctxt->serror;
1967: }
1968: __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1969: error, XML_ERR_ERROR, NULL, 0,
1970: (const char *) strData1, (const char *) strData2,
1971: (const char *) strData3, 0, 0, msg, str1, str2,
1972: str3, str4, str5);
1973: }
1974:
1975: /************************************************************************
1976: * *
1977: * Allround error functions *
1978: * *
1979: ************************************************************************/
1980:
1981: /**
1982: * xmlSchemaVTypeErrMemory:
1983: * @node: a context node
1984: * @extra: extra informations
1985: *
1986: * Handle an out of memory condition
1987: */
1988: static void
1989: xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1990: const char *extra, xmlNodePtr node)
1991: {
1992: if (ctxt != NULL) {
1993: ctxt->nberrors++;
1994: ctxt->err = XML_SCHEMAV_INTERNAL;
1995: }
1996: __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1997: extra);
1998: }
1999:
2000: static void
2001: xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2002: const char *msg, const xmlChar *str)
2003: {
2004: __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2005: msg, (const char *) str);
2006: }
2007:
2008: #define WXS_ERROR_TYPE_ERROR 1
2009: #define WXS_ERROR_TYPE_WARNING 2
2010: /**
2011: * xmlSchemaErr3:
2012: * @ctxt: the validation context
2013: * @node: the context node
2014: * @error: the error code
2015: * @msg: the error message
2016: * @str1: extra data
2017: * @str2: extra data
2018: * @str3: extra data
2019: *
2020: * Handle a validation error
2021: */
2022: static void
2023: xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2024: xmlErrorLevel errorLevel,
2025: int error, xmlNodePtr node, int line, const char *msg,
2026: const xmlChar *str1, const xmlChar *str2,
2027: const xmlChar *str3, const xmlChar *str4)
2028: {
2029: xmlStructuredErrorFunc schannel = NULL;
2030: xmlGenericErrorFunc channel = NULL;
2031: void *data = NULL;
2032:
2033: if (ctxt != NULL) {
2034: if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2035: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2036: const char *file = NULL;
2037: if (errorLevel != XML_ERR_WARNING) {
2038: vctxt->nberrors++;
2039: vctxt->err = error;
2040: channel = vctxt->error;
2041: } else {
2042: channel = vctxt->warning;
2043: }
2044: schannel = vctxt->serror;
2045: data = vctxt->errCtxt;
2046:
2047: /*
2048: * Error node. If we specify a line number, then
2049: * do not channel any node to the error function.
2050: */
2051: if (line == 0) {
2052: if ((node == NULL) &&
2053: (vctxt->depth >= 0) &&
2054: (vctxt->inode != NULL)) {
2055: node = vctxt->inode->node;
2056: }
2057: /*
2058: * Get filename and line if no node-tree.
2059: */
2060: if ((node == NULL) &&
2061: (vctxt->parserCtxt != NULL) &&
2062: (vctxt->parserCtxt->input != NULL)) {
2063: file = vctxt->parserCtxt->input->filename;
2064: line = vctxt->parserCtxt->input->line;
2065: }
2066: } else {
2067: /*
2068: * Override the given node's (if any) position
2069: * and channel only the given line number.
2070: */
2071: node = NULL;
2072: /*
2073: * Get filename.
2074: */
2075: if (vctxt->doc != NULL)
2076: file = (const char *) vctxt->doc->URL;
2077: else if ((vctxt->parserCtxt != NULL) &&
2078: (vctxt->parserCtxt->input != NULL))
2079: file = vctxt->parserCtxt->input->filename;
2080: }
2081: __xmlRaiseError(schannel, channel, data, ctxt,
2082: node, XML_FROM_SCHEMASV,
2083: error, errorLevel, file, line,
2084: (const char *) str1, (const char *) str2,
2085: (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2086:
2087: } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2088: xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2089: if (errorLevel != XML_ERR_WARNING) {
2090: pctxt->nberrors++;
2091: pctxt->err = error;
2092: channel = pctxt->error;
2093: } else {
2094: channel = pctxt->warning;
2095: }
2096: schannel = pctxt->serror;
2097: data = pctxt->errCtxt;
2098: __xmlRaiseError(schannel, channel, data, ctxt,
2099: node, XML_FROM_SCHEMASP, error,
2100: errorLevel, NULL, 0,
2101: (const char *) str1, (const char *) str2,
2102: (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2103: } else {
2104: TODO
2105: }
2106: }
2107: }
2108:
2109: /**
2110: * xmlSchemaErr3:
2111: * @ctxt: the validation context
2112: * @node: the context node
2113: * @error: the error code
2114: * @msg: the error message
2115: * @str1: extra data
2116: * @str2: extra data
2117: * @str3: extra data
2118: *
2119: * Handle a validation error
2120: */
2121: static void
2122: xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2123: int error, xmlNodePtr node, const char *msg,
2124: const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2125: {
2126: xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2127: msg, str1, str2, str3, NULL);
2128: }
2129:
2130: static void
2131: xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2132: int error, xmlNodePtr node, const char *msg,
2133: const xmlChar *str1, const xmlChar *str2,
2134: const xmlChar *str3, const xmlChar *str4)
2135: {
2136: xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2137: msg, str1, str2, str3, str4);
2138: }
2139:
2140: static void
2141: xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2142: int error, xmlNodePtr node, const char *msg,
2143: const xmlChar *str1, const xmlChar *str2)
2144: {
2145: xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2146: }
2147:
2148: static xmlChar *
2149: xmlSchemaFormatNodeForError(xmlChar ** msg,
2150: xmlSchemaAbstractCtxtPtr actxt,
2151: xmlNodePtr node)
2152: {
2153: xmlChar *str = NULL;
2154:
2155: *msg = NULL;
2156: if ((node != NULL) &&
2157: (node->type != XML_ELEMENT_NODE) &&
2158: (node->type != XML_ATTRIBUTE_NODE))
2159: {
2160: /*
2161: * Don't try to format other nodes than element and
2162: * attribute nodes.
2163: * Play save and return an empty string.
2164: */
2165: *msg = xmlStrdup(BAD_CAST "");
2166: return(*msg);
2167: }
2168: if (node != NULL) {
2169: /*
2170: * Work on tree nodes.
2171: */
2172: if (node->type == XML_ATTRIBUTE_NODE) {
2173: xmlNodePtr elem = node->parent;
2174:
2175: *msg = xmlStrdup(BAD_CAST "Element '");
2176: if (elem->ns != NULL)
2177: *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2178: elem->ns->href, elem->name));
2179: else
2180: *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2181: NULL, elem->name));
2182: FREE_AND_NULL(str);
2183: *msg = xmlStrcat(*msg, BAD_CAST "', ");
2184: *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2185: } else {
2186: *msg = xmlStrdup(BAD_CAST "Element '");
2187: }
2188: if (node->ns != NULL)
2189: *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2190: node->ns->href, node->name));
2191: else
2192: *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2193: NULL, node->name));
2194: FREE_AND_NULL(str);
2195: *msg = xmlStrcat(*msg, BAD_CAST "': ");
2196: } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2197: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2198: /*
2199: * Work on node infos.
2200: */
2201: if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2202: xmlSchemaNodeInfoPtr ielem =
2203: vctxt->elemInfos[vctxt->depth];
2204:
2205: *msg = xmlStrdup(BAD_CAST "Element '");
2206: *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2207: ielem->nsName, ielem->localName));
2208: FREE_AND_NULL(str);
2209: *msg = xmlStrcat(*msg, BAD_CAST "', ");
2210: *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2211: } else {
2212: *msg = xmlStrdup(BAD_CAST "Element '");
2213: }
2214: *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2215: vctxt->inode->nsName, vctxt->inode->localName));
2216: FREE_AND_NULL(str);
2217: *msg = xmlStrcat(*msg, BAD_CAST "': ");
2218: } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2219: /*
2220: * Hmm, no node while parsing?
2221: * Return an empty string, in case NULL will break something.
2222: */
2223: *msg = xmlStrdup(BAD_CAST "");
2224: } else {
2225: TODO
2226: return (NULL);
2227: }
2228: /*
2229: * VAL TODO: The output of the given schema component is currently
2230: * disabled.
2231: */
2232: #if 0
2233: if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2234: *msg = xmlStrcat(*msg, BAD_CAST " [");
2235: *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2236: NULL, type, NULL, 0));
2237: FREE_AND_NULL(str)
2238: *msg = xmlStrcat(*msg, BAD_CAST "]");
2239: }
2240: #endif
2241: return (*msg);
2242: }
2243:
2244: static void
2245: xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2246: const char *funcName,
2247: const char *message,
2248: const xmlChar *str1,
2249: const xmlChar *str2)
2250: {
2251: xmlChar *msg = NULL;
2252:
2253: if (actxt == NULL)
2254: return;
2255: msg = xmlStrdup(BAD_CAST "Internal error: ");
2256: msg = xmlStrcat(msg, BAD_CAST funcName);
2257: msg = xmlStrcat(msg, BAD_CAST ", ");
2258: msg = xmlStrcat(msg, BAD_CAST message);
2259: msg = xmlStrcat(msg, BAD_CAST ".\n");
2260:
2261: if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2262: xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
2263: (const char *) msg, str1, str2);
2264:
2265: else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2266: xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
2267: (const char *) msg, str1, str2);
2268:
2269: FREE_AND_NULL(msg)
2270: }
2271:
2272: static void
2273: xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2274: const char *funcName,
2275: const char *message)
2276: {
2277: xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2278: }
2279:
2280: #if 0
2281: static void
2282: xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2283: const char *funcName,
2284: const char *message,
2285: const xmlChar *str1,
2286: const xmlChar *str2)
2287: {
2288: xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2289: str1, str2);
2290: }
2291: #endif
2292:
2293: static void
2294: xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2295: xmlParserErrors error,
2296: xmlNodePtr node,
2297: xmlSchemaBasicItemPtr item,
2298: const char *message,
2299: const xmlChar *str1, const xmlChar *str2,
2300: const xmlChar *str3, const xmlChar *str4)
2301: {
2302: xmlChar *msg = NULL;
2303:
2304: if ((node == NULL) && (item != NULL) &&
2305: (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2306: node = WXS_ITEM_NODE(item);
2307: xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2308: msg = xmlStrcat(msg, BAD_CAST ": ");
2309: } else
2310: xmlSchemaFormatNodeForError(&msg, actxt, node);
2311: msg = xmlStrcat(msg, (const xmlChar *) message);
2312: msg = xmlStrcat(msg, BAD_CAST ".\n");
2313: xmlSchemaErr4(actxt, error, node,
2314: (const char *) msg, str1, str2, str3, str4);
2315: FREE_AND_NULL(msg)
2316: }
2317:
2318: static void
2319: xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2320: xmlParserErrors error,
2321: xmlNodePtr node,
2322: xmlSchemaBasicItemPtr item,
2323: const char *message,
2324: const xmlChar *str1,
2325: const xmlChar *str2)
2326: {
2327: xmlSchemaCustomErr4(actxt, error, node, item,
2328: message, str1, str2, NULL, NULL);
2329: }
2330:
2331:
2332:
2333: static void
2334: xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2335: xmlParserErrors error,
2336: xmlNodePtr node,
2337: xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2338: const char *message,
2339: const xmlChar *str1,
2340: const xmlChar *str2,
2341: const xmlChar *str3)
2342: {
2343: xmlChar *msg = NULL;
2344:
2345: xmlSchemaFormatNodeForError(&msg, actxt, node);
2346: msg = xmlStrcat(msg, (const xmlChar *) message);
2347: msg = xmlStrcat(msg, BAD_CAST ".\n");
2348:
2349: /* URGENT TODO: Set the error code to something sane. */
2350: xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2351: (const char *) msg, str1, str2, str3, NULL);
2352:
2353: FREE_AND_NULL(msg)
2354: }
2355:
2356:
2357:
2358: static void
2359: xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2360: xmlParserErrors error,
2361: xmlSchemaPSVIIDCNodePtr idcNode,
2362: xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2363: const char *message,
2364: const xmlChar *str1,
2365: const xmlChar *str2)
2366: {
2367: xmlChar *msg = NULL, *qname = NULL;
2368:
2369: msg = xmlStrdup(BAD_CAST "Element '%s': ");
2370: msg = xmlStrcat(msg, (const xmlChar *) message);
2371: msg = xmlStrcat(msg, BAD_CAST ".\n");
2372: xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2373: error, NULL, idcNode->nodeLine, (const char *) msg,
2374: xmlSchemaFormatQName(&qname,
2375: vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2376: vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2377: str1, str2, NULL);
2378: FREE_AND_NULL(qname);
2379: FREE_AND_NULL(msg);
2380: }
2381:
2382: static int
2383: xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2384: xmlNodePtr node)
2385: {
2386: if (node != NULL)
2387: return (node->type);
2388: if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2389: (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2390: return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2391: return (-1);
2392: }
2393:
2394: static int
2395: xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2396: {
2397: switch (item->type) {
2398: case XML_SCHEMA_TYPE_COMPLEX:
2399: case XML_SCHEMA_TYPE_SIMPLE:
2400: if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2401: return(1);
2402: break;
2403: case XML_SCHEMA_TYPE_GROUP:
2404: return (1);
2405: case XML_SCHEMA_TYPE_ELEMENT:
2406: if ( ((xmlSchemaElementPtr) item)->flags &
2407: XML_SCHEMAS_ELEM_GLOBAL)
2408: return(1);
2409: break;
2410: case XML_SCHEMA_TYPE_ATTRIBUTE:
2411: if ( ((xmlSchemaAttributePtr) item)->flags &
2412: XML_SCHEMAS_ATTR_GLOBAL)
2413: return(1);
2414: break;
2415: /* Note that attribute groups are always global. */
2416: default:
2417: return(1);
2418: }
2419: return (0);
2420: }
2421:
2422: static void
2423: xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2424: xmlParserErrors error,
2425: xmlNodePtr node,
2426: const xmlChar *value,
2427: xmlSchemaTypePtr type,
2428: int displayValue)
2429: {
2430: xmlChar *msg = NULL;
2431:
2432: xmlSchemaFormatNodeForError(&msg, actxt, node);
2433:
2434: if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2435: XML_ATTRIBUTE_NODE))
2436: msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2437: else
2438: msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2439: "value of ");
2440:
2441: if (! xmlSchemaIsGlobalItem(type))
2442: msg = xmlStrcat(msg, BAD_CAST "the local ");
2443: else
2444: msg = xmlStrcat(msg, BAD_CAST "the ");
2445:
2446: if (WXS_IS_ATOMIC(type))
2447: msg = xmlStrcat(msg, BAD_CAST "atomic type");
2448: else if (WXS_IS_LIST(type))
2449: msg = xmlStrcat(msg, BAD_CAST "list type");
2450: else if (WXS_IS_UNION(type))
2451: msg = xmlStrcat(msg, BAD_CAST "union type");
2452:
2453: if (xmlSchemaIsGlobalItem(type)) {
2454: xmlChar *str = NULL;
2455: msg = xmlStrcat(msg, BAD_CAST " '");
2456: if (type->builtInType != 0) {
2457: msg = xmlStrcat(msg, BAD_CAST "xs:");
2458: msg = xmlStrcat(msg, type->name);
2459: } else
2460: msg = xmlStrcat(msg,
2461: xmlSchemaFormatQName(&str,
2462: type->targetNamespace, type->name));
2463: msg = xmlStrcat(msg, BAD_CAST "'");
2464: FREE_AND_NULL(str);
2465: }
2466: msg = xmlStrcat(msg, BAD_CAST ".\n");
2467: if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2468: XML_ATTRIBUTE_NODE))
2469: xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2470: else
2471: xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2472: FREE_AND_NULL(msg)
2473: }
2474:
2475: static const xmlChar *
2476: xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2477: xmlSchemaNodeInfoPtr ni,
2478: xmlNodePtr node)
2479: {
2480: if (node != NULL) {
2481: if (node->ns != NULL)
2482: return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2483: else
2484: return (xmlSchemaFormatQName(str, NULL, node->name));
2485: } else if (ni != NULL)
2486: return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2487: return (NULL);
2488: }
2489:
2490: static void
2491: xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2492: xmlParserErrors error,
2493: xmlSchemaAttrInfoPtr ni,
2494: xmlNodePtr node)
2495: {
2496: xmlChar *msg = NULL, *str = NULL;
2497:
2498: xmlSchemaFormatNodeForError(&msg, actxt, node);
2499: msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2500: xmlSchemaErr(actxt, error, node, (const char *) msg,
2501: xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2502: NULL);
2503: FREE_AND_NULL(str)
2504: FREE_AND_NULL(msg)
2505: }
2506:
2507: static void
2508: xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2509: xmlParserErrors error,
2510: xmlNodePtr node,
2511: xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2512: const char *message,
2513: int nbval,
2514: int nbneg,
2515: xmlChar **values)
2516: {
2517: xmlChar *str = NULL, *msg = NULL;
2518: xmlChar *localName, *nsName;
2519: const xmlChar *cur, *end;
2520: int i;
2521:
2522: xmlSchemaFormatNodeForError(&msg, actxt, node);
2523: msg = xmlStrcat(msg, (const xmlChar *) message);
2524: msg = xmlStrcat(msg, BAD_CAST ".");
2525: /*
2526: * Note that is does not make sense to report that we have a
2527: * wildcard here, since the wildcard might be unfolded into
2528: * multiple transitions.
2529: */
2530: if (nbval + nbneg > 0) {
2531: if (nbval + nbneg > 1) {
2532: str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2533: } else
2534: str = xmlStrdup(BAD_CAST " Expected is ( ");
2535: nsName = NULL;
2536:
2537: for (i = 0; i < nbval + nbneg; i++) {
2538: cur = values[i];
2539: if (cur == NULL)
2540: continue;
2541: if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2542: (cur[3] == ' ')) {
2543: cur += 4;
2544: str = xmlStrcat(str, BAD_CAST "##other");
2545: }
2546: /*
2547: * Get the local name.
2548: */
2549: localName = NULL;
2550:
2551: end = cur;
2552: if (*end == '*') {
2553: localName = xmlStrdup(BAD_CAST "*");
2554: end++;
2555: } else {
2556: while ((*end != 0) && (*end != '|'))
2557: end++;
2558: localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2559: }
2560: if (*end != 0) {
2561: end++;
2562: /*
2563: * Skip "*|*" if they come with negated expressions, since
2564: * they represent the same negated wildcard.
2565: */
2566: if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2567: /*
2568: * Get the namespace name.
2569: */
2570: cur = end;
2571: if (*end == '*') {
2572: nsName = xmlStrdup(BAD_CAST "{*}");
2573: } else {
2574: while (*end != 0)
2575: end++;
2576:
2577: if (i >= nbval)
2578: nsName = xmlStrdup(BAD_CAST "{##other:");
2579: else
2580: nsName = xmlStrdup(BAD_CAST "{");
2581:
2582: nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2583: nsName = xmlStrcat(nsName, BAD_CAST "}");
2584: }
2585: str = xmlStrcat(str, BAD_CAST nsName);
2586: FREE_AND_NULL(nsName)
2587: } else {
2588: FREE_AND_NULL(localName);
2589: continue;
2590: }
2591: }
2592: str = xmlStrcat(str, BAD_CAST localName);
2593: FREE_AND_NULL(localName);
2594:
2595: if (i < nbval + nbneg -1)
2596: str = xmlStrcat(str, BAD_CAST ", ");
2597: }
2598: str = xmlStrcat(str, BAD_CAST " ).\n");
2599: msg = xmlStrcat(msg, BAD_CAST str);
2600: FREE_AND_NULL(str)
2601: } else
2602: msg = xmlStrcat(msg, BAD_CAST "\n");
2603: xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2604: xmlFree(msg);
2605: }
2606:
2607: static void
2608: xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2609: xmlParserErrors error,
2610: xmlNodePtr node,
2611: const xmlChar *value,
2612: unsigned long length,
2613: xmlSchemaTypePtr type,
2614: xmlSchemaFacetPtr facet,
2615: const char *message,
2616: const xmlChar *str1,
2617: const xmlChar *str2)
2618: {
2619: xmlChar *str = NULL, *msg = NULL;
2620: xmlSchemaTypeType facetType;
2621: int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2622:
2623: xmlSchemaFormatNodeForError(&msg, actxt, node);
2624: if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2625: facetType = XML_SCHEMA_FACET_ENUMERATION;
2626: /*
2627: * If enumerations are validated, one must not expect the
2628: * facet to be given.
2629: */
2630: } else
2631: facetType = facet->type;
2632: msg = xmlStrcat(msg, BAD_CAST "[");
2633: msg = xmlStrcat(msg, BAD_CAST "facet '");
2634: msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2635: msg = xmlStrcat(msg, BAD_CAST "'] ");
2636: if (message == NULL) {
2637: /*
2638: * Use a default message.
2639: */
2640: if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2641: (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2642: (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2643:
2644: char len[25], actLen[25];
2645:
2646: /* FIXME, TODO: What is the max expected string length of the
2647: * this value?
2648: */
2649: if (nodeType == XML_ATTRIBUTE_NODE)
2650: msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2651: else
2652: msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2653:
2654: snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2655: snprintf(actLen, 24, "%lu", length);
2656:
2657: if (facetType == XML_SCHEMA_FACET_LENGTH)
2658: msg = xmlStrcat(msg,
2659: BAD_CAST "this differs from the allowed length of '%s'.\n");
2660: else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2661: msg = xmlStrcat(msg,
2662: BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2663: else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2664: msg = xmlStrcat(msg,
2665: BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2666:
2667: if (nodeType == XML_ATTRIBUTE_NODE)
2668: xmlSchemaErr3(actxt, error, node, (const char *) msg,
2669: value, (const xmlChar *) actLen, (const xmlChar *) len);
2670: else
2671: xmlSchemaErr(actxt, error, node, (const char *) msg,
2672: (const xmlChar *) actLen, (const xmlChar *) len);
2673:
2674: } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2675: msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2676: "of the set {%s}.\n");
2677: xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2678: xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2679: } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2680: msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2681: "by the pattern '%s'.\n");
2682: xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2683: facet->value);
2684: } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2685: msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2686: "minimum value allowed ('%s').\n");
2687: xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2688: facet->value);
2689: } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2690: msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2691: "maximum value allowed ('%s').\n");
2692: xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2693: facet->value);
2694: } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2695: msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2696: "'%s'.\n");
2697: xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2698: facet->value);
2699: } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2700: msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2701: "'%s'.\n");
2702: xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2703: facet->value);
2704: } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2705: msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2706: "digits than are allowed ('%s').\n");
2707: xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2708: facet->value);
2709: } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2710: msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2711: "digits than are allowed ('%s').\n");
2712: xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2713: facet->value);
2714: } else if (nodeType == XML_ATTRIBUTE_NODE) {
2715: msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2716: xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2717: } else {
2718: msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2719: xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2720: }
2721: } else {
2722: msg = xmlStrcat(msg, (const xmlChar *) message);
2723: msg = xmlStrcat(msg, BAD_CAST ".\n");
2724: xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2725: }
2726: FREE_AND_NULL(str)
2727: xmlFree(msg);
2728: }
2729:
2730: #define VERROR(err, type, msg) \
2731: xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2732:
2733: #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2734:
2735: #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2736: #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2737:
2738: #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2739:
2740:
2741: /**
2742: * xmlSchemaPMissingAttrErr:
2743: * @ctxt: the schema validation context
2744: * @ownerDes: the designation of the owner
2745: * @ownerName: the name of the owner
2746: * @ownerItem: the owner as a schema object
2747: * @ownerElem: the owner as an element node
2748: * @node: the parent element node of the missing attribute node
2749: * @type: the corresponding type of the attribute node
2750: *
2751: * Reports an illegal attribute.
2752: */
2753: static void
2754: xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2755: xmlParserErrors error,
2756: xmlSchemaBasicItemPtr ownerItem,
2757: xmlNodePtr ownerElem,
2758: const char *name,
2759: const char *message)
2760: {
2761: xmlChar *des = NULL;
2762:
2763: xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2764:
2765: if (message != NULL)
2766: xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2767: else
2768: xmlSchemaPErr(ctxt, ownerElem, error,
2769: "%s: The attribute '%s' is required but missing.\n",
2770: BAD_CAST des, BAD_CAST name);
2771: FREE_AND_NULL(des);
2772: }
2773:
2774:
2775: /**
2776: * xmlSchemaPResCompAttrErr:
2777: * @ctxt: the schema validation context
2778: * @error: the error code
2779: * @ownerDes: the designation of the owner
2780: * @ownerItem: the owner as a schema object
2781: * @ownerElem: the owner as an element node
2782: * @name: the name of the attribute holding the QName
2783: * @refName: the referenced local name
2784: * @refURI: the referenced namespace URI
2785: * @message: optional message
2786: *
2787: * Used to report QName attribute values that failed to resolve
2788: * to schema components.
2789: */
2790: static void
2791: xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2792: xmlParserErrors error,
2793: xmlSchemaBasicItemPtr ownerItem,
2794: xmlNodePtr ownerElem,
2795: const char *name,
2796: const xmlChar *refName,
2797: const xmlChar *refURI,
2798: xmlSchemaTypeType refType,
2799: const char *refTypeStr)
2800: {
2801: xmlChar *des = NULL, *strA = NULL;
2802:
2803: xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2804: if (refTypeStr == NULL)
2805: refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2806: xmlSchemaPErrExt(ctxt, ownerElem, error,
2807: NULL, NULL, NULL,
2808: "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2809: "%s.\n", BAD_CAST des, BAD_CAST name,
2810: xmlSchemaFormatQName(&strA, refURI, refName),
2811: BAD_CAST refTypeStr, NULL);
2812: FREE_AND_NULL(des)
2813: FREE_AND_NULL(strA)
2814: }
2815:
2816: /**
2817: * xmlSchemaPCustomAttrErr:
2818: * @ctxt: the schema parser context
2819: * @error: the error code
2820: * @ownerDes: the designation of the owner
2821: * @ownerItem: the owner as a schema object
2822: * @attr: the illegal attribute node
2823: *
2824: * Reports an illegal attribute during the parse.
2825: */
2826: static void
2827: xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2828: xmlParserErrors error,
2829: xmlChar **ownerDes,
2830: xmlSchemaBasicItemPtr ownerItem,
2831: xmlAttrPtr attr,
2832: const char *msg)
2833: {
2834: xmlChar *des = NULL;
2835:
2836: if (ownerDes == NULL)
2837: xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2838: else if (*ownerDes == NULL) {
2839: xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2840: des = *ownerDes;
2841: } else
2842: des = *ownerDes;
2843: if (attr == NULL) {
2844: xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2845: "%s, attribute '%s': %s.\n",
2846: BAD_CAST des, (const xmlChar *) "Unknown",
2847: (const xmlChar *) msg, NULL, NULL);
2848: } else {
2849: xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2850: "%s, attribute '%s': %s.\n",
2851: BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2852: }
2853: if (ownerDes == NULL)
2854: FREE_AND_NULL(des);
2855: }
2856:
2857: /**
2858: * xmlSchemaPIllegalAttrErr:
2859: * @ctxt: the schema parser context
2860: * @error: the error code
2861: * @ownerDes: the designation of the attribute's owner
2862: * @ownerItem: the attribute's owner item
2863: * @attr: the illegal attribute node
2864: *
2865: * Reports an illegal attribute during the parse.
2866: */
2867: static void
2868: xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2869: xmlParserErrors error,
2870: xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2871: xmlAttrPtr attr)
2872: {
2873: xmlChar *strA = NULL, *strB = NULL;
2874:
2875: xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2876: xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2877: "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2878: xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2879: NULL, NULL);
2880: FREE_AND_NULL(strA);
2881: FREE_AND_NULL(strB);
2882: }
2883:
2884: /**
2885: * xmlSchemaPCustomErr:
2886: * @ctxt: the schema parser context
2887: * @error: the error code
2888: * @itemDes: the designation of the schema item
2889: * @item: the schema item
2890: * @itemElem: the node of the schema item
2891: * @message: the error message
2892: * @str1: an optional param for the error message
2893: * @str2: an optional param for the error message
2894: * @str3: an optional param for the error message
2895: *
2896: * Reports an error during parsing.
2897: */
2898: static void
2899: xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2900: xmlParserErrors error,
2901: xmlSchemaBasicItemPtr item,
2902: xmlNodePtr itemElem,
2903: const char *message,
2904: const xmlChar *str1,
2905: const xmlChar *str2,
2906: const xmlChar *str3)
2907: {
2908: xmlChar *des = NULL, *msg = NULL;
2909:
2910: xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2911: msg = xmlStrdup(BAD_CAST "%s: ");
2912: msg = xmlStrcat(msg, (const xmlChar *) message);
2913: msg = xmlStrcat(msg, BAD_CAST ".\n");
2914: if ((itemElem == NULL) && (item != NULL))
2915: itemElem = WXS_ITEM_NODE(item);
2916: xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2917: (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2918: FREE_AND_NULL(des);
2919: FREE_AND_NULL(msg);
2920: }
2921:
2922: /**
2923: * xmlSchemaPCustomErr:
2924: * @ctxt: the schema parser context
2925: * @error: the error code
2926: * @itemDes: the designation of the schema item
2927: * @item: the schema item
2928: * @itemElem: the node of the schema item
2929: * @message: the error message
2930: * @str1: the optional param for the error message
2931: *
2932: * Reports an error during parsing.
2933: */
2934: static void
2935: xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2936: xmlParserErrors error,
2937: xmlSchemaBasicItemPtr item,
2938: xmlNodePtr itemElem,
2939: const char *message,
2940: const xmlChar *str1)
2941: {
2942: xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2943: str1, NULL, NULL);
2944: }
2945:
2946: /**
2947: * xmlSchemaPAttrUseErr:
2948: * @ctxt: the schema parser context
2949: * @error: the error code
2950: * @itemDes: the designation of the schema type
2951: * @item: the schema type
2952: * @itemElem: the node of the schema type
2953: * @attr: the invalid schema attribute
2954: * @message: the error message
2955: * @str1: the optional param for the error message
2956: *
2957: * Reports an attribute use error during parsing.
2958: */
2959: static void
2960: xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
2961: xmlParserErrors error,
2962: xmlNodePtr node,
2963: xmlSchemaBasicItemPtr ownerItem,
2964: const xmlSchemaAttributeUsePtr attruse,
2965: const char *message,
2966: const xmlChar *str1, const xmlChar *str2,
2967: const xmlChar *str3,const xmlChar *str4)
2968: {
2969: xmlChar *str = NULL, *msg = NULL;
2970:
2971: xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2972: msg = xmlStrcat(msg, BAD_CAST ", ");
2973: msg = xmlStrcat(msg,
2974: BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2975: WXS_BASIC_CAST attruse, NULL));
2976: FREE_AND_NULL(str);
2977: msg = xmlStrcat(msg, BAD_CAST ": ");
2978: msg = xmlStrcat(msg, (const xmlChar *) message);
2979: msg = xmlStrcat(msg, BAD_CAST ".\n");
2980: xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2981: (const char *) msg, str1, str2, str3, str4);
2982: xmlFree(msg);
2983: }
2984:
2985: /**
2986: * xmlSchemaPIllegalFacetAtomicErr:
2987: * @ctxt: the schema parser context
2988: * @error: the error code
2989: * @type: the schema type
2990: * @baseType: the base type of type
2991: * @facet: the illegal facet
2992: *
2993: * Reports an illegal facet for atomic simple types.
2994: */
2995: static void
2996: xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
2997: xmlParserErrors error,
2998: xmlSchemaTypePtr type,
2999: xmlSchemaTypePtr baseType,
3000: xmlSchemaFacetPtr facet)
3001: {
3002: xmlChar *des = NULL, *strT = NULL;
3003:
3004: xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3005: xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3006: "%s: The facet '%s' is not allowed on types derived from the "
3007: "type %s.\n",
3008: BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3009: xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3010: NULL, NULL);
3011: FREE_AND_NULL(des);
3012: FREE_AND_NULL(strT);
3013: }
3014:
3015: /**
3016: * xmlSchemaPIllegalFacetListUnionErr:
3017: * @ctxt: the schema parser context
3018: * @error: the error code
3019: * @itemDes: the designation of the schema item involved
3020: * @item: the schema item involved
3021: * @facet: the illegal facet
3022: *
3023: * Reports an illegal facet for <list> and <union>.
3024: */
3025: static void
3026: xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3027: xmlParserErrors error,
3028: xmlSchemaTypePtr type,
3029: xmlSchemaFacetPtr facet)
3030: {
3031: xmlChar *des = NULL;
3032:
3033: xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3034: type->node);
3035: xmlSchemaPErr(ctxt, type->node, error,
3036: "%s: The facet '%s' is not allowed.\n",
3037: BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3038: FREE_AND_NULL(des);
3039: }
3040:
3041: /**
3042: * xmlSchemaPMutualExclAttrErr:
3043: * @ctxt: the schema validation context
3044: * @error: the error code
3045: * @elemDes: the designation of the parent element node
3046: * @attr: the bad attribute node
3047: * @type: the corresponding type of the attribute node
3048: *
3049: * Reports an illegal attribute.
3050: */
3051: static void
3052: xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3053: xmlParserErrors error,
3054: xmlSchemaBasicItemPtr ownerItem,
3055: xmlAttrPtr attr,
3056: const char *name1,
3057: const char *name2)
3058: {
3059: xmlChar *des = NULL;
3060:
3061: xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3062: xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3063: "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3064: BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3065: FREE_AND_NULL(des);
3066: }
3067:
3068: /**
3069: * xmlSchemaPSimpleTypeErr:
3070: * @ctxt: the schema validation context
3071: * @error: the error code
3072: * @type: the type specifier
3073: * @ownerDes: the designation of the owner
3074: * @ownerItem: the schema object if existent
3075: * @node: the validated node
3076: * @value: the validated value
3077: *
3078: * Reports a simple type validation error.
3079: * TODO: Should this report the value of an element as well?
3080: */
3081: static void
3082: xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3083: xmlParserErrors error,
3084: xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3085: xmlNodePtr node,
3086: xmlSchemaTypePtr type,
3087: const char *expected,
3088: const xmlChar *value,
3089: const char *message,
3090: const xmlChar *str1,
3091: const xmlChar *str2)
3092: {
3093: xmlChar *msg = NULL;
3094:
3095: xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3096: if (message == NULL) {
3097: /*
3098: * Use default messages.
3099: */
3100: if (type != NULL) {
3101: if (node->type == XML_ATTRIBUTE_NODE)
3102: msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3103: else
3104: msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3105: "valid value of ");
3106: if (! xmlSchemaIsGlobalItem(type))
3107: msg = xmlStrcat(msg, BAD_CAST "the local ");
3108: else
3109: msg = xmlStrcat(msg, BAD_CAST "the ");
3110:
3111: if (WXS_IS_ATOMIC(type))
3112: msg = xmlStrcat(msg, BAD_CAST "atomic type");
3113: else if (WXS_IS_LIST(type))
3114: msg = xmlStrcat(msg, BAD_CAST "list type");
3115: else if (WXS_IS_UNION(type))
3116: msg = xmlStrcat(msg, BAD_CAST "union type");
3117:
3118: if (xmlSchemaIsGlobalItem(type)) {
3119: xmlChar *str = NULL;
3120: msg = xmlStrcat(msg, BAD_CAST " '");
3121: if (type->builtInType != 0) {
3122: msg = xmlStrcat(msg, BAD_CAST "xs:");
3123: msg = xmlStrcat(msg, type->name);
3124: } else
3125: msg = xmlStrcat(msg,
3126: xmlSchemaFormatQName(&str,
3127: type->targetNamespace, type->name));
3128: msg = xmlStrcat(msg, BAD_CAST "'.");
3129: FREE_AND_NULL(str);
3130: }
3131: } else {
3132: if (node->type == XML_ATTRIBUTE_NODE)
3133: msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3134: else
3135: msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3136: "valid.");
3137: }
3138: if (expected) {
3139: msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3140: msg = xmlStrcat(msg, BAD_CAST expected);
3141: msg = xmlStrcat(msg, BAD_CAST "'.\n");
3142: } else
3143: msg = xmlStrcat(msg, BAD_CAST "\n");
3144: if (node->type == XML_ATTRIBUTE_NODE)
3145: xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3146: else
3147: xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3148: } else {
3149: msg = xmlStrcat(msg, BAD_CAST message);
3150: msg = xmlStrcat(msg, BAD_CAST ".\n");
3151: xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3152: (const char*) msg, str1, str2, NULL, NULL, NULL);
3153: }
3154: /* Cleanup. */
3155: FREE_AND_NULL(msg)
3156: }
3157:
3158: /**
3159: * xmlSchemaPContentErr:
3160: * @ctxt: the schema parser context
3161: * @error: the error code
3162: * @onwerDes: the designation of the holder of the content
3163: * @ownerItem: the owner item of the holder of the content
3164: * @ownerElem: the node of the holder of the content
3165: * @child: the invalid child node
3166: * @message: the optional error message
3167: * @content: the optional string describing the correct content
3168: *
3169: * Reports an error concerning the content of a schema element.
3170: */
3171: static void
3172: xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3173: xmlParserErrors error,
3174: xmlSchemaBasicItemPtr ownerItem,
3175: xmlNodePtr ownerElem,
3176: xmlNodePtr child,
3177: const char *message,
3178: const char *content)
3179: {
3180: xmlChar *des = NULL;
3181:
3182: xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3183: if (message != NULL)
3184: xmlSchemaPErr2(ctxt, ownerElem, child, error,
3185: "%s: %s.\n",
3186: BAD_CAST des, BAD_CAST message);
3187: else {
3188: if (content != NULL) {
3189: xmlSchemaPErr2(ctxt, ownerElem, child, error,
3190: "%s: The content is not valid. Expected is %s.\n",
3191: BAD_CAST des, BAD_CAST content);
3192: } else {
3193: xmlSchemaPErr2(ctxt, ownerElem, child, error,
3194: "%s: The content is not valid.\n",
3195: BAD_CAST des, NULL);
3196: }
3197: }
3198: FREE_AND_NULL(des)
3199: }
3200:
3201: /************************************************************************
3202: * *
3203: * Streamable error functions *
3204: * *
3205: ************************************************************************/
3206:
3207:
3208:
3209:
3210: /************************************************************************
3211: * *
3212: * Validation helper functions *
3213: * *
3214: ************************************************************************/
3215:
3216:
3217: /************************************************************************
3218: * *
3219: * Allocation functions *
3220: * *
3221: ************************************************************************/
3222:
3223: /**
3224: * xmlSchemaNewSchemaForParserCtxt:
3225: * @ctxt: a schema validation context
3226: *
3227: * Allocate a new Schema structure.
3228: *
3229: * Returns the newly allocated structure or NULL in case or error
3230: */
3231: static xmlSchemaPtr
3232: xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3233: {
3234: xmlSchemaPtr ret;
3235:
3236: ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3237: if (ret == NULL) {
3238: xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3239: return (NULL);
3240: }
3241: memset(ret, 0, sizeof(xmlSchema));
3242: ret->dict = ctxt->dict;
3243: xmlDictReference(ret->dict);
3244:
3245: return (ret);
3246: }
3247:
3248: /**
3249: * xmlSchemaNewFacet:
3250: *
3251: * Allocate a new Facet structure.
3252: *
3253: * Returns the newly allocated structure or NULL in case or error
3254: */
3255: xmlSchemaFacetPtr
3256: xmlSchemaNewFacet(void)
3257: {
3258: xmlSchemaFacetPtr ret;
3259:
3260: ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3261: if (ret == NULL) {
3262: return (NULL);
3263: }
3264: memset(ret, 0, sizeof(xmlSchemaFacet));
3265:
3266: return (ret);
3267: }
3268:
3269: /**
3270: * xmlSchemaNewAnnot:
3271: * @ctxt: a schema validation context
3272: * @node: a node
3273: *
3274: * Allocate a new annotation structure.
3275: *
3276: * Returns the newly allocated structure or NULL in case or error
3277: */
3278: static xmlSchemaAnnotPtr
3279: xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3280: {
3281: xmlSchemaAnnotPtr ret;
3282:
3283: ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3284: if (ret == NULL) {
3285: xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3286: return (NULL);
3287: }
3288: memset(ret, 0, sizeof(xmlSchemaAnnot));
3289: ret->content = node;
3290: return (ret);
3291: }
3292:
3293: static xmlSchemaItemListPtr
3294: xmlSchemaItemListCreate(void)
3295: {
3296: xmlSchemaItemListPtr ret;
3297:
3298: ret = xmlMalloc(sizeof(xmlSchemaItemList));
3299: if (ret == NULL) {
3300: xmlSchemaPErrMemory(NULL,
3301: "allocating an item list structure", NULL);
3302: return (NULL);
3303: }
3304: memset(ret, 0, sizeof(xmlSchemaItemList));
3305: return (ret);
3306: }
3307:
3308: static void
3309: xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3310: {
3311: if (list->items != NULL) {
3312: xmlFree(list->items);
3313: list->items = NULL;
3314: }
3315: list->nbItems = 0;
3316: list->sizeItems = 0;
3317: }
3318:
3319: static int
3320: xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3321: {
3322: if (list->items == NULL) {
3323: list->items = (void **) xmlMalloc(
3324: 20 * sizeof(void *));
3325: if (list->items == NULL) {
3326: xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3327: return(-1);
3328: }
3329: list->sizeItems = 20;
3330: } else if (list->sizeItems <= list->nbItems) {
3331: list->sizeItems *= 2;
3332: list->items = (void **) xmlRealloc(list->items,
3333: list->sizeItems * sizeof(void *));
3334: if (list->items == NULL) {
3335: xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3336: list->sizeItems = 0;
3337: return(-1);
3338: }
3339: }
3340: list->items[list->nbItems++] = item;
3341: return(0);
3342: }
3343:
3344: static int
3345: xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3346: int initialSize,
3347: void *item)
3348: {
3349: if (list->items == NULL) {
3350: if (initialSize <= 0)
3351: initialSize = 1;
3352: list->items = (void **) xmlMalloc(
3353: initialSize * sizeof(void *));
3354: if (list->items == NULL) {
3355: xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3356: return(-1);
3357: }
3358: list->sizeItems = initialSize;
3359: } else if (list->sizeItems <= list->nbItems) {
3360: list->sizeItems *= 2;
3361: list->items = (void **) xmlRealloc(list->items,
3362: list->sizeItems * sizeof(void *));
3363: if (list->items == NULL) {
3364: xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3365: list->sizeItems = 0;
3366: return(-1);
3367: }
3368: }
3369: list->items[list->nbItems++] = item;
3370: return(0);
3371: }
3372:
3373: static int
3374: xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3375: {
3376: if (list->items == NULL) {
3377: list->items = (void **) xmlMalloc(
3378: 20 * sizeof(void *));
3379: if (list->items == NULL) {
3380: xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3381: return(-1);
3382: }
3383: list->sizeItems = 20;
3384: } else if (list->sizeItems <= list->nbItems) {
3385: list->sizeItems *= 2;
3386: list->items = (void **) xmlRealloc(list->items,
3387: list->sizeItems * sizeof(void *));
3388: if (list->items == NULL) {
3389: xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3390: list->sizeItems = 0;
3391: return(-1);
3392: }
3393: }
3394: /*
3395: * Just append if the index is greater/equal than the item count.
3396: */
3397: if (idx >= list->nbItems) {
3398: list->items[list->nbItems++] = item;
3399: } else {
3400: int i;
3401: for (i = list->nbItems; i > idx; i--)
3402: list->items[i] = list->items[i-1];
3403: list->items[idx] = item;
3404: list->nbItems++;
3405: }
3406: return(0);
3407: }
3408:
3409: #if 0 /* enable if ever needed */
3410: static int
3411: xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3412: int initialSize,
3413: void *item,
3414: int idx)
3415: {
3416: if (list->items == NULL) {
3417: if (initialSize <= 0)
3418: initialSize = 1;
3419: list->items = (void **) xmlMalloc(
3420: initialSize * sizeof(void *));
3421: if (list->items == NULL) {
3422: xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3423: return(-1);
3424: }
3425: list->sizeItems = initialSize;
3426: } else if (list->sizeItems <= list->nbItems) {
3427: list->sizeItems *= 2;
3428: list->items = (void **) xmlRealloc(list->items,
3429: list->sizeItems * sizeof(void *));
3430: if (list->items == NULL) {
3431: xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3432: list->sizeItems = 0;
3433: return(-1);
3434: }
3435: }
3436: /*
3437: * Just append if the index is greater/equal than the item count.
3438: */
3439: if (idx >= list->nbItems) {
3440: list->items[list->nbItems++] = item;
3441: } else {
3442: int i;
3443: for (i = list->nbItems; i > idx; i--)
3444: list->items[i] = list->items[i-1];
3445: list->items[idx] = item;
3446: list->nbItems++;
3447: }
3448: return(0);
3449: }
3450: #endif
3451:
3452: static int
3453: xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3454: {
3455: int i;
3456: if ((list->items == NULL) || (idx >= list->nbItems)) {
3457: xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3458: "index error.\n");
3459: return(-1);
3460: }
3461:
3462: if (list->nbItems == 1) {
3463: /* TODO: Really free the list? */
3464: xmlFree(list->items);
3465: list->items = NULL;
3466: list->nbItems = 0;
3467: list->sizeItems = 0;
3468: } else if (list->nbItems -1 == idx) {
3469: list->nbItems--;
3470: } else {
3471: for (i = idx; i < list->nbItems -1; i++)
3472: list->items[i] = list->items[i+1];
3473: list->nbItems--;
3474: }
3475: return(0);
3476: }
3477:
3478: /**
3479: * xmlSchemaItemListFree:
3480: * @annot: a schema type structure
3481: *
3482: * Deallocate a annotation structure
3483: */
3484: static void
3485: xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3486: {
3487: if (list == NULL)
3488: return;
3489: if (list->items != NULL)
3490: xmlFree(list->items);
3491: xmlFree(list);
3492: }
3493:
3494: static void
3495: xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3496: {
3497: if (bucket == NULL)
3498: return;
3499: if (bucket->globals != NULL) {
3500: xmlSchemaComponentListFree(bucket->globals);
3501: xmlSchemaItemListFree(bucket->globals);
3502: }
3503: if (bucket->locals != NULL) {
3504: xmlSchemaComponentListFree(bucket->locals);
3505: xmlSchemaItemListFree(bucket->locals);
3506: }
3507: if (bucket->relations != NULL) {
3508: xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3509: do {
3510: prev = cur;
3511: cur = cur->next;
3512: xmlFree(prev);
3513: } while (cur != NULL);
3514: }
3515: if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3516: xmlFreeDoc(bucket->doc);
3517: }
3518: if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3519: if (WXS_IMPBUCKET(bucket)->schema != NULL)
3520: xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3521: }
3522: xmlFree(bucket);
3523: }
3524:
3525: static xmlSchemaBucketPtr
3526: xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3527: int type, const xmlChar *targetNamespace)
3528: {
3529: xmlSchemaBucketPtr ret;
3530: int size;
3531: xmlSchemaPtr mainSchema;
3532:
3533: if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3534: PERROR_INT("xmlSchemaBucketCreate",
3535: "no main schema on constructor");
3536: return(NULL);
3537: }
3538: mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3539: /* Create the schema bucket. */
3540: if (WXS_IS_BUCKET_INCREDEF(type))
3541: size = sizeof(xmlSchemaInclude);
3542: else
3543: size = sizeof(xmlSchemaImport);
3544: ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3545: if (ret == NULL) {
3546: xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3547: return(NULL);
3548: }
3549: memset(ret, 0, size);
3550: ret->targetNamespace = targetNamespace;
3551: ret->type = type;
3552: ret->globals = xmlSchemaItemListCreate();
3553: if (ret->globals == NULL) {
3554: xmlFree(ret);
3555: return(NULL);
3556: }
3557: ret->locals = xmlSchemaItemListCreate();
3558: if (ret->locals == NULL) {
3559: xmlFree(ret);
3560: return(NULL);
3561: }
3562: /*
3563: * The following will assure that only the first bucket is marked as
3564: * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3565: * For each following import buckets an xmlSchema will be created.
3566: * An xmlSchema will be created for every distinct targetNamespace.
3567: * We assign the targetNamespace to the schemata here.
3568: */
3569: if (! WXS_HAS_BUCKETS(pctxt)) {
3570: if (WXS_IS_BUCKET_INCREDEF(type)) {
3571: PERROR_INT("xmlSchemaBucketCreate",
3572: "first bucket but it's an include or redefine");
3573: xmlSchemaBucketFree(ret);
3574: return(NULL);
3575: }
3576: /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3577: ret->type = XML_SCHEMA_SCHEMA_MAIN;
3578: /* Point to the *main* schema. */
3579: WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3580: WXS_IMPBUCKET(ret)->schema = mainSchema;
3581: /*
3582: * Ensure that the main schema gets a targetNamespace.
3583: */
3584: mainSchema->targetNamespace = targetNamespace;
3585: } else {
3586: if (type == XML_SCHEMA_SCHEMA_MAIN) {
3587: PERROR_INT("xmlSchemaBucketCreate",
3588: "main bucket but it's not the first one");
3589: xmlSchemaBucketFree(ret);
3590: return(NULL);
3591: } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3592: /*
3593: * Create a schema for imports and assign the
3594: * targetNamespace.
3595: */
3596: WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3597: if (WXS_IMPBUCKET(ret)->schema == NULL) {
3598: xmlSchemaBucketFree(ret);
3599: return(NULL);
3600: }
3601: WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3602: }
3603: }
3604: if (WXS_IS_BUCKET_IMPMAIN(type)) {
3605: int res;
3606: /*
3607: * Imports go into the "schemasImports" slot of the main *schema*.
3608: * Note that we create an import entry for the main schema as well; i.e.,
3609: * even if there's only one schema, we'll get an import.
3610: */
3611: if (mainSchema->schemasImports == NULL) {
3612: mainSchema->schemasImports = xmlHashCreateDict(5,
3613: WXS_CONSTRUCTOR(pctxt)->dict);
3614: if (mainSchema->schemasImports == NULL) {
3615: xmlSchemaBucketFree(ret);
3616: return(NULL);
3617: }
3618: }
3619: if (targetNamespace == NULL)
3620: res = xmlHashAddEntry(mainSchema->schemasImports,
3621: XML_SCHEMAS_NO_NAMESPACE, ret);
3622: else
3623: res = xmlHashAddEntry(mainSchema->schemasImports,
3624: targetNamespace, ret);
3625: if (res != 0) {
3626: PERROR_INT("xmlSchemaBucketCreate",
3627: "failed to add the schema bucket to the hash");
3628: xmlSchemaBucketFree(ret);
3629: return(NULL);
3630: }
3631: } else {
3632: /* Set the @ownerImport of an include bucket. */
3633: if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3634: WXS_INCBUCKET(ret)->ownerImport =
3635: WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3636: else
3637: WXS_INCBUCKET(ret)->ownerImport =
3638: WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3639:
3640: /* Includes got into the "includes" slot of the *main* schema. */
3641: if (mainSchema->includes == NULL) {
3642: mainSchema->includes = xmlSchemaItemListCreate();
3643: if (mainSchema->includes == NULL) {
3644: xmlSchemaBucketFree(ret);
3645: return(NULL);
3646: }
3647: }
3648: xmlSchemaItemListAdd(mainSchema->includes, ret);
3649: }
3650: /*
3651: * Add to list of all buckets; this is used for lookup
3652: * during schema construction time only.
3653: */
3654: if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3655: return(NULL);
3656: return(ret);
3657: }
3658:
3659: static int
3660: xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3661: {
3662: if (*list == NULL) {
3663: *list = xmlSchemaItemListCreate();
3664: if (*list == NULL)
3665: return(-1);
3666: }
3667: xmlSchemaItemListAddSize(*list, initialSize, item);
3668: return(0);
3669: }
3670:
3671: /**
3672: * xmlSchemaFreeAnnot:
3673: * @annot: a schema type structure
3674: *
3675: * Deallocate a annotation structure
3676: */
3677: static void
3678: xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3679: {
3680: if (annot == NULL)
3681: return;
3682: if (annot->next == NULL) {
3683: xmlFree(annot);
3684: } else {
3685: xmlSchemaAnnotPtr prev;
3686:
3687: do {
3688: prev = annot;
3689: annot = annot->next;
3690: xmlFree(prev);
3691: } while (annot != NULL);
3692: }
3693: }
3694:
3695: /**
3696: * xmlSchemaFreeNotation:
3697: * @schema: a schema notation structure
3698: *
3699: * Deallocate a Schema Notation structure.
3700: */
3701: static void
3702: xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3703: {
3704: if (nota == NULL)
3705: return;
3706: xmlFree(nota);
3707: }
3708:
3709: /**
3710: * xmlSchemaFreeAttribute:
3711: * @attr: an attribute declaration
3712: *
3713: * Deallocates an attribute declaration structure.
3714: */
3715: static void
3716: xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3717: {
3718: if (attr == NULL)
3719: return;
3720: if (attr->annot != NULL)
3721: xmlSchemaFreeAnnot(attr->annot);
3722: if (attr->defVal != NULL)
3723: xmlSchemaFreeValue(attr->defVal);
3724: xmlFree(attr);
3725: }
3726:
3727: /**
3728: * xmlSchemaFreeAttributeUse:
3729: * @use: an attribute use
3730: *
3731: * Deallocates an attribute use structure.
3732: */
3733: static void
3734: xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3735: {
3736: if (use == NULL)
3737: return;
3738: if (use->annot != NULL)
3739: xmlSchemaFreeAnnot(use->annot);
3740: if (use->defVal != NULL)
3741: xmlSchemaFreeValue(use->defVal);
3742: xmlFree(use);
3743: }
3744:
3745: /**
3746: * xmlSchemaFreeAttributeUseProhib:
3747: * @prohib: an attribute use prohibition
3748: *
3749: * Deallocates an attribute use structure.
3750: */
3751: static void
3752: xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3753: {
3754: if (prohib == NULL)
3755: return;
3756: xmlFree(prohib);
3757: }
3758:
3759: /**
3760: * xmlSchemaFreeWildcardNsSet:
3761: * set: a schema wildcard namespace
3762: *
3763: * Deallocates a list of wildcard constraint structures.
3764: */
3765: static void
3766: xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3767: {
3768: xmlSchemaWildcardNsPtr next;
3769:
3770: while (set != NULL) {
3771: next = set->next;
3772: xmlFree(set);
3773: set = next;
3774: }
3775: }
3776:
3777: /**
3778: * xmlSchemaFreeWildcard:
3779: * @wildcard: a wildcard structure
3780: *
3781: * Deallocates a wildcard structure.
3782: */
3783: void
3784: xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3785: {
3786: if (wildcard == NULL)
3787: return;
3788: if (wildcard->annot != NULL)
3789: xmlSchemaFreeAnnot(wildcard->annot);
3790: if (wildcard->nsSet != NULL)
3791: xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3792: if (wildcard->negNsSet != NULL)
3793: xmlFree(wildcard->negNsSet);
3794: xmlFree(wildcard);
3795: }
3796:
3797: /**
3798: * xmlSchemaFreeAttributeGroup:
3799: * @schema: a schema attribute group structure
3800: *
3801: * Deallocate a Schema Attribute Group structure.
3802: */
3803: static void
3804: xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3805: {
3806: if (attrGr == NULL)
3807: return;
3808: if (attrGr->annot != NULL)
3809: xmlSchemaFreeAnnot(attrGr->annot);
3810: if (attrGr->attrUses != NULL)
3811: xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3812: xmlFree(attrGr);
3813: }
3814:
3815: /**
3816: * xmlSchemaFreeQNameRef:
3817: * @item: a QName reference structure
3818: *
3819: * Deallocatea a QName reference structure.
3820: */
3821: static void
3822: xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3823: {
3824: xmlFree(item);
3825: }
3826:
3827: /**
3828: * xmlSchemaFreeTypeLinkList:
3829: * @alink: a type link
3830: *
3831: * Deallocate a list of types.
3832: */
3833: static void
3834: xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3835: {
3836: xmlSchemaTypeLinkPtr next;
3837:
3838: while (link != NULL) {
3839: next = link->next;
3840: xmlFree(link);
3841: link = next;
3842: }
3843: }
3844:
3845: static void
3846: xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3847: {
3848: xmlSchemaIDCStateObjPtr next;
3849: while (sto != NULL) {
3850: next = sto->next;
3851: if (sto->history != NULL)
3852: xmlFree(sto->history);
3853: if (sto->xpathCtxt != NULL)
3854: xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3855: xmlFree(sto);
3856: sto = next;
3857: }
3858: }
3859:
3860: /**
3861: * xmlSchemaFreeIDC:
3862: * @idc: a identity-constraint definition
3863: *
3864: * Deallocates an identity-constraint definition.
3865: */
3866: static void
3867: xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3868: {
3869: xmlSchemaIDCSelectPtr cur, prev;
3870:
3871: if (idcDef == NULL)
3872: return;
3873: if (idcDef->annot != NULL)
3874: xmlSchemaFreeAnnot(idcDef->annot);
3875: /* Selector */
3876: if (idcDef->selector != NULL) {
3877: if (idcDef->selector->xpathComp != NULL)
3878: xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3879: xmlFree(idcDef->selector);
3880: }
3881: /* Fields */
3882: if (idcDef->fields != NULL) {
3883: cur = idcDef->fields;
3884: do {
3885: prev = cur;
3886: cur = cur->next;
3887: if (prev->xpathComp != NULL)
3888: xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3889: xmlFree(prev);
3890: } while (cur != NULL);
3891: }
3892: xmlFree(idcDef);
3893: }
3894:
3895: /**
3896: * xmlSchemaFreeElement:
3897: * @schema: a schema element structure
3898: *
3899: * Deallocate a Schema Element structure.
3900: */
3901: static void
3902: xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3903: {
3904: if (elem == NULL)
3905: return;
3906: if (elem->annot != NULL)
3907: xmlSchemaFreeAnnot(elem->annot);
3908: if (elem->contModel != NULL)
3909: xmlRegFreeRegexp(elem->contModel);
3910: if (elem->defVal != NULL)
3911: xmlSchemaFreeValue(elem->defVal);
3912: xmlFree(elem);
3913: }
3914:
3915: /**
3916: * xmlSchemaFreeFacet:
3917: * @facet: a schema facet structure
3918: *
3919: * Deallocate a Schema Facet structure.
3920: */
3921: void
3922: xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3923: {
3924: if (facet == NULL)
3925: return;
3926: if (facet->val != NULL)
3927: xmlSchemaFreeValue(facet->val);
3928: if (facet->regexp != NULL)
3929: xmlRegFreeRegexp(facet->regexp);
3930: if (facet->annot != NULL)
3931: xmlSchemaFreeAnnot(facet->annot);
3932: xmlFree(facet);
3933: }
3934:
3935: /**
3936: * xmlSchemaFreeType:
3937: * @type: a schema type structure
3938: *
3939: * Deallocate a Schema Type structure.
3940: */
3941: void
3942: xmlSchemaFreeType(xmlSchemaTypePtr type)
3943: {
3944: if (type == NULL)
3945: return;
3946: if (type->annot != NULL)
3947: xmlSchemaFreeAnnot(type->annot);
3948: if (type->facets != NULL) {
3949: xmlSchemaFacetPtr facet, next;
3950:
3951: facet = type->facets;
3952: while (facet != NULL) {
3953: next = facet->next;
3954: xmlSchemaFreeFacet(facet);
3955: facet = next;
3956: }
3957: }
3958: if (type->attrUses != NULL)
3959: xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
3960: if (type->memberTypes != NULL)
3961: xmlSchemaFreeTypeLinkList(type->memberTypes);
3962: if (type->facetSet != NULL) {
3963: xmlSchemaFacetLinkPtr next, link;
3964:
3965: link = type->facetSet;
3966: do {
3967: next = link->next;
3968: xmlFree(link);
3969: link = next;
3970: } while (link != NULL);
3971: }
3972: if (type->contModel != NULL)
3973: xmlRegFreeRegexp(type->contModel);
3974: xmlFree(type);
3975: }
3976:
3977: /**
3978: * xmlSchemaFreeModelGroupDef:
3979: * @item: a schema model group definition
3980: *
3981: * Deallocates a schema model group definition.
3982: */
3983: static void
3984: xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3985: {
3986: if (item->annot != NULL)
3987: xmlSchemaFreeAnnot(item->annot);
3988: xmlFree(item);
3989: }
3990:
3991: /**
3992: * xmlSchemaFreeModelGroup:
3993: * @item: a schema model group
3994: *
3995: * Deallocates a schema model group structure.
3996: */
3997: static void
3998: xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3999: {
4000: if (item->annot != NULL)
4001: xmlSchemaFreeAnnot(item->annot);
4002: xmlFree(item);
4003: }
4004:
4005: static void
4006: xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4007: {
4008: if ((list == NULL) || (list->nbItems == 0))
4009: return;
4010: {
4011: xmlSchemaTreeItemPtr item;
4012: xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4013: int i;
4014:
4015: for (i = 0; i < list->nbItems; i++) {
4016: item = items[i];
4017: if (item == NULL)
4018: continue;
4019: switch (item->type) {
4020: case XML_SCHEMA_TYPE_SIMPLE:
4021: case XML_SCHEMA_TYPE_COMPLEX:
4022: xmlSchemaFreeType((xmlSchemaTypePtr) item);
4023: break;
4024: case XML_SCHEMA_TYPE_ATTRIBUTE:
4025: xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4026: break;
4027: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4028: xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4029: break;
4030: case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4031: xmlSchemaFreeAttributeUseProhib(
4032: (xmlSchemaAttributeUseProhibPtr) item);
4033: break;
4034: case XML_SCHEMA_TYPE_ELEMENT:
4035: xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4036: break;
4037: case XML_SCHEMA_TYPE_PARTICLE:
4038: if (item->annot != NULL)
4039: xmlSchemaFreeAnnot(item->annot);
4040: xmlFree(item);
4041: break;
4042: case XML_SCHEMA_TYPE_SEQUENCE:
4043: case XML_SCHEMA_TYPE_CHOICE:
4044: case XML_SCHEMA_TYPE_ALL:
4045: xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4046: break;
4047: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4048: xmlSchemaFreeAttributeGroup(
4049: (xmlSchemaAttributeGroupPtr) item);
4050: break;
4051: case XML_SCHEMA_TYPE_GROUP:
4052: xmlSchemaFreeModelGroupDef(
4053: (xmlSchemaModelGroupDefPtr) item);
4054: break;
4055: case XML_SCHEMA_TYPE_ANY:
4056: case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4057: xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4058: break;
4059: case XML_SCHEMA_TYPE_IDC_KEY:
4060: case XML_SCHEMA_TYPE_IDC_UNIQUE:
4061: case XML_SCHEMA_TYPE_IDC_KEYREF:
4062: xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4063: break;
4064: case XML_SCHEMA_TYPE_NOTATION:
4065: xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4066: break;
4067: case XML_SCHEMA_EXTRA_QNAMEREF:
4068: xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4069: break;
4070: default: {
4071: /* TODO: This should never be hit. */
4072: xmlSchemaPSimpleInternalErr(NULL,
4073: "Internal error: xmlSchemaComponentListFree, "
4074: "unexpected component type '%s'\n",
4075: (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4076: }
4077: break;
4078: }
4079: }
4080: list->nbItems = 0;
4081: }
4082: }
4083:
4084: /**
4085: * xmlSchemaFree:
4086: * @schema: a schema structure
4087: *
4088: * Deallocate a Schema structure.
4089: */
4090: void
4091: xmlSchemaFree(xmlSchemaPtr schema)
4092: {
4093: if (schema == NULL)
4094: return;
4095: /* @volatiles is not used anymore :-/ */
4096: if (schema->volatiles != NULL)
4097: TODO
4098: /*
4099: * Note that those slots are not responsible for freeing
4100: * schema components anymore; this will now be done by
4101: * the schema buckets.
4102: */
4103: if (schema->notaDecl != NULL)
4104: xmlHashFree(schema->notaDecl, NULL);
4105: if (schema->attrDecl != NULL)
4106: xmlHashFree(schema->attrDecl, NULL);
4107: if (schema->attrgrpDecl != NULL)
4108: xmlHashFree(schema->attrgrpDecl, NULL);
4109: if (schema->elemDecl != NULL)
4110: xmlHashFree(schema->elemDecl, NULL);
4111: if (schema->typeDecl != NULL)
4112: xmlHashFree(schema->typeDecl, NULL);
4113: if (schema->groupDecl != NULL)
4114: xmlHashFree(schema->groupDecl, NULL);
4115: if (schema->idcDef != NULL)
4116: xmlHashFree(schema->idcDef, NULL);
4117:
4118: if (schema->schemasImports != NULL)
4119: xmlHashFree(schema->schemasImports,
4120: (xmlHashDeallocator) xmlSchemaBucketFree);
4121: if (schema->includes != NULL) {
4122: xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4123: int i;
4124: for (i = 0; i < list->nbItems; i++) {
4125: xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4126: }
4127: xmlSchemaItemListFree(list);
4128: }
4129: if (schema->annot != NULL)
4130: xmlSchemaFreeAnnot(schema->annot);
4131: /* Never free the doc here, since this will be done by the buckets. */
4132:
4133: xmlDictFree(schema->dict);
4134: xmlFree(schema);
4135: }
4136:
4137: /************************************************************************
4138: * *
4139: * Debug functions *
4140: * *
4141: ************************************************************************/
4142:
4143: #ifdef LIBXML_OUTPUT_ENABLED
4144:
4145: static void
4146: xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4147:
4148: /**
4149: * xmlSchemaElementDump:
4150: * @elem: an element
4151: * @output: the file output
4152: *
4153: * Dump the element
4154: */
4155: static void
4156: xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4157: const xmlChar * name ATTRIBUTE_UNUSED,
4158: const xmlChar * namespace ATTRIBUTE_UNUSED,
4159: const xmlChar * context ATTRIBUTE_UNUSED)
4160: {
4161: if (elem == NULL)
4162: return;
4163:
4164:
4165: fprintf(output, "Element");
4166: if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4167: fprintf(output, " (global)");
4168: fprintf(output, ": '%s' ", elem->name);
4169: if (namespace != NULL)
4170: fprintf(output, "ns '%s'", namespace);
4171: fprintf(output, "\n");
4172: #if 0
4173: if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4174: fprintf(output, " min %d ", elem->minOccurs);
4175: if (elem->maxOccurs >= UNBOUNDED)
4176: fprintf(output, "max: unbounded\n");
4177: else if (elem->maxOccurs != 1)
4178: fprintf(output, "max: %d\n", elem->maxOccurs);
4179: else
4180: fprintf(output, "\n");
4181: }
4182: #endif
4183: /*
4184: * Misc other properties.
4185: */
4186: if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4187: (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4188: (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4189: (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4190: fprintf(output, " props: ");
4191: if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4192: fprintf(output, "[fixed] ");
4193: if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4194: fprintf(output, "[default] ");
4195: if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4196: fprintf(output, "[abstract] ");
4197: if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4198: fprintf(output, "[nillable] ");
4199: fprintf(output, "\n");
4200: }
4201: /*
4202: * Default/fixed value.
4203: */
4204: if (elem->value != NULL)
4205: fprintf(output, " value: '%s'\n", elem->value);
4206: /*
4207: * Type.
4208: */
4209: if (elem->namedType != NULL) {
4210: fprintf(output, " type: '%s' ", elem->namedType);
4211: if (elem->namedTypeNs != NULL)
4212: fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4213: else
4214: fprintf(output, "\n");
4215: } else if (elem->subtypes != NULL) {
4216: /*
4217: * Dump local types.
4218: */
4219: xmlSchemaTypeDump(elem->subtypes, output);
4220: }
4221: /*
4222: * Substitution group.
4223: */
4224: if (elem->substGroup != NULL) {
4225: fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
4226: if (elem->substGroupNs != NULL)
4227: fprintf(output, "ns '%s'\n", elem->substGroupNs);
4228: else
4229: fprintf(output, "\n");
4230: }
4231: }
4232:
4233: /**
4234: * xmlSchemaAnnotDump:
4235: * @output: the file output
4236: * @annot: a annotation
4237: *
4238: * Dump the annotation
4239: */
4240: static void
4241: xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4242: {
4243: xmlChar *content;
4244:
4245: if (annot == NULL)
4246: return;
4247:
4248: content = xmlNodeGetContent(annot->content);
4249: if (content != NULL) {
4250: fprintf(output, " Annot: %s\n", content);
4251: xmlFree(content);
4252: } else
4253: fprintf(output, " Annot: empty\n");
4254: }
4255:
4256: /**
4257: * xmlSchemaContentModelDump:
4258: * @particle: the schema particle
4259: * @output: the file output
4260: * @depth: the depth used for intentation
4261: *
4262: * Dump a SchemaType structure
4263: */
4264: static void
4265: xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4266: {
4267: xmlChar *str = NULL;
4268: xmlSchemaTreeItemPtr term;
4269: char shift[100];
4270: int i;
4271:
4272: if (particle == NULL)
4273: return;
4274: for (i = 0;((i < depth) && (i < 25));i++)
4275: shift[2 * i] = shift[2 * i + 1] = ' ';
4276: shift[2 * i] = shift[2 * i + 1] = 0;
4277: fprintf(output, "%s", shift);
4278: if (particle->children == NULL) {
4279: fprintf(output, "MISSING particle term\n");
4280: return;
4281: }
4282: term = particle->children;
4283: if (term == NULL) {
4284: fprintf(output, "(NULL)");
4285: } else {
4286: switch (term->type) {
4287: case XML_SCHEMA_TYPE_ELEMENT:
4288: fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4289: ((xmlSchemaElementPtr)term)->targetNamespace,
4290: ((xmlSchemaElementPtr)term)->name));
4291: FREE_AND_NULL(str);
4292: break;
4293: case XML_SCHEMA_TYPE_SEQUENCE:
4294: fprintf(output, "SEQUENCE");
4295: break;
4296: case XML_SCHEMA_TYPE_CHOICE:
4297: fprintf(output, "CHOICE");
4298: break;
4299: case XML_SCHEMA_TYPE_ALL:
4300: fprintf(output, "ALL");
4301: break;
4302: case XML_SCHEMA_TYPE_ANY:
4303: fprintf(output, "ANY");
4304: break;
4305: default:
4306: fprintf(output, "UNKNOWN\n");
4307: return;
4308: }
4309: }
4310: if (particle->minOccurs != 1)
4311: fprintf(output, " min: %d", particle->minOccurs);
4312: if (particle->maxOccurs >= UNBOUNDED)
4313: fprintf(output, " max: unbounded");
4314: else if (particle->maxOccurs != 1)
4315: fprintf(output, " max: %d", particle->maxOccurs);
4316: fprintf(output, "\n");
4317: if (term &&
4318: ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4319: (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4320: (term->type == XML_SCHEMA_TYPE_ALL)) &&
4321: (term->children != NULL)) {
4322: xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4323: output, depth +1);
4324: }
4325: if (particle->next != NULL)
4326: xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4327: output, depth);
4328: }
4329:
4330: /**
4331: * xmlSchemaAttrUsesDump:
4332: * @uses: attribute uses list
4333: * @output: the file output
4334: *
4335: * Dumps a list of attribute use components.
4336: */
4337: static void
4338: xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4339: {
4340: xmlSchemaAttributeUsePtr use;
4341: xmlSchemaAttributeUseProhibPtr prohib;
4342: xmlSchemaQNameRefPtr ref;
4343: const xmlChar *name, *tns;
4344: xmlChar *str = NULL;
4345: int i;
4346:
4347: if ((uses == NULL) || (uses->nbItems == 0))
4348: return;
4349:
4350: fprintf(output, " attributes:\n");
4351: for (i = 0; i < uses->nbItems; i++) {
4352: use = uses->items[i];
4353: if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4354: fprintf(output, " [prohibition] ");
4355: prohib = (xmlSchemaAttributeUseProhibPtr) use;
4356: name = prohib->name;
4357: tns = prohib->targetNamespace;
4358: } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4359: fprintf(output, " [reference] ");
4360: ref = (xmlSchemaQNameRefPtr) use;
4361: name = ref->name;
4362: tns = ref->targetNamespace;
4363: } else {
4364: fprintf(output, " [use] ");
4365: name = WXS_ATTRUSE_DECL_NAME(use);
4366: tns = WXS_ATTRUSE_DECL_TNS(use);
4367: }
4368: fprintf(output, "'%s'\n",
4369: (const char *) xmlSchemaFormatQName(&str, tns, name));
4370: FREE_AND_NULL(str);
4371: }
4372: }
4373:
4374: /**
4375: * xmlSchemaTypeDump:
4376: * @output: the file output
4377: * @type: a type structure
4378: *
4379: * Dump a SchemaType structure
4380: */
4381: static void
4382: xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4383: {
4384: if (type == NULL) {
4385: fprintf(output, "Type: NULL\n");
4386: return;
4387: }
4388: fprintf(output, "Type: ");
4389: if (type->name != NULL)
4390: fprintf(output, "'%s' ", type->name);
4391: else
4392: fprintf(output, "(no name) ");
4393: if (type->targetNamespace != NULL)
4394: fprintf(output, "ns '%s' ", type->targetNamespace);
4395: switch (type->type) {
4396: case XML_SCHEMA_TYPE_BASIC:
4397: fprintf(output, "[basic] ");
4398: break;
4399: case XML_SCHEMA_TYPE_SIMPLE:
4400: fprintf(output, "[simple] ");
4401: break;
4402: case XML_SCHEMA_TYPE_COMPLEX:
4403: fprintf(output, "[complex] ");
4404: break;
4405: case XML_SCHEMA_TYPE_SEQUENCE:
4406: fprintf(output, "[sequence] ");
4407: break;
4408: case XML_SCHEMA_TYPE_CHOICE:
4409: fprintf(output, "[choice] ");
4410: break;
4411: case XML_SCHEMA_TYPE_ALL:
4412: fprintf(output, "[all] ");
4413: break;
4414: case XML_SCHEMA_TYPE_UR:
4415: fprintf(output, "[ur] ");
4416: break;
4417: case XML_SCHEMA_TYPE_RESTRICTION:
4418: fprintf(output, "[restriction] ");
4419: break;
4420: case XML_SCHEMA_TYPE_EXTENSION:
4421: fprintf(output, "[extension] ");
4422: break;
4423: default:
4424: fprintf(output, "[unknown type %d] ", type->type);
4425: break;
4426: }
4427: fprintf(output, "content: ");
4428: switch (type->contentType) {
4429: case XML_SCHEMA_CONTENT_UNKNOWN:
4430: fprintf(output, "[unknown] ");
4431: break;
4432: case XML_SCHEMA_CONTENT_EMPTY:
4433: fprintf(output, "[empty] ");
4434: break;
4435: case XML_SCHEMA_CONTENT_ELEMENTS:
4436: fprintf(output, "[element] ");
4437: break;
4438: case XML_SCHEMA_CONTENT_MIXED:
4439: fprintf(output, "[mixed] ");
4440: break;
4441: case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4442: /* not used. */
4443: break;
4444: case XML_SCHEMA_CONTENT_BASIC:
4445: fprintf(output, "[basic] ");
4446: break;
4447: case XML_SCHEMA_CONTENT_SIMPLE:
4448: fprintf(output, "[simple] ");
4449: break;
4450: case XML_SCHEMA_CONTENT_ANY:
4451: fprintf(output, "[any] ");
4452: break;
4453: }
4454: fprintf(output, "\n");
4455: if (type->base != NULL) {
4456: fprintf(output, " base type: '%s'", type->base);
4457: if (type->baseNs != NULL)
4458: fprintf(output, " ns '%s'\n", type->baseNs);
4459: else
4460: fprintf(output, "\n");
4461: }
4462: if (type->attrUses != NULL)
4463: xmlSchemaAttrUsesDump(type->attrUses, output);
4464: if (type->annot != NULL)
4465: xmlSchemaAnnotDump(output, type->annot);
4466: #ifdef DUMP_CONTENT_MODEL
4467: if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4468: (type->subtypes != NULL)) {
4469: xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4470: output, 1);
4471: }
4472: #endif
4473: }
4474:
4475: /**
4476: * xmlSchemaDump:
4477: * @output: the file output
4478: * @schema: a schema structure
4479: *
4480: * Dump a Schema structure.
4481: */
4482: void
4483: xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4484: {
4485: if (output == NULL)
4486: return;
4487: if (schema == NULL) {
4488: fprintf(output, "Schemas: NULL\n");
4489: return;
4490: }
4491: fprintf(output, "Schemas: ");
4492: if (schema->name != NULL)
4493: fprintf(output, "%s, ", schema->name);
4494: else
4495: fprintf(output, "no name, ");
4496: if (schema->targetNamespace != NULL)
4497: fprintf(output, "%s", (const char *) schema->targetNamespace);
4498: else
4499: fprintf(output, "no target namespace");
4500: fprintf(output, "\n");
4501: if (schema->annot != NULL)
4502: xmlSchemaAnnotDump(output, schema->annot);
4503: xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4504: output);
4505: xmlHashScanFull(schema->elemDecl,
4506: (xmlHashScannerFull) xmlSchemaElementDump, output);
4507: }
4508:
4509: #ifdef DEBUG_IDC_NODE_TABLE
4510: /**
4511: * xmlSchemaDebugDumpIDCTable:
4512: * @vctxt: the WXS validation context
4513: *
4514: * Displays the current IDC table for debug purposes.
4515: */
4516: static void
4517: xmlSchemaDebugDumpIDCTable(FILE * output,
4518: const xmlChar *namespaceName,
4519: const xmlChar *localName,
4520: xmlSchemaPSVIIDCBindingPtr bind)
4521: {
4522: xmlChar *str = NULL;
4523: const xmlChar *value;
4524: xmlSchemaPSVIIDCNodePtr tab;
4525: xmlSchemaPSVIIDCKeyPtr key;
4526: int i, j, res;
4527:
4528: fprintf(output, "IDC: TABLES on '%s'\n",
4529: xmlSchemaFormatQName(&str, namespaceName, localName));
4530: FREE_AND_NULL(str)
4531:
4532: if (bind == NULL)
4533: return;
4534: do {
4535: fprintf(output, "IDC: BINDING '%s' (%d)\n",
4536: xmlSchemaGetComponentQName(&str,
4537: bind->definition), bind->nbNodes);
4538: FREE_AND_NULL(str)
4539: for (i = 0; i < bind->nbNodes; i++) {
4540: tab = bind->nodeTable[i];
4541: fprintf(output, " ( ");
4542: for (j = 0; j < bind->definition->nbFields; j++) {
4543: key = tab->keys[j];
4544: if ((key != NULL) && (key->val != NULL)) {
4545: res = xmlSchemaGetCanonValue(key->val, &value);
4546: if (res >= 0)
4547: fprintf(output, "'%s' ", value);
4548: else
4549: fprintf(output, "CANON-VALUE-FAILED ");
4550: if (res == 0)
4551: FREE_AND_NULL(value)
4552: } else if (key != NULL)
4553: fprintf(output, "(no val), ");
4554: else
4555: fprintf(output, "(key missing), ");
4556: }
4557: fprintf(output, ")\n");
4558: }
4559: if (bind->dupls && bind->dupls->nbItems) {
4560: fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
4561: for (i = 0; i < bind->dupls->nbItems; i++) {
4562: tab = bind->dupls->items[i];
4563: fprintf(output, " ( ");
4564: for (j = 0; j < bind->definition->nbFields; j++) {
4565: key = tab->keys[j];
4566: if ((key != NULL) && (key->val != NULL)) {
4567: res = xmlSchemaGetCanonValue(key->val, &value);
4568: if (res >= 0)
4569: fprintf(output, "'%s' ", value);
4570: else
4571: fprintf(output, "CANON-VALUE-FAILED ");
4572: if (res == 0)
4573: FREE_AND_NULL(value)
4574: } else if (key != NULL)
4575: fprintf(output, "(no val), ");
4576: else
4577: fprintf(output, "(key missing), ");
4578: }
4579: fprintf(output, ")\n");
4580: }
4581: }
4582: bind = bind->next;
4583: } while (bind != NULL);
4584: }
4585: #endif /* DEBUG_IDC */
4586: #endif /* LIBXML_OUTPUT_ENABLED */
4587:
4588: /************************************************************************
4589: * *
4590: * Utilities *
4591: * *
4592: ************************************************************************/
4593:
4594: /**
4595: * xmlSchemaGetPropNode:
4596: * @node: the element node
4597: * @name: the name of the attribute
4598: *
4599: * Seeks an attribute with a name of @name in
4600: * no namespace.
4601: *
4602: * Returns the attribute or NULL if not present.
4603: */
4604: static xmlAttrPtr
4605: xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4606: {
4607: xmlAttrPtr prop;
4608:
4609: if ((node == NULL) || (name == NULL))
4610: return(NULL);
4611: prop = node->properties;
4612: while (prop != NULL) {
4613: if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4614: return(prop);
4615: prop = prop->next;
4616: }
4617: return (NULL);
4618: }
4619:
4620: /**
4621: * xmlSchemaGetPropNodeNs:
4622: * @node: the element node
4623: * @uri: the uri
4624: * @name: the name of the attribute
4625: *
4626: * Seeks an attribute with a local name of @name and
4627: * a namespace URI of @uri.
4628: *
4629: * Returns the attribute or NULL if not present.
4630: */
4631: static xmlAttrPtr
4632: xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4633: {
4634: xmlAttrPtr prop;
4635:
4636: if ((node == NULL) || (name == NULL))
4637: return(NULL);
4638: prop = node->properties;
4639: while (prop != NULL) {
4640: if ((prop->ns != NULL) &&
4641: xmlStrEqual(prop->name, BAD_CAST name) &&
4642: xmlStrEqual(prop->ns->href, BAD_CAST uri))
4643: return(prop);
4644: prop = prop->next;
4645: }
4646: return (NULL);
4647: }
4648:
4649: static const xmlChar *
4650: xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4651: {
4652: xmlChar *val;
4653: const xmlChar *ret;
4654:
4655: val = xmlNodeGetContent(node);
4656: if (val == NULL)
4657: val = xmlStrdup((xmlChar *)"");
4658: ret = xmlDictLookup(ctxt->dict, val, -1);
4659: xmlFree(val);
4660: return(ret);
4661: }
4662:
4663: static const xmlChar *
4664: xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4665: {
4666: return((const xmlChar*) xmlNodeGetContent(node));
4667: }
4668:
4669: /**
4670: * xmlSchemaGetProp:
4671: * @ctxt: the parser context
4672: * @node: the node
4673: * @name: the property name
4674: *
4675: * Read a attribute value and internalize the string
4676: *
4677: * Returns the string or NULL if not present.
4678: */
4679: static const xmlChar *
4680: xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4681: const char *name)
4682: {
4683: xmlChar *val;
4684: const xmlChar *ret;
4685:
4686: val = xmlGetNoNsProp(node, BAD_CAST name);
4687: if (val == NULL)
4688: return(NULL);
4689: ret = xmlDictLookup(ctxt->dict, val, -1);
4690: xmlFree(val);
4691: return(ret);
4692: }
4693:
4694: /************************************************************************
4695: * *
4696: * Parsing functions *
4697: * *
4698: ************************************************************************/
4699:
4700: #define WXS_FIND_GLOBAL_ITEM(slot) \
4701: if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4702: ret = xmlHashLookup(schema->slot, name); \
4703: if (ret != NULL) goto exit; \
4704: } \
4705: if (xmlHashSize(schema->schemasImports) > 1) { \
4706: xmlSchemaImportPtr import; \
4707: if (nsName == NULL) \
4708: import = xmlHashLookup(schema->schemasImports, \
4709: XML_SCHEMAS_NO_NAMESPACE); \
4710: else \
4711: import = xmlHashLookup(schema->schemasImports, nsName); \
4712: if (import == NULL) \
4713: goto exit; \
4714: ret = xmlHashLookup(import->schema->slot, name); \
4715: }
4716:
4717: /**
4718: * xmlSchemaGetElem:
4719: * @schema: the schema context
4720: * @name: the element name
4721: * @ns: the element namespace
4722: *
4723: * Lookup a global element declaration in the schema.
4724: *
4725: * Returns the element declaration or NULL if not found.
4726: */
4727: static xmlSchemaElementPtr
4728: xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4729: const xmlChar * nsName)
4730: {
4731: xmlSchemaElementPtr ret = NULL;
4732:
4733: if ((name == NULL) || (schema == NULL))
4734: return(NULL);
4735: if (schema != NULL) {
4736: WXS_FIND_GLOBAL_ITEM(elemDecl)
4737: }
4738: exit:
4739: #ifdef DEBUG
4740: if (ret == NULL) {
4741: if (nsName == NULL)
4742: fprintf(stderr, "Unable to lookup element decl. %s", name);
4743: else
4744: fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4745: nsName);
4746: }
4747: #endif
4748: return (ret);
4749: }
4750:
4751: /**
4752: * xmlSchemaGetType:
4753: * @schema: the main schema
4754: * @name: the type's name
4755: * nsName: the type's namespace
4756: *
4757: * Lookup a type in the schemas or the predefined types
4758: *
4759: * Returns the group definition or NULL if not found.
4760: */
4761: static xmlSchemaTypePtr
4762: xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4763: const xmlChar * nsName)
4764: {
4765: xmlSchemaTypePtr ret = NULL;
4766:
4767: if (name == NULL)
4768: return (NULL);
4769: /* First try the built-in types. */
4770: if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4771: ret = xmlSchemaGetPredefinedType(name, nsName);
4772: if (ret != NULL)
4773: goto exit;
4774: /*
4775: * Note that we try the parsed schemas as well here
4776: * since one might have parsed the S4S, which contain more
4777: * than the built-in types.
4778: * TODO: Can we optimize this?
4779: */
4780: }
4781: if (schema != NULL) {
4782: WXS_FIND_GLOBAL_ITEM(typeDecl)
4783: }
4784: exit:
4785:
4786: #ifdef DEBUG
4787: if (ret == NULL) {
4788: if (nsName == NULL)
4789: fprintf(stderr, "Unable to lookup type %s", name);
4790: else
4791: fprintf(stderr, "Unable to lookup type %s:%s", name,
4792: nsName);
4793: }
4794: #endif
4795: return (ret);
4796: }
4797:
4798: /**
4799: * xmlSchemaGetAttributeDecl:
4800: * @schema: the context of the schema
4801: * @name: the name of the attribute
4802: * @ns: the target namespace of the attribute
4803: *
4804: * Lookup a an attribute in the schema or imported schemas
4805: *
4806: * Returns the attribute declaration or NULL if not found.
4807: */
4808: static xmlSchemaAttributePtr
4809: xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4810: const xmlChar * nsName)
4811: {
4812: xmlSchemaAttributePtr ret = NULL;
4813:
4814: if ((name == NULL) || (schema == NULL))
4815: return (NULL);
4816: if (schema != NULL) {
4817: WXS_FIND_GLOBAL_ITEM(attrDecl)
4818: }
4819: exit:
4820: #ifdef DEBUG
4821: if (ret == NULL) {
4822: if (nsName == NULL)
4823: fprintf(stderr, "Unable to lookup attribute %s", name);
4824: else
4825: fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4826: nsName);
4827: }
4828: #endif
4829: return (ret);
4830: }
4831:
4832: /**
4833: * xmlSchemaGetAttributeGroup:
4834: * @schema: the context of the schema
4835: * @name: the name of the attribute group
4836: * @ns: the target namespace of the attribute group
4837: *
4838: * Lookup a an attribute group in the schema or imported schemas
4839: *
4840: * Returns the attribute group definition or NULL if not found.
4841: */
4842: static xmlSchemaAttributeGroupPtr
4843: xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4844: const xmlChar * nsName)
4845: {
4846: xmlSchemaAttributeGroupPtr ret = NULL;
4847:
4848: if ((name == NULL) || (schema == NULL))
4849: return (NULL);
4850: if (schema != NULL) {
4851: WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4852: }
4853: exit:
4854: /* TODO:
4855: if ((ret != NULL) && (ret->redef != NULL)) {
4856: * Return the last redefinition. *
4857: ret = ret->redef;
4858: }
4859: */
4860: #ifdef DEBUG
4861: if (ret == NULL) {
4862: if (nsName == NULL)
4863: fprintf(stderr, "Unable to lookup attribute group %s", name);
4864: else
4865: fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4866: nsName);
4867: }
4868: #endif
4869: return (ret);
4870: }
4871:
4872: /**
4873: * xmlSchemaGetGroup:
4874: * @schema: the context of the schema
4875: * @name: the name of the group
4876: * @ns: the target namespace of the group
4877: *
4878: * Lookup a group in the schema or imported schemas
4879: *
4880: * Returns the group definition or NULL if not found.
4881: */
4882: static xmlSchemaModelGroupDefPtr
4883: xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4884: const xmlChar * nsName)
4885: {
4886: xmlSchemaModelGroupDefPtr ret = NULL;
4887:
4888: if ((name == NULL) || (schema == NULL))
4889: return (NULL);
4890: if (schema != NULL) {
4891: WXS_FIND_GLOBAL_ITEM(groupDecl)
4892: }
4893: exit:
4894:
4895: #ifdef DEBUG
4896: if (ret == NULL) {
4897: if (nsName == NULL)
4898: fprintf(stderr, "Unable to lookup group %s", name);
4899: else
4900: fprintf(stderr, "Unable to lookup group %s:%s", name,
4901: nsName);
4902: }
4903: #endif
4904: return (ret);
4905: }
4906:
4907: static xmlSchemaNotationPtr
4908: xmlSchemaGetNotation(xmlSchemaPtr schema,
4909: const xmlChar *name,
4910: const xmlChar *nsName)
4911: {
4912: xmlSchemaNotationPtr ret = NULL;
4913:
4914: if ((name == NULL) || (schema == NULL))
4915: return (NULL);
4916: if (schema != NULL) {
4917: WXS_FIND_GLOBAL_ITEM(notaDecl)
4918: }
4919: exit:
4920: return (ret);
4921: }
4922:
4923: static xmlSchemaIDCPtr
4924: xmlSchemaGetIDC(xmlSchemaPtr schema,
4925: const xmlChar *name,
4926: const xmlChar *nsName)
4927: {
4928: xmlSchemaIDCPtr ret = NULL;
4929:
4930: if ((name == NULL) || (schema == NULL))
4931: return (NULL);
4932: if (schema != NULL) {
4933: WXS_FIND_GLOBAL_ITEM(idcDef)
4934: }
4935: exit:
4936: return (ret);
4937: }
4938:
4939: /**
4940: * xmlSchemaGetNamedComponent:
4941: * @schema: the schema
4942: * @name: the name of the group
4943: * @ns: the target namespace of the group
4944: *
4945: * Lookup a group in the schema or imported schemas
4946: *
4947: * Returns the group definition or NULL if not found.
4948: */
4949: static xmlSchemaBasicItemPtr
4950: xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4951: xmlSchemaTypeType itemType,
4952: const xmlChar *name,
4953: const xmlChar *targetNs)
4954: {
4955: switch (itemType) {
4956: case XML_SCHEMA_TYPE_GROUP:
4957: return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4958: name, targetNs));
4959: case XML_SCHEMA_TYPE_ELEMENT:
4960: return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4961: name, targetNs));
4962: default:
4963: TODO
4964: return (NULL);
4965: }
4966: }
4967:
4968: /************************************************************************
4969: * *
4970: * Parsing functions *
4971: * *
4972: ************************************************************************/
4973:
4974: #define IS_BLANK_NODE(n) \
4975: (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4976:
4977: /**
4978: * xmlSchemaIsBlank:
4979: * @str: a string
4980: * @len: the length of the string or -1
4981: *
4982: * Check if a string is ignorable
4983: *
4984: * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4985: */
4986: static int
4987: xmlSchemaIsBlank(xmlChar * str, int len)
4988: {
4989: if (str == NULL)
4990: return (1);
4991: if (len < 0) {
4992: while (*str != 0) {
4993: if (!(IS_BLANK_CH(*str)))
4994: return (0);
4995: str++;
4996: }
4997: } else while ((*str != 0) && (len != 0)) {
4998: if (!(IS_BLANK_CH(*str)))
4999: return (0);
5000: str++;
5001: len--;
5002: }
5003:
5004: return (1);
5005: }
5006:
5007: #define WXS_COMP_NAME(c, t) ((t) (c))->name
5008: #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5009: /*
5010: * xmlSchemaFindRedefCompInGraph:
5011: * ATTENTION TODO: This uses pointer comp. for strings.
5012: */
5013: static xmlSchemaBasicItemPtr
5014: xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5015: xmlSchemaTypeType type,
5016: const xmlChar *name,
5017: const xmlChar *nsName)
5018: {
5019: xmlSchemaBasicItemPtr ret;
5020: int i;
5021:
5022: if ((bucket == NULL) || (name == NULL))
5023: return(NULL);
5024: if ((bucket->globals == NULL) ||
5025: (bucket->globals->nbItems == 0))
5026: goto subschemas;
5027: /*
5028: * Search in global components.
5029: */
5030: for (i = 0; i < bucket->globals->nbItems; i++) {
5031: ret = bucket->globals->items[i];
5032: if (ret->type == type) {
5033: switch (type) {
5034: case XML_SCHEMA_TYPE_COMPLEX:
5035: case XML_SCHEMA_TYPE_SIMPLE:
5036: if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5037: (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5038: nsName))
5039: {
5040: return(ret);
5041: }
5042: break;
5043: case XML_SCHEMA_TYPE_GROUP:
5044: if ((WXS_COMP_NAME(ret,
5045: xmlSchemaModelGroupDefPtr) == name) &&
5046: (WXS_COMP_TNS(ret,
5047: xmlSchemaModelGroupDefPtr) == nsName))
5048: {
5049: return(ret);
5050: }
5051: break;
5052: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5053: if ((WXS_COMP_NAME(ret,
5054: xmlSchemaAttributeGroupPtr) == name) &&
5055: (WXS_COMP_TNS(ret,
5056: xmlSchemaAttributeGroupPtr) == nsName))
5057: {
5058: return(ret);
5059: }
5060: break;
5061: default:
5062: /* Should not be hit. */
5063: return(NULL);
5064: }
5065: }
5066: }
5067: subschemas:
5068: /*
5069: * Process imported/included schemas.
5070: */
5071: if (bucket->relations != NULL) {
5072: xmlSchemaSchemaRelationPtr rel = bucket->relations;
5073:
5074: /*
5075: * TODO: Marking the bucket will not avoid multiple searches
5076: * in the same schema, but avoids at least circularity.
5077: */
5078: bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5079: do {
5080: if ((rel->bucket != NULL) &&
5081: ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5082: ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5083: type, name, nsName);
5084: if (ret != NULL)
5085: return(ret);
5086: }
5087: rel = rel->next;
5088: } while (rel != NULL);
5089: bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5090: }
5091: return(NULL);
5092: }
5093:
5094: /**
5095: * xmlSchemaAddNotation:
5096: * @ctxt: a schema parser context
5097: * @schema: the schema being built
5098: * @name: the item name
5099: *
5100: * Add an XML schema annotation declaration
5101: * *WARNING* this interface is highly subject to change
5102: *
5103: * Returns the new struture or NULL in case of error
5104: */
5105: static xmlSchemaNotationPtr
5106: xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5107: const xmlChar *name, const xmlChar *nsName,
5108: xmlNodePtr node ATTRIBUTE_UNUSED)
5109: {
5110: xmlSchemaNotationPtr ret = NULL;
5111:
5112: if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5113: return (NULL);
5114:
5115: ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5116: if (ret == NULL) {
5117: xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5118: return (NULL);
5119: }
5120: memset(ret, 0, sizeof(xmlSchemaNotation));
5121: ret->type = XML_SCHEMA_TYPE_NOTATION;
5122: ret->name = name;
5123: ret->targetNamespace = nsName;
5124: /* TODO: do we need the node to be set?
5125: * ret->node = node;*/
5126: WXS_ADD_GLOBAL(ctxt, ret);
5127: return (ret);
5128: }
5129:
5130: /**
5131: * xmlSchemaAddAttribute:
5132: * @ctxt: a schema parser context
5133: * @schema: the schema being built
5134: * @name: the item name
5135: * @namespace: the namespace
5136: *
5137: * Add an XML schema Attrribute declaration
5138: * *WARNING* this interface is highly subject to change
5139: *
5140: * Returns the new struture or NULL in case of error
5141: */
5142: static xmlSchemaAttributePtr
5143: xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5144: const xmlChar * name, const xmlChar * nsName,
5145: xmlNodePtr node, int topLevel)
5146: {
5147: xmlSchemaAttributePtr ret = NULL;
5148:
5149: if ((ctxt == NULL) || (schema == NULL))
5150: return (NULL);
5151:
5152: ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5153: if (ret == NULL) {
5154: xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5155: return (NULL);
5156: }
5157: memset(ret, 0, sizeof(xmlSchemaAttribute));
5158: ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5159: ret->node = node;
5160: ret->name = name;
5161: ret->targetNamespace = nsName;
5162:
5163: if (topLevel)
5164: WXS_ADD_GLOBAL(ctxt, ret);
5165: else
5166: WXS_ADD_LOCAL(ctxt, ret);
5167: WXS_ADD_PENDING(ctxt, ret);
5168: return (ret);
5169: }
5170:
5171: /**
5172: * xmlSchemaAddAttributeUse:
5173: * @ctxt: a schema parser context
5174: * @schema: the schema being built
5175: * @name: the item name
5176: * @namespace: the namespace
5177: *
5178: * Add an XML schema Attrribute declaration
5179: * *WARNING* this interface is highly subject to change
5180: *
5181: * Returns the new struture or NULL in case of error
5182: */
5183: static xmlSchemaAttributeUsePtr
5184: xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5185: xmlNodePtr node)
5186: {
5187: xmlSchemaAttributeUsePtr ret = NULL;
5188:
5189: if (pctxt == NULL)
5190: return (NULL);
5191:
5192: ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5193: if (ret == NULL) {
5194: xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5195: return (NULL);
5196: }
5197: memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5198: ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5199: ret->node = node;
5200:
5201: WXS_ADD_LOCAL(pctxt, ret);
5202: return (ret);
5203: }
5204:
5205: /*
5206: * xmlSchemaAddRedef:
5207: *
5208: * Adds a redefinition information. This is used at a later stage to:
5209: * resolve references to the redefined components and to check constraints.
5210: */
5211: static xmlSchemaRedefPtr
5212: xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5213: xmlSchemaBucketPtr targetBucket,
5214: void *item,
5215: const xmlChar *refName,
5216: const xmlChar *refTargetNs)
5217: {
5218: xmlSchemaRedefPtr ret;
5219:
5220: ret = (xmlSchemaRedefPtr)
5221: xmlMalloc(sizeof(xmlSchemaRedef));
5222: if (ret == NULL) {
5223: xmlSchemaPErrMemory(pctxt,
5224: "allocating redefinition info", NULL);
5225: return (NULL);
5226: }
5227: memset(ret, 0, sizeof(xmlSchemaRedef));
5228: ret->item = item;
5229: ret->targetBucket = targetBucket;
5230: ret->refName = refName;
5231: ret->refTargetNs = refTargetNs;
5232: if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5233: WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5234: else
5235: WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5236: WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5237:
5238: return (ret);
5239: }
5240:
5241: /**
5242: * xmlSchemaAddAttributeGroupDefinition:
5243: * @ctxt: a schema parser context
5244: * @schema: the schema being built
5245: * @name: the item name
5246: * @nsName: the target namespace
5247: * @node: the corresponding node
5248: *
5249: * Add an XML schema Attrribute Group definition.
5250: *
5251: * Returns the new struture or NULL in case of error
5252: */
5253: static xmlSchemaAttributeGroupPtr
5254: xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5255: xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5256: const xmlChar *name,
5257: const xmlChar *nsName,
5258: xmlNodePtr node)
5259: {
5260: xmlSchemaAttributeGroupPtr ret = NULL;
5261:
5262: if ((pctxt == NULL) || (name == NULL))
5263: return (NULL);
5264:
5265: ret = (xmlSchemaAttributeGroupPtr)
5266: xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5267: if (ret == NULL) {
5268: xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5269: return (NULL);
5270: }
5271: memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5272: ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5273: ret->name = name;
5274: ret->targetNamespace = nsName;
5275: ret->node = node;
5276:
5277: /* TODO: Remove the flag. */
5278: ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5279: if (pctxt->isRedefine) {
5280: pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5281: ret, name, nsName);
5282: if (pctxt->redef == NULL) {
5283: xmlFree(ret);
5284: return(NULL);
5285: }
5286: pctxt->redefCounter = 0;
5287: }
5288: WXS_ADD_GLOBAL(pctxt, ret);
5289: WXS_ADD_PENDING(pctxt, ret);
5290: return (ret);
5291: }
5292:
5293: /**
5294: * xmlSchemaAddElement:
5295: * @ctxt: a schema parser context
5296: * @schema: the schema being built
5297: * @name: the type name
5298: * @namespace: the type namespace
5299: *
5300: * Add an XML schema Element declaration
5301: * *WARNING* this interface is highly subject to change
5302: *
5303: * Returns the new struture or NULL in case of error
5304: */
5305: static xmlSchemaElementPtr
5306: xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5307: const xmlChar * name, const xmlChar * nsName,
5308: xmlNodePtr node, int topLevel)
5309: {
5310: xmlSchemaElementPtr ret = NULL;
5311:
5312: if ((ctxt == NULL) || (name == NULL))
5313: return (NULL);
5314:
5315: ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5316: if (ret == NULL) {
5317: xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5318: return (NULL);
5319: }
5320: memset(ret, 0, sizeof(xmlSchemaElement));
5321: ret->type = XML_SCHEMA_TYPE_ELEMENT;
5322: ret->name = name;
5323: ret->targetNamespace = nsName;
5324: ret->node = node;
5325:
5326: if (topLevel)
5327: WXS_ADD_GLOBAL(ctxt, ret);
5328: else
5329: WXS_ADD_LOCAL(ctxt, ret);
5330: WXS_ADD_PENDING(ctxt, ret);
5331: return (ret);
5332: }
5333:
5334: /**
5335: * xmlSchemaAddType:
5336: * @ctxt: a schema parser context
5337: * @schema: the schema being built
5338: * @name: the item name
5339: * @namespace: the namespace
5340: *
5341: * Add an XML schema item
5342: * *WARNING* this interface is highly subject to change
5343: *
5344: * Returns the new struture or NULL in case of error
5345: */
5346: static xmlSchemaTypePtr
5347: xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5348: xmlSchemaTypeType type,
5349: const xmlChar * name, const xmlChar * nsName,
5350: xmlNodePtr node, int topLevel)
5351: {
5352: xmlSchemaTypePtr ret = NULL;
5353:
5354: if ((ctxt == NULL) || (schema == NULL))
5355: return (NULL);
5356:
5357: ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5358: if (ret == NULL) {
5359: xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5360: return (NULL);
5361: }
5362: memset(ret, 0, sizeof(xmlSchemaType));
5363: ret->type = type;
5364: ret->name = name;
5365: ret->targetNamespace = nsName;
5366: ret->node = node;
5367: if (topLevel) {
5368: if (ctxt->isRedefine) {
5369: ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5370: ret, name, nsName);
5371: if (ctxt->redef == NULL) {
5372: xmlFree(ret);
5373: return(NULL);
5374: }
5375: ctxt->redefCounter = 0;
5376: }
5377: WXS_ADD_GLOBAL(ctxt, ret);
5378: } else
5379: WXS_ADD_LOCAL(ctxt, ret);
5380: WXS_ADD_PENDING(ctxt, ret);
5381: return (ret);
5382: }
5383:
5384: static xmlSchemaQNameRefPtr
5385: xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5386: xmlSchemaTypeType refType,
5387: const xmlChar *refName,
5388: const xmlChar *refNs)
5389: {
5390: xmlSchemaQNameRefPtr ret;
5391:
5392: ret = (xmlSchemaQNameRefPtr)
5393: xmlMalloc(sizeof(xmlSchemaQNameRef));
5394: if (ret == NULL) {
5395: xmlSchemaPErrMemory(pctxt,
5396: "allocating QName reference item", NULL);
5397: return (NULL);
5398: }
5399: ret->node = NULL;
5400: ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5401: ret->name = refName;
5402: ret->targetNamespace = refNs;
5403: ret->item = NULL;
5404: ret->itemType = refType;
5405: /*
5406: * Store the reference item in the schema.
5407: */
5408: WXS_ADD_LOCAL(pctxt, ret);
5409: return (ret);
5410: }
5411:
5412: static xmlSchemaAttributeUseProhibPtr
5413: xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5414: {
5415: xmlSchemaAttributeUseProhibPtr ret;
5416:
5417: ret = (xmlSchemaAttributeUseProhibPtr)
5418: xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5419: if (ret == NULL) {
5420: xmlSchemaPErrMemory(pctxt,
5421: "allocating attribute use prohibition", NULL);
5422: return (NULL);
5423: }
5424: memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5425: ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5426: WXS_ADD_LOCAL(pctxt, ret);
5427: return (ret);
5428: }
5429:
5430:
5431: /**
5432: * xmlSchemaAddModelGroup:
5433: * @ctxt: a schema parser context
5434: * @schema: the schema being built
5435: * @type: the "compositor" type of the model group
5436: * @node: the node in the schema doc
5437: *
5438: * Adds a schema model group
5439: * *WARNING* this interface is highly subject to change
5440: *
5441: * Returns the new struture or NULL in case of error
5442: */
5443: static xmlSchemaModelGroupPtr
5444: xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5445: xmlSchemaPtr schema,
5446: xmlSchemaTypeType type,
5447: xmlNodePtr node)
5448: {
5449: xmlSchemaModelGroupPtr ret = NULL;
5450:
5451: if ((ctxt == NULL) || (schema == NULL))
5452: return (NULL);
5453:
5454: ret = (xmlSchemaModelGroupPtr)
5455: xmlMalloc(sizeof(xmlSchemaModelGroup));
5456: if (ret == NULL) {
5457: xmlSchemaPErrMemory(ctxt, "allocating model group component",
5458: NULL);
5459: return (NULL);
5460: }
5461: memset(ret, 0, sizeof(xmlSchemaModelGroup));
5462: ret->type = type;
5463: ret->node = node;
5464: WXS_ADD_LOCAL(ctxt, ret);
5465: if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5466: (type == XML_SCHEMA_TYPE_CHOICE))
5467: WXS_ADD_PENDING(ctxt, ret);
5468: return (ret);
5469: }
5470:
5471:
5472: /**
5473: * xmlSchemaAddParticle:
5474: * @ctxt: a schema parser context
5475: * @schema: the schema being built
5476: * @node: the corresponding node in the schema doc
5477: * @min: the minOccurs
5478: * @max: the maxOccurs
5479: *
5480: * Adds an XML schema particle component.
5481: * *WARNING* this interface is highly subject to change
5482: *
5483: * Returns the new struture or NULL in case of error
5484: */
5485: static xmlSchemaParticlePtr
5486: xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5487: xmlNodePtr node, int min, int max)
5488: {
5489: xmlSchemaParticlePtr ret = NULL;
5490: if (ctxt == NULL)
5491: return (NULL);
5492:
5493: #ifdef DEBUG
5494: fprintf(stderr, "Adding particle component\n");
5495: #endif
5496: ret = (xmlSchemaParticlePtr)
5497: xmlMalloc(sizeof(xmlSchemaParticle));
5498: if (ret == NULL) {
5499: xmlSchemaPErrMemory(ctxt, "allocating particle component",
5500: NULL);
5501: return (NULL);
5502: }
5503: ret->type = XML_SCHEMA_TYPE_PARTICLE;
5504: ret->annot = NULL;
5505: ret->node = node;
5506: ret->minOccurs = min;
5507: ret->maxOccurs = max;
5508: ret->next = NULL;
5509: ret->children = NULL;
5510:
5511: WXS_ADD_LOCAL(ctxt, ret);
5512: /*
5513: * Note that addition to pending components will be done locally
5514: * to the specific parsing function, since the most particles
5515: * need not to be fixed up (i.e. the reference to be resolved).
5516: * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5517: */
5518: return (ret);
5519: }
5520:
5521: /**
5522: * xmlSchemaAddModelGroupDefinition:
5523: * @ctxt: a schema validation context
5524: * @schema: the schema being built
5525: * @name: the group name
5526: *
5527: * Add an XML schema Group definition
5528: *
5529: * Returns the new struture or NULL in case of error
5530: */
5531: static xmlSchemaModelGroupDefPtr
5532: xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5533: xmlSchemaPtr schema,
5534: const xmlChar *name,
5535: const xmlChar *nsName,
5536: xmlNodePtr node)
5537: {
5538: xmlSchemaModelGroupDefPtr ret = NULL;
5539:
5540: if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5541: return (NULL);
5542:
5543: ret = (xmlSchemaModelGroupDefPtr)
5544: xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5545: if (ret == NULL) {
5546: xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5547: return (NULL);
5548: }
5549: memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5550: ret->name = name;
5551: ret->type = XML_SCHEMA_TYPE_GROUP;
5552: ret->node = node;
5553: ret->targetNamespace = nsName;
5554:
5555: if (ctxt->isRedefine) {
5556: ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5557: ret, name, nsName);
5558: if (ctxt->redef == NULL) {
5559: xmlFree(ret);
5560: return(NULL);
5561: }
5562: ctxt->redefCounter = 0;
5563: }
5564: WXS_ADD_GLOBAL(ctxt, ret);
5565: WXS_ADD_PENDING(ctxt, ret);
5566: return (ret);
5567: }
5568:
5569: /**
5570: * xmlSchemaNewWildcardNs:
5571: * @ctxt: a schema validation context
5572: *
5573: * Creates a new wildcard namespace constraint.
5574: *
5575: * Returns the new struture or NULL in case of error
5576: */
5577: static xmlSchemaWildcardNsPtr
5578: xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5579: {
5580: xmlSchemaWildcardNsPtr ret;
5581:
5582: ret = (xmlSchemaWildcardNsPtr)
5583: xmlMalloc(sizeof(xmlSchemaWildcardNs));
5584: if (ret == NULL) {
5585: xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5586: return (NULL);
5587: }
5588: ret->value = NULL;
5589: ret->next = NULL;
5590: return (ret);
5591: }
5592:
5593: static xmlSchemaIDCPtr
5594: xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5595: const xmlChar *name, const xmlChar *nsName,
5596: int category, xmlNodePtr node)
5597: {
5598: xmlSchemaIDCPtr ret = NULL;
5599:
5600: if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5601: return (NULL);
5602:
5603: ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5604: if (ret == NULL) {
5605: xmlSchemaPErrMemory(ctxt,
5606: "allocating an identity-constraint definition", NULL);
5607: return (NULL);
5608: }
5609: memset(ret, 0, sizeof(xmlSchemaIDC));
5610: /* The target namespace of the parent element declaration. */
5611: ret->targetNamespace = nsName;
5612: ret->name = name;
5613: ret->type = category;
5614: ret->node = node;
5615:
5616: WXS_ADD_GLOBAL(ctxt, ret);
5617: /*
5618: * Only keyrefs need to be fixup up.
5619: */
5620: if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5621: WXS_ADD_PENDING(ctxt, ret);
5622: return (ret);
5623: }
5624:
5625: /**
5626: * xmlSchemaAddWildcard:
5627: * @ctxt: a schema validation context
5628: * @schema: a schema
5629: *
5630: * Adds a wildcard.
5631: * It corresponds to a xsd:anyAttribute and xsd:any.
5632: *
5633: * Returns the new struture or NULL in case of error
5634: */
5635: static xmlSchemaWildcardPtr
5636: xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5637: xmlSchemaTypeType type, xmlNodePtr node)
5638: {
5639: xmlSchemaWildcardPtr ret = NULL;
5640:
5641: if ((ctxt == NULL) || (schema == NULL))
5642: return (NULL);
5643:
5644: ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5645: if (ret == NULL) {
5646: xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5647: return (NULL);
5648: }
5649: memset(ret, 0, sizeof(xmlSchemaWildcard));
5650: ret->type = type;
5651: ret->node = node;
5652: WXS_ADD_LOCAL(ctxt, ret);
5653: return (ret);
5654: }
5655:
5656: static void
5657: xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5658: {
5659: if (group == NULL)
5660: return;
5661: if (group->members != NULL)
5662: xmlSchemaItemListFree(group->members);
5663: xmlFree(group);
5664: }
5665:
5666: static xmlSchemaSubstGroupPtr
5667: xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5668: xmlSchemaElementPtr head)
5669: {
5670: xmlSchemaSubstGroupPtr ret;
5671:
5672: /* Init subst group hash. */
5673: if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5674: WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5675: if (WXS_SUBST_GROUPS(pctxt) == NULL)
5676: return(NULL);
5677: }
5678: /* Create a new substitution group. */
5679: ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5680: if (ret == NULL) {
5681: xmlSchemaPErrMemory(NULL,
5682: "allocating a substitution group container", NULL);
5683: return(NULL);
5684: }
5685: memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5686: ret->head = head;
5687: /* Create list of members. */
5688: ret->members = xmlSchemaItemListCreate();
5689: if (ret->members == NULL) {
5690: xmlSchemaSubstGroupFree(ret);
5691: return(NULL);
5692: }
5693: /* Add subst group to hash. */
5694: if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5695: head->name, head->targetNamespace, ret) != 0) {
5696: PERROR_INT("xmlSchemaSubstGroupAdd",
5697: "failed to add a new substitution container");
5698: xmlSchemaSubstGroupFree(ret);
5699: return(NULL);
5700: }
5701: return(ret);
5702: }
5703:
5704: static xmlSchemaSubstGroupPtr
5705: xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5706: xmlSchemaElementPtr head)
5707: {
5708: if (WXS_SUBST_GROUPS(pctxt) == NULL)
5709: return(NULL);
5710: return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5711: head->name, head->targetNamespace));
5712:
5713: }
5714:
5715: /**
5716: * xmlSchemaAddElementSubstitutionMember:
5717: * @pctxt: a schema parser context
5718: * @head: the head of the substitution group
5719: * @member: the new member of the substitution group
5720: *
5721: * Allocate a new annotation structure.
5722: *
5723: * Returns the newly allocated structure or NULL in case or error
5724: */
5725: static int
5726: xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5727: xmlSchemaElementPtr head,
5728: xmlSchemaElementPtr member)
5729: {
5730: xmlSchemaSubstGroupPtr substGroup = NULL;
5731:
5732: if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5733: return (-1);
5734:
5735: substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5736: if (substGroup == NULL)
5737: substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5738: if (substGroup == NULL)
5739: return(-1);
5740: if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5741: return(-1);
5742: return(0);
5743: }
5744:
5745: /************************************************************************
5746: * *
5747: * Utilities for parsing *
5748: * *
5749: ************************************************************************/
5750:
5751: /**
5752: * xmlSchemaPValAttrNodeQNameValue:
5753: * @ctxt: a schema parser context
5754: * @schema: the schema context
5755: * @ownerDes: the designation of the parent element
5756: * @ownerItem: the parent as a schema object
5757: * @value: the QName value
5758: * @local: the resulting local part if found, the attribute value otherwise
5759: * @uri: the resulting namespace URI if found
5760: *
5761: * Extracts the local name and the URI of a QName value and validates it.
5762: * This one is intended to be used on attribute values that
5763: * should resolve to schema components.
5764: *
5765: * Returns 0, in case the QName is valid, a positive error code
5766: * if not valid and -1 if an internal error occurs.
5767: */
5768: static int
5769: xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5770: xmlSchemaPtr schema,
5771: xmlSchemaBasicItemPtr ownerItem,
5772: xmlAttrPtr attr,
5773: const xmlChar *value,
5774: const xmlChar **uri,
5775: const xmlChar **local)
5776: {
5777: const xmlChar *pref;
5778: xmlNsPtr ns;
5779: int len, ret;
5780:
5781: *uri = NULL;
5782: *local = NULL;
5783: ret = xmlValidateQName(value, 1);
5784: if (ret > 0) {
5785: xmlSchemaPSimpleTypeErr(ctxt,
5786: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5787: ownerItem, (xmlNodePtr) attr,
5788: xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5789: NULL, value, NULL, NULL, NULL);
5790: *local = value;
5791: return (ctxt->err);
5792: } else if (ret < 0)
5793: return (-1);
5794:
5795: if (!strchr((char *) value, ':')) {
5796: ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5797: if (ns)
5798: *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5799: else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5800: /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5801: * parser context. */
5802: /*
5803: * This one takes care of included schemas with no
5804: * target namespace.
5805: */
5806: *uri = ctxt->targetNamespace;
5807: }
5808: *local = xmlDictLookup(ctxt->dict, value, -1);
5809: return (0);
5810: }
5811: /*
5812: * At this point xmlSplitQName3 has to return a local name.
5813: */
5814: *local = xmlSplitQName3(value, &len);
5815: *local = xmlDictLookup(ctxt->dict, *local, -1);
5816: pref = xmlDictLookup(ctxt->dict, value, len);
5817: ns = xmlSearchNs(attr->doc, attr->parent, pref);
5818: if (ns == NULL) {
5819: xmlSchemaPSimpleTypeErr(ctxt,
5820: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5821: ownerItem, (xmlNodePtr) attr,
5822: xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5823: "The value '%s' of simple type 'xs:QName' has no "
5824: "corresponding namespace declaration in scope", value, NULL);
5825: return (ctxt->err);
5826: } else {
5827: *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5828: }
5829: return (0);
5830: }
5831:
5832: /**
5833: * xmlSchemaPValAttrNodeQName:
5834: * @ctxt: a schema parser context
5835: * @schema: the schema context
5836: * @ownerDes: the designation of the owner element
5837: * @ownerItem: the owner as a schema object
5838: * @attr: the attribute node
5839: * @local: the resulting local part if found, the attribute value otherwise
5840: * @uri: the resulting namespace URI if found
5841: *
5842: * Extracts and validates the QName of an attribute value.
5843: * This one is intended to be used on attribute values that
5844: * should resolve to schema components.
5845: *
5846: * Returns 0, in case the QName is valid, a positive error code
5847: * if not valid and -1 if an internal error occurs.
5848: */
5849: static int
5850: xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5851: xmlSchemaPtr schema,
5852: xmlSchemaBasicItemPtr ownerItem,
5853: xmlAttrPtr attr,
5854: const xmlChar **uri,
5855: const xmlChar **local)
5856: {
5857: const xmlChar *value;
5858:
5859: value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5860: return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5861: ownerItem, attr, value, uri, local));
5862: }
5863:
5864: /**
5865: * xmlSchemaPValAttrQName:
5866: * @ctxt: a schema parser context
5867: * @schema: the schema context
5868: * @ownerDes: the designation of the parent element
5869: * @ownerItem: the owner as a schema object
5870: * @ownerElem: the parent node of the attribute
5871: * @name: the name of the attribute
5872: * @local: the resulting local part if found, the attribute value otherwise
5873: * @uri: the resulting namespace URI if found
5874: *
5875: * Extracts and validates the QName of an attribute value.
5876: *
5877: * Returns 0, in case the QName is valid, a positive error code
5878: * if not valid and -1 if an internal error occurs.
5879: */
5880: static int
5881: xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5882: xmlSchemaPtr schema,
5883: xmlSchemaBasicItemPtr ownerItem,
5884: xmlNodePtr ownerElem,
5885: const char *name,
5886: const xmlChar **uri,
5887: const xmlChar **local)
5888: {
5889: xmlAttrPtr attr;
5890:
5891: attr = xmlSchemaGetPropNode(ownerElem, name);
5892: if (attr == NULL) {
5893: *local = NULL;
5894: *uri = NULL;
5895: return (0);
5896: }
5897: return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5898: ownerItem, attr, uri, local));
5899: }
5900:
5901: /**
5902: * xmlSchemaPValAttrID:
5903: * @ctxt: a schema parser context
5904: * @schema: the schema context
5905: * @ownerDes: the designation of the parent element
5906: * @ownerItem: the owner as a schema object
5907: * @ownerElem: the parent node of the attribute
5908: * @name: the name of the attribute
5909: *
5910: * Extracts and validates the ID of an attribute value.
5911: *
5912: * Returns 0, in case the ID is valid, a positive error code
5913: * if not valid and -1 if an internal error occurs.
5914: */
5915: static int
5916: xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5917: {
5918: int ret;
5919: const xmlChar *value;
5920:
5921: if (attr == NULL)
5922: return(0);
5923: value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5924: ret = xmlValidateNCName(value, 1);
5925: if (ret == 0) {
5926: /*
5927: * NOTE: the IDness might have already be declared in the DTD
5928: */
5929: if (attr->atype != XML_ATTRIBUTE_ID) {
5930: xmlIDPtr res;
5931: xmlChar *strip;
5932:
5933: /*
5934: * TODO: Use xmlSchemaStrip here; it's not exported at this
5935: * moment.
5936: */
5937: strip = xmlSchemaCollapseString(value);
5938: if (strip != NULL) {
5939: xmlFree((xmlChar *) value);
5940: value = strip;
5941: }
5942: res = xmlAddID(NULL, attr->doc, value, attr);
5943: if (res == NULL) {
5944: ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5945: xmlSchemaPSimpleTypeErr(ctxt,
5946: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5947: NULL, (xmlNodePtr) attr,
5948: xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5949: NULL, NULL, "Duplicate value '%s' of simple "
5950: "type 'xs:ID'", value, NULL);
5951: } else
5952: attr->atype = XML_ATTRIBUTE_ID;
5953: }
5954: } else if (ret > 0) {
5955: ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5956: xmlSchemaPSimpleTypeErr(ctxt,
5957: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5958: NULL, (xmlNodePtr) attr,
5959: xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5960: NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5961: "not a valid 'xs:NCName'",
5962: value, NULL);
5963: }
5964: if (value != NULL)
5965: xmlFree((xmlChar *)value);
5966:
5967: return (ret);
5968: }
5969:
5970: static int
5971: xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5972: xmlNodePtr ownerElem,
5973: const xmlChar *name)
5974: {
5975: xmlAttrPtr attr;
5976:
5977: attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5978: if (attr == NULL)
5979: return(0);
5980: return(xmlSchemaPValAttrNodeID(ctxt, attr));
5981:
5982: }
5983:
5984: /**
5985: * xmlGetMaxOccurs:
5986: * @ctxt: a schema validation context
5987: * @node: a subtree containing XML Schema informations
5988: *
5989: * Get the maxOccurs property
5990: *
5991: * Returns the default if not found, or the value
5992: */
5993: static int
5994: xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5995: int min, int max, int def, const char *expected)
5996: {
5997: const xmlChar *val, *cur;
5998: int ret = 0;
5999: xmlAttrPtr attr;
6000:
6001: attr = xmlSchemaGetPropNode(node, "maxOccurs");
6002: if (attr == NULL)
6003: return (def);
6004: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6005:
6006: if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6007: if (max != UNBOUNDED) {
6008: xmlSchemaPSimpleTypeErr(ctxt,
6009: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6010: /* XML_SCHEMAP_INVALID_MINOCCURS, */
6011: NULL, (xmlNodePtr) attr, NULL, expected,
6012: val, NULL, NULL, NULL);
6013: return (def);
6014: } else
6015: return (UNBOUNDED); /* encoding it with -1 might be another option */
6016: }
6017:
6018: cur = val;
6019: while (IS_BLANK_CH(*cur))
6020: cur++;
6021: if (*cur == 0) {
6022: xmlSchemaPSimpleTypeErr(ctxt,
6023: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6024: /* XML_SCHEMAP_INVALID_MINOCCURS, */
6025: NULL, (xmlNodePtr) attr, NULL, expected,
6026: val, NULL, NULL, NULL);
6027: return (def);
6028: }
6029: while ((*cur >= '0') && (*cur <= '9')) {
6030: ret = ret * 10 + (*cur - '0');
6031: cur++;
6032: }
6033: while (IS_BLANK_CH(*cur))
6034: cur++;
6035: /*
6036: * TODO: Restrict the maximal value to Integer.
6037: */
6038: if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6039: xmlSchemaPSimpleTypeErr(ctxt,
6040: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6041: /* XML_SCHEMAP_INVALID_MINOCCURS, */
6042: NULL, (xmlNodePtr) attr, NULL, expected,
6043: val, NULL, NULL, NULL);
6044: return (def);
6045: }
6046: return (ret);
6047: }
6048:
6049: /**
6050: * xmlGetMinOccurs:
6051: * @ctxt: a schema validation context
6052: * @node: a subtree containing XML Schema informations
6053: *
6054: * Get the minOccurs property
6055: *
6056: * Returns the default if not found, or the value
6057: */
6058: static int
6059: xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6060: int min, int max, int def, const char *expected)
6061: {
6062: const xmlChar *val, *cur;
6063: int ret = 0;
6064: xmlAttrPtr attr;
6065:
6066: attr = xmlSchemaGetPropNode(node, "minOccurs");
6067: if (attr == NULL)
6068: return (def);
6069: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6070: cur = val;
6071: while (IS_BLANK_CH(*cur))
6072: cur++;
6073: if (*cur == 0) {
6074: xmlSchemaPSimpleTypeErr(ctxt,
6075: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6076: /* XML_SCHEMAP_INVALID_MINOCCURS, */
6077: NULL, (xmlNodePtr) attr, NULL, expected,
6078: val, NULL, NULL, NULL);
6079: return (def);
6080: }
6081: while ((*cur >= '0') && (*cur <= '9')) {
6082: ret = ret * 10 + (*cur - '0');
6083: cur++;
6084: }
6085: while (IS_BLANK_CH(*cur))
6086: cur++;
6087: /*
6088: * TODO: Restrict the maximal value to Integer.
6089: */
6090: if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6091: xmlSchemaPSimpleTypeErr(ctxt,
6092: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6093: /* XML_SCHEMAP_INVALID_MINOCCURS, */
6094: NULL, (xmlNodePtr) attr, NULL, expected,
6095: val, NULL, NULL, NULL);
6096: return (def);
6097: }
6098: return (ret);
6099: }
6100:
6101: /**
6102: * xmlSchemaPGetBoolNodeValue:
6103: * @ctxt: a schema validation context
6104: * @ownerDes: owner designation
6105: * @ownerItem: the owner as a schema item
6106: * @node: the node holding the value
6107: *
6108: * Converts a boolean string value into 1 or 0.
6109: *
6110: * Returns 0 or 1.
6111: */
6112: static int
6113: xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6114: xmlSchemaBasicItemPtr ownerItem,
6115: xmlNodePtr node)
6116: {
6117: xmlChar *value = NULL;
6118: int res = 0;
6119:
6120: value = xmlNodeGetContent(node);
6121: /*
6122: * 3.2.2.1 Lexical representation
6123: * An instance of a datatype that is defined as �boolean�
6124: * can have the following legal literals {true, false, 1, 0}.
6125: */
6126: if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6127: res = 1;
6128: else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6129: res = 0;
6130: else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6131: res = 1;
6132: else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6133: res = 0;
6134: else {
6135: xmlSchemaPSimpleTypeErr(ctxt,
6136: XML_SCHEMAP_INVALID_BOOLEAN,
6137: ownerItem, node,
6138: xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6139: NULL, BAD_CAST value,
6140: NULL, NULL, NULL);
6141: }
6142: if (value != NULL)
6143: xmlFree(value);
6144: return (res);
6145: }
6146:
6147: /**
6148: * xmlGetBooleanProp:
6149: * @ctxt: a schema validation context
6150: * @node: a subtree containing XML Schema informations
6151: * @name: the attribute name
6152: * @def: the default value
6153: *
6154: * Evaluate if a boolean property is set
6155: *
6156: * Returns the default if not found, 0 if found to be false,
6157: * 1 if found to be true
6158: */
6159: static int
6160: xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6161: xmlNodePtr node,
6162: const char *name, int def)
6163: {
6164: const xmlChar *val;
6165:
6166: val = xmlSchemaGetProp(ctxt, node, name);
6167: if (val == NULL)
6168: return (def);
6169: /*
6170: * 3.2.2.1 Lexical representation
6171: * An instance of a datatype that is defined as �boolean�
6172: * can have the following legal literals {true, false, 1, 0}.
6173: */
6174: if (xmlStrEqual(val, BAD_CAST "true"))
6175: def = 1;
6176: else if (xmlStrEqual(val, BAD_CAST "false"))
6177: def = 0;
6178: else if (xmlStrEqual(val, BAD_CAST "1"))
6179: def = 1;
6180: else if (xmlStrEqual(val, BAD_CAST "0"))
6181: def = 0;
6182: else {
6183: xmlSchemaPSimpleTypeErr(ctxt,
6184: XML_SCHEMAP_INVALID_BOOLEAN,
6185: NULL,
6186: (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6187: xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6188: NULL, val, NULL, NULL, NULL);
6189: }
6190: return (def);
6191: }
6192:
6193: /************************************************************************
6194: * *
6195: * Shema extraction from an Infoset *
6196: * *
6197: ************************************************************************/
6198: static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6199: ctxt, xmlSchemaPtr schema,
6200: xmlNodePtr node,
6201: int topLevel);
6202: static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6203: ctxt,
6204: xmlSchemaPtr schema,
6205: xmlNodePtr node,
6206: int topLevel);
6207: static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6208: ctxt,
6209: xmlSchemaPtr schema,
6210: xmlNodePtr node,
6211: xmlSchemaTypeType parentType);
6212: static xmlSchemaBasicItemPtr
6213: xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6214: xmlSchemaPtr schema,
6215: xmlNodePtr node,
6216: xmlSchemaItemListPtr uses,
6217: int parentType);
6218: static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6219: xmlSchemaPtr schema,
6220: xmlNodePtr node);
6221: static xmlSchemaWildcardPtr
6222: xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6223: xmlSchemaPtr schema, xmlNodePtr node);
6224:
6225: /**
6226: * xmlSchemaPValAttrNodeValue:
6227: *
6228: * @ctxt: a schema parser context
6229: * @ownerDes: the designation of the parent element
6230: * @ownerItem: the schema object owner if existent
6231: * @attr: the schema attribute node being validated
6232: * @value: the value
6233: * @type: the built-in type to be validated against
6234: *
6235: * Validates a value against the given built-in type.
6236: * This one is intended to be used internally for validation
6237: * of schema attribute values during parsing of the schema.
6238: *
6239: * Returns 0 if the value is valid, a positive error code
6240: * number otherwise and -1 in case of an internal or API error.
6241: */
6242: static int
6243: xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6244: xmlSchemaBasicItemPtr ownerItem,
6245: xmlAttrPtr attr,
6246: const xmlChar *value,
6247: xmlSchemaTypePtr type)
6248: {
6249:
6250: int ret = 0;
6251:
6252: /*
6253: * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6254: * one is really meant to be used internally, so better not.
6255: */
6256: if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6257: return (-1);
6258: if (type->type != XML_SCHEMA_TYPE_BASIC) {
6259: PERROR_INT("xmlSchemaPValAttrNodeValue",
6260: "the given type is not a built-in type");
6261: return (-1);
6262: }
6263: switch (type->builtInType) {
6264: case XML_SCHEMAS_NCNAME:
6265: case XML_SCHEMAS_QNAME:
6266: case XML_SCHEMAS_ANYURI:
6267: case XML_SCHEMAS_TOKEN:
6268: case XML_SCHEMAS_LANGUAGE:
6269: ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6270: (xmlNodePtr) attr);
6271: break;
6272: default: {
6273: PERROR_INT("xmlSchemaPValAttrNodeValue",
6274: "validation using the given type is not supported while "
6275: "parsing a schema");
6276: return (-1);
6277: }
6278: }
6279: /*
6280: * TODO: Should we use the S4S error codes instead?
6281: */
6282: if (ret < 0) {
6283: PERROR_INT("xmlSchemaPValAttrNodeValue",
6284: "failed to validate a schema attribute value");
6285: return (-1);
6286: } else if (ret > 0) {
6287: if (WXS_IS_LIST(type))
6288: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6289: else
6290: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6291: xmlSchemaPSimpleTypeErr(pctxt,
6292: ret, ownerItem, (xmlNodePtr) attr,
6293: type, NULL, value, NULL, NULL, NULL);
6294: }
6295: return (ret);
6296: }
6297:
6298: /**
6299: * xmlSchemaPValAttrNode:
6300: *
6301: * @ctxt: a schema parser context
6302: * @ownerDes: the designation of the parent element
6303: * @ownerItem: the schema object owner if existent
6304: * @attr: the schema attribute node being validated
6305: * @type: the built-in type to be validated against
6306: * @value: the resulting value if any
6307: *
6308: * Extracts and validates a value against the given built-in type.
6309: * This one is intended to be used internally for validation
6310: * of schema attribute values during parsing of the schema.
6311: *
6312: * Returns 0 if the value is valid, a positive error code
6313: * number otherwise and -1 in case of an internal or API error.
6314: */
6315: static int
6316: xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6317: xmlSchemaBasicItemPtr ownerItem,
6318: xmlAttrPtr attr,
6319: xmlSchemaTypePtr type,
6320: const xmlChar **value)
6321: {
6322: const xmlChar *val;
6323:
6324: if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6325: return (-1);
6326:
6327: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6328: if (value != NULL)
6329: *value = val;
6330:
6331: return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6332: val, type));
6333: }
6334:
6335: /**
6336: * xmlSchemaPValAttr:
6337: *
6338: * @ctxt: a schema parser context
6339: * @node: the element node of the attribute
6340: * @ownerDes: the designation of the parent element
6341: * @ownerItem: the schema object owner if existent
6342: * @ownerElem: the owner element node
6343: * @name: the name of the schema attribute node
6344: * @type: the built-in type to be validated against
6345: * @value: the resulting value if any
6346: *
6347: * Extracts and validates a value against the given built-in type.
6348: * This one is intended to be used internally for validation
6349: * of schema attribute values during parsing of the schema.
6350: *
6351: * Returns 0 if the value is valid, a positive error code
6352: * number otherwise and -1 in case of an internal or API error.
6353: */
6354: static int
6355: xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6356: xmlSchemaBasicItemPtr ownerItem,
6357: xmlNodePtr ownerElem,
6358: const char *name,
6359: xmlSchemaTypePtr type,
6360: const xmlChar **value)
6361: {
6362: xmlAttrPtr attr;
6363:
6364: if ((ctxt == NULL) || (type == NULL)) {
6365: if (value != NULL)
6366: *value = NULL;
6367: return (-1);
6368: }
6369: if (type->type != XML_SCHEMA_TYPE_BASIC) {
6370: if (value != NULL)
6371: *value = NULL;
6372: xmlSchemaPErr(ctxt, ownerElem,
6373: XML_SCHEMAP_INTERNAL,
6374: "Internal error: xmlSchemaPValAttr, the given "
6375: "type '%s' is not a built-in type.\n",
6376: type->name, NULL);
6377: return (-1);
6378: }
6379: attr = xmlSchemaGetPropNode(ownerElem, name);
6380: if (attr == NULL) {
6381: if (value != NULL)
6382: *value = NULL;
6383: return (0);
6384: }
6385: return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6386: type, value));
6387: }
6388:
6389: static int
6390: xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6391: xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6392: xmlNodePtr node,
6393: xmlAttrPtr attr,
6394: const xmlChar *namespaceName)
6395: {
6396: /* TODO: Pointer comparison instead? */
6397: if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6398: return (0);
6399: if (xmlStrEqual(xmlSchemaNs, namespaceName))
6400: return (0);
6401: /*
6402: * Check if the referenced namespace was <import>ed.
6403: */
6404: if (WXS_BUCKET(pctxt)->relations != NULL) {
6405: xmlSchemaSchemaRelationPtr rel;
6406:
6407: rel = WXS_BUCKET(pctxt)->relations;
6408: do {
6409: if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6410: xmlStrEqual(namespaceName, rel->importNamespace))
6411: return (0);
6412: rel = rel->next;
6413: } while (rel != NULL);
6414: }
6415: /*
6416: * No matching <import>ed namespace found.
6417: */
6418: {
6419: xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6420:
6421: if (namespaceName == NULL)
6422: xmlSchemaCustomErr(ACTXT_CAST pctxt,
6423: XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6424: "References from this schema to components in no "
6425: "namespace are not allowed, since not indicated by an "
6426: "import statement", NULL, NULL);
6427: else
6428: xmlSchemaCustomErr(ACTXT_CAST pctxt,
6429: XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6430: "References from this schema to components in the "
6431: "namespace '%s' are not allowed, since not indicated by an "
6432: "import statement", namespaceName, NULL);
6433: }
6434: return (XML_SCHEMAP_SRC_RESOLVE);
6435: }
6436:
6437: /**
6438: * xmlSchemaParseLocalAttributes:
6439: * @ctxt: a schema validation context
6440: * @schema: the schema being built
6441: * @node: a subtree containing XML Schema informations
6442: * @type: the hosting type where the attributes will be anchored
6443: *
6444: * Parses attribute uses and attribute declarations and
6445: * attribute group references.
6446: */
6447: static int
6448: xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6449: xmlNodePtr *child, xmlSchemaItemListPtr *list,
6450: int parentType, int *hasRefs)
6451: {
6452: void *item;
6453:
6454: while ((IS_SCHEMA((*child), "attribute")) ||
6455: (IS_SCHEMA((*child), "attributeGroup"))) {
6456: if (IS_SCHEMA((*child), "attribute")) {
6457: item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6458: *list, parentType);
6459: } else {
6460: item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6461: if ((item != NULL) && (hasRefs != NULL))
6462: *hasRefs = 1;
6463: }
6464: if (item != NULL) {
6465: if (*list == NULL) {
6466: /* TODO: Customize grow factor. */
6467: *list = xmlSchemaItemListCreate();
6468: if (*list == NULL)
6469: return(-1);
6470: }
6471: if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6472: return(-1);
6473: }
6474: *child = (*child)->next;
6475: }
6476: return (0);
6477: }
6478:
6479: /**
6480: * xmlSchemaParseAnnotation:
6481: * @ctxt: a schema validation context
6482: * @schema: the schema being built
6483: * @node: a subtree containing XML Schema informations
6484: *
6485: * parse a XML schema Attrribute declaration
6486: * *WARNING* this interface is highly subject to change
6487: *
6488: * Returns -1 in case of error, 0 if the declaration is improper and
6489: * 1 in case of success.
6490: */
6491: static xmlSchemaAnnotPtr
6492: xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6493: {
6494: xmlSchemaAnnotPtr ret;
6495: xmlNodePtr child = NULL;
6496: xmlAttrPtr attr;
6497: int barked = 0;
6498:
6499: /*
6500: * INFO: S4S completed.
6501: */
6502: /*
6503: * id = ID
6504: * {any attributes with non-schema namespace . . .}>
6505: * Content: (appinfo | documentation)*
6506: */
6507: if ((ctxt == NULL) || (node == NULL))
6508: return (NULL);
6509: if (needed)
6510: ret = xmlSchemaNewAnnot(ctxt, node);
6511: else
6512: ret = NULL;
6513: attr = node->properties;
6514: while (attr != NULL) {
6515: if (((attr->ns == NULL) &&
6516: (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6517: ((attr->ns != NULL) &&
6518: xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6519:
6520: xmlSchemaPIllegalAttrErr(ctxt,
6521: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6522: }
6523: attr = attr->next;
6524: }
6525: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6526: /*
6527: * And now for the children...
6528: */
6529: child = node->children;
6530: while (child != NULL) {
6531: if (IS_SCHEMA(child, "appinfo")) {
6532: /* TODO: make available the content of "appinfo". */
6533: /*
6534: * source = anyURI
6535: * {any attributes with non-schema namespace . . .}>
6536: * Content: ({any})*
6537: */
6538: attr = child->properties;
6539: while (attr != NULL) {
6540: if (((attr->ns == NULL) &&
6541: (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6542: ((attr->ns != NULL) &&
6543: xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6544:
6545: xmlSchemaPIllegalAttrErr(ctxt,
6546: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6547: }
6548: attr = attr->next;
6549: }
6550: xmlSchemaPValAttr(ctxt, NULL, child, "source",
6551: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6552: child = child->next;
6553: } else if (IS_SCHEMA(child, "documentation")) {
6554: /* TODO: make available the content of "documentation". */
6555: /*
6556: * source = anyURI
6557: * {any attributes with non-schema namespace . . .}>
6558: * Content: ({any})*
6559: */
6560: attr = child->properties;
6561: while (attr != NULL) {
6562: if (attr->ns == NULL) {
6563: if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6564: xmlSchemaPIllegalAttrErr(ctxt,
6565: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6566: }
6567: } else {
6568: if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6569: (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6570: (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6571:
6572: xmlSchemaPIllegalAttrErr(ctxt,
6573: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6574: }
6575: }
6576: attr = attr->next;
6577: }
6578: /*
6579: * Attribute "xml:lang".
6580: */
6581: attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6582: if (attr != NULL)
6583: xmlSchemaPValAttrNode(ctxt, NULL, attr,
6584: xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6585: child = child->next;
6586: } else {
6587: if (!barked)
6588: xmlSchemaPContentErr(ctxt,
6589: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6590: NULL, node, child, NULL, "(appinfo | documentation)*");
6591: barked = 1;
6592: child = child->next;
6593: }
6594: }
6595:
6596: return (ret);
6597: }
6598:
6599: /**
6600: * xmlSchemaParseFacet:
6601: * @ctxt: a schema validation context
6602: * @schema: the schema being built
6603: * @node: a subtree containing XML Schema informations
6604: *
6605: * parse a XML schema Facet declaration
6606: * *WARNING* this interface is highly subject to change
6607: *
6608: * Returns the new type structure or NULL in case of error
6609: */
6610: static xmlSchemaFacetPtr
6611: xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6612: xmlNodePtr node)
6613: {
6614: xmlSchemaFacetPtr facet;
6615: xmlNodePtr child = NULL;
6616: const xmlChar *value;
6617:
6618: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6619: return (NULL);
6620:
6621: facet = xmlSchemaNewFacet();
6622: if (facet == NULL) {
6623: xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6624: return (NULL);
6625: }
6626: facet->node = node;
6627: value = xmlSchemaGetProp(ctxt, node, "value");
6628: if (value == NULL) {
6629: xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6630: "Facet %s has no value\n", node->name, NULL);
6631: xmlSchemaFreeFacet(facet);
6632: return (NULL);
6633: }
6634: if (IS_SCHEMA(node, "minInclusive")) {
6635: facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6636: } else if (IS_SCHEMA(node, "minExclusive")) {
6637: facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6638: } else if (IS_SCHEMA(node, "maxInclusive")) {
6639: facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6640: } else if (IS_SCHEMA(node, "maxExclusive")) {
6641: facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6642: } else if (IS_SCHEMA(node, "totalDigits")) {
6643: facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6644: } else if (IS_SCHEMA(node, "fractionDigits")) {
6645: facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6646: } else if (IS_SCHEMA(node, "pattern")) {
6647: facet->type = XML_SCHEMA_FACET_PATTERN;
6648: } else if (IS_SCHEMA(node, "enumeration")) {
6649: facet->type = XML_SCHEMA_FACET_ENUMERATION;
6650: } else if (IS_SCHEMA(node, "whiteSpace")) {
6651: facet->type = XML_SCHEMA_FACET_WHITESPACE;
6652: } else if (IS_SCHEMA(node, "length")) {
6653: facet->type = XML_SCHEMA_FACET_LENGTH;
6654: } else if (IS_SCHEMA(node, "maxLength")) {
6655: facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6656: } else if (IS_SCHEMA(node, "minLength")) {
6657: facet->type = XML_SCHEMA_FACET_MINLENGTH;
6658: } else {
6659: xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6660: "Unknown facet type %s\n", node->name, NULL);
6661: xmlSchemaFreeFacet(facet);
6662: return (NULL);
6663: }
6664: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6665: facet->value = value;
6666: if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6667: (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6668: const xmlChar *fixed;
6669:
6670: fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6671: if (fixed != NULL) {
6672: if (xmlStrEqual(fixed, BAD_CAST "true"))
6673: facet->fixed = 1;
6674: }
6675: }
6676: child = node->children;
6677:
6678: if (IS_SCHEMA(child, "annotation")) {
6679: facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6680: child = child->next;
6681: }
6682: if (child != NULL) {
6683: xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6684: "Facet %s has unexpected child content\n",
6685: node->name, NULL);
6686: }
6687: return (facet);
6688: }
6689:
6690: /**
6691: * xmlSchemaParseWildcardNs:
6692: * @ctxt: a schema parser context
6693: * @wildc: the wildcard, already created
6694: * @node: a subtree containing XML Schema informations
6695: *
6696: * Parses the attribute "processContents" and "namespace"
6697: * of a xsd:anyAttribute and xsd:any.
6698: * *WARNING* this interface is highly subject to change
6699: *
6700: * Returns 0 if everything goes fine, a positive error code
6701: * if something is not valid and -1 if an internal error occurs.
6702: */
6703: static int
6704: xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6705: xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6706: xmlSchemaWildcardPtr wildc,
6707: xmlNodePtr node)
6708: {
6709: const xmlChar *pc, *ns, *dictnsItem;
6710: int ret = 0;
6711: xmlChar *nsItem;
6712: xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6713: xmlAttrPtr attr;
6714:
6715: pc = xmlSchemaGetProp(ctxt, node, "processContents");
6716: if ((pc == NULL)
6717: || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6718: wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6719: } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6720: wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6721: } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6722: wildc->processContents = XML_SCHEMAS_ANY_LAX;
6723: } else {
6724: xmlSchemaPSimpleTypeErr(ctxt,
6725: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6726: NULL, node,
6727: NULL, "(strict | skip | lax)", pc,
6728: NULL, NULL, NULL);
6729: wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6730: ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6731: }
6732: /*
6733: * Build the namespace constraints.
6734: */
6735: attr = xmlSchemaGetPropNode(node, "namespace");
6736: ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6737: if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6738: wildc->any = 1;
6739: else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6740: wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6741: if (wildc->negNsSet == NULL) {
6742: return (-1);
6743: }
6744: wildc->negNsSet->value = ctxt->targetNamespace;
6745: } else {
6746: const xmlChar *end, *cur;
6747:
6748: cur = ns;
6749: do {
6750: while (IS_BLANK_CH(*cur))
6751: cur++;
6752: end = cur;
6753: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6754: end++;
6755: if (end == cur)
6756: break;
6757: nsItem = xmlStrndup(cur, end - cur);
6758: if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6759: (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6760: xmlSchemaPSimpleTypeErr(ctxt,
6761: XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6762: NULL, (xmlNodePtr) attr,
6763: NULL,
6764: "((##any | ##other) | List of (xs:anyURI | "
6765: "(##targetNamespace | ##local)))",
6766: nsItem, NULL, NULL, NULL);
6767: ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6768: } else {
6769: if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6770: dictnsItem = ctxt->targetNamespace;
6771: } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6772: dictnsItem = NULL;
6773: } else {
6774: /*
6775: * Validate the item (anyURI).
6776: */
6777: xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6778: nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6779: dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6780: }
6781: /*
6782: * Avoid dublicate namespaces.
6783: */
6784: tmp = wildc->nsSet;
6785: while (tmp != NULL) {
6786: if (dictnsItem == tmp->value)
6787: break;
6788: tmp = tmp->next;
6789: }
6790: if (tmp == NULL) {
6791: tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6792: if (tmp == NULL) {
6793: xmlFree(nsItem);
6794: return (-1);
6795: }
6796: tmp->value = dictnsItem;
6797: tmp->next = NULL;
6798: if (wildc->nsSet == NULL)
6799: wildc->nsSet = tmp;
6800: else if (lastNs != NULL)
6801: lastNs->next = tmp;
6802: lastNs = tmp;
6803: }
6804:
6805: }
6806: xmlFree(nsItem);
6807: cur = end;
6808: } while (*cur != 0);
6809: }
6810: return (ret);
6811: }
6812:
6813: static int
6814: xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6815: xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6816: xmlNodePtr node,
6817: int minOccurs,
6818: int maxOccurs) {
6819:
6820: if ((maxOccurs == 0) && ( minOccurs == 0))
6821: return (0);
6822: if (maxOccurs != UNBOUNDED) {
6823: /*
6824: * TODO: Maybe we should better not create the particle,
6825: * if min/max is invalid, since it could confuse the build of the
6826: * content model.
6827: */
6828: /*
6829: * 3.9.6 Schema Component Constraint: Particle Correct
6830: *
6831: */
6832: if (maxOccurs < 1) {
6833: /*
6834: * 2.2 {max occurs} must be greater than or equal to 1.
6835: */
6836: xmlSchemaPCustomAttrErr(ctxt,
6837: XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6838: NULL, NULL,
6839: xmlSchemaGetPropNode(node, "maxOccurs"),
6840: "The value must be greater than or equal to 1");
6841: return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6842: } else if (minOccurs > maxOccurs) {
6843: /*
6844: * 2.1 {min occurs} must not be greater than {max occurs}.
6845: */
6846: xmlSchemaPCustomAttrErr(ctxt,
6847: XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6848: NULL, NULL,
6849: xmlSchemaGetPropNode(node, "minOccurs"),
6850: "The value must not be greater than the value of 'maxOccurs'");
6851: return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6852: }
6853: }
6854: return (0);
6855: }
6856:
6857: /**
6858: * xmlSchemaParseAny:
6859: * @ctxt: a schema validation context
6860: * @schema: the schema being built
6861: * @node: a subtree containing XML Schema informations
6862: *
6863: * Parsea a XML schema <any> element. A particle and wildcard
6864: * will be created (except if minOccurs==maxOccurs==0, in this case
6865: * nothing will be created).
6866: * *WARNING* this interface is highly subject to change
6867: *
6868: * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6869: */
6870: static xmlSchemaParticlePtr
6871: xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6872: xmlNodePtr node)
6873: {
6874: xmlSchemaParticlePtr particle;
6875: xmlNodePtr child = NULL;
6876: xmlSchemaWildcardPtr wild;
6877: int min, max;
6878: xmlAttrPtr attr;
6879: xmlSchemaAnnotPtr annot = NULL;
6880:
6881: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6882: return (NULL);
6883: /*
6884: * Check for illegal attributes.
6885: */
6886: attr = node->properties;
6887: while (attr != NULL) {
6888: if (attr->ns == NULL) {
6889: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6890: (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6891: (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6892: (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6893: (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6894: xmlSchemaPIllegalAttrErr(ctxt,
6895: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6896: }
6897: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6898: xmlSchemaPIllegalAttrErr(ctxt,
6899: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6900: }
6901: attr = attr->next;
6902: }
6903: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6904: /*
6905: * minOccurs/maxOccurs.
6906: */
6907: max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6908: "(xs:nonNegativeInteger | unbounded)");
6909: min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6910: "xs:nonNegativeInteger");
6911: xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6912: /*
6913: * Create & parse the wildcard.
6914: */
6915: wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6916: if (wild == NULL)
6917: return (NULL);
6918: xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6919: /*
6920: * And now for the children...
6921: */
6922: child = node->children;
6923: if (IS_SCHEMA(child, "annotation")) {
6924: annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6925: child = child->next;
6926: }
6927: if (child != NULL) {
6928: xmlSchemaPContentErr(ctxt,
6929: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6930: NULL, node, child,
6931: NULL, "(annotation?)");
6932: }
6933: /*
6934: * No component if minOccurs==maxOccurs==0.
6935: */
6936: if ((min == 0) && (max == 0)) {
6937: /* Don't free the wildcard, since it's already on the list. */
6938: return (NULL);
6939: }
6940: /*
6941: * Create the particle.
6942: */
6943: particle = xmlSchemaAddParticle(ctxt, node, min, max);
6944: if (particle == NULL)
6945: return (NULL);
6946: particle->annot = annot;
6947: particle->children = (xmlSchemaTreeItemPtr) wild;
6948:
6949: return (particle);
6950: }
6951:
6952: /**
6953: * xmlSchemaParseNotation:
6954: * @ctxt: a schema validation context
6955: * @schema: the schema being built
6956: * @node: a subtree containing XML Schema informations
6957: *
6958: * parse a XML schema Notation declaration
6959: *
6960: * Returns the new structure or NULL in case of error
6961: */
6962: static xmlSchemaNotationPtr
6963: xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6964: xmlNodePtr node)
6965: {
6966: const xmlChar *name;
6967: xmlSchemaNotationPtr ret;
6968: xmlNodePtr child = NULL;
6969:
6970: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6971: return (NULL);
6972: name = xmlSchemaGetProp(ctxt, node, "name");
6973: if (name == NULL) {
6974: xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6975: "Notation has no name\n", NULL, NULL);
6976: return (NULL);
6977: }
6978: ret = xmlSchemaAddNotation(ctxt, schema, name,
6979: ctxt->targetNamespace, node);
6980: if (ret == NULL)
6981: return (NULL);
6982: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6983:
6984: child = node->children;
6985: if (IS_SCHEMA(child, "annotation")) {
6986: ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6987: child = child->next;
6988: }
6989: if (child != NULL) {
6990: xmlSchemaPContentErr(ctxt,
6991: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6992: NULL, node, child,
6993: NULL, "(annotation?)");
6994: }
6995:
6996: return (ret);
6997: }
6998:
6999: /**
7000: * xmlSchemaParseAnyAttribute:
7001: * @ctxt: a schema validation context
7002: * @schema: the schema being built
7003: * @node: a subtree containing XML Schema informations
7004: *
7005: * parse a XML schema AnyAttrribute declaration
7006: * *WARNING* this interface is highly subject to change
7007: *
7008: * Returns a wildcard or NULL.
7009: */
7010: static xmlSchemaWildcardPtr
7011: xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7012: xmlSchemaPtr schema, xmlNodePtr node)
7013: {
7014: xmlSchemaWildcardPtr ret;
7015: xmlNodePtr child = NULL;
7016: xmlAttrPtr attr;
7017:
7018: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7019: return (NULL);
7020:
7021: ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7022: node);
7023: if (ret == NULL) {
7024: return (NULL);
7025: }
7026: /*
7027: * Check for illegal attributes.
7028: */
7029: attr = node->properties;
7030: while (attr != NULL) {
7031: if (attr->ns == NULL) {
7032: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7033: (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7034: (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7035: xmlSchemaPIllegalAttrErr(ctxt,
7036: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7037: }
7038: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7039: xmlSchemaPIllegalAttrErr(ctxt,
7040: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7041: }
7042: attr = attr->next;
7043: }
7044: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7045: /*
7046: * Parse the namespace list.
7047: */
7048: if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7049: return (NULL);
7050: /*
7051: * And now for the children...
7052: */
7053: child = node->children;
7054: if (IS_SCHEMA(child, "annotation")) {
7055: ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7056: child = child->next;
7057: }
7058: if (child != NULL) {
7059: xmlSchemaPContentErr(ctxt,
7060: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7061: NULL, node, child,
7062: NULL, "(annotation?)");
7063: }
7064:
7065: return (ret);
7066: }
7067:
7068:
7069: /**
7070: * xmlSchemaParseAttribute:
7071: * @ctxt: a schema validation context
7072: * @schema: the schema being built
7073: * @node: a subtree containing XML Schema informations
7074: *
7075: * parse a XML schema Attrribute declaration
7076: * *WARNING* this interface is highly subject to change
7077: *
7078: * Returns the attribute declaration.
7079: */
7080: static xmlSchemaBasicItemPtr
7081: xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7082: xmlSchemaPtr schema,
7083: xmlNodePtr node,
7084: xmlSchemaItemListPtr uses,
7085: int parentType)
7086: {
7087: const xmlChar *attrValue, *name = NULL, *ns = NULL;
7088: xmlSchemaAttributeUsePtr use = NULL;
7089: xmlNodePtr child = NULL;
7090: xmlAttrPtr attr;
7091: const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7092: int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7093: int nberrors, hasForm = 0, defValueType = 0;
7094:
7095: #define WXS_ATTR_DEF_VAL_DEFAULT 1
7096: #define WXS_ATTR_DEF_VAL_FIXED 2
7097:
7098: /*
7099: * 3.2.3 Constraints on XML Representations of Attribute Declarations
7100: */
7101:
7102: if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7103: return (NULL);
7104: attr = xmlSchemaGetPropNode(node, "ref");
7105: if (attr != NULL) {
7106: if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7107: NULL, attr, &tmpNs, &tmpName) != 0) {
7108: return (NULL);
7109: }
7110: if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7111: return(NULL);
7112: isRef = 1;
7113: }
7114: nberrors = pctxt->nberrors;
7115: /*
7116: * Check for illegal attributes.
7117: */
7118: attr = node->properties;
7119: while (attr != NULL) {
7120: if (attr->ns == NULL) {
7121: if (isRef) {
7122: if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7123: xmlSchemaPValAttrNodeID(pctxt, attr);
7124: goto attr_next;
7125: } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7126: goto attr_next;
7127: }
7128: } else {
7129: if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7130: goto attr_next;
7131: } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7132: xmlSchemaPValAttrNodeID(pctxt, attr);
7133: goto attr_next;
7134: } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7135: xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7136: attr, &tmpNs, &tmpName);
7137: goto attr_next;
7138: } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7139: /*
7140: * Evaluate the target namespace
7141: */
7142: hasForm = 1;
7143: attrValue = xmlSchemaGetNodeContent(pctxt,
7144: (xmlNodePtr) attr);
7145: if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7146: ns = pctxt->targetNamespace;
7147: } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7148: {
7149: xmlSchemaPSimpleTypeErr(pctxt,
7150: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7151: NULL, (xmlNodePtr) attr,
7152: NULL, "(qualified | unqualified)",
7153: attrValue, NULL, NULL, NULL);
7154: }
7155: goto attr_next;
7156: }
7157: }
7158: if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7159:
7160: attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7161: /* TODO: Maybe we need to normalize the value beforehand. */
7162: if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7163: occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7164: else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7165: occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7166: else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7167: occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7168: else {
7169: xmlSchemaPSimpleTypeErr(pctxt,
7170: XML_SCHEMAP_INVALID_ATTR_USE,
7171: NULL, (xmlNodePtr) attr,
7172: NULL, "(optional | prohibited | required)",
7173: attrValue, NULL, NULL, NULL);
7174: }
7175: goto attr_next;
7176: } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7177: /*
7178: * 3.2.3 : 1
7179: * default and fixed must not both be present.
7180: */
7181: if (defValue) {
7182: xmlSchemaPMutualExclAttrErr(pctxt,
7183: XML_SCHEMAP_SRC_ATTRIBUTE_1,
7184: NULL, attr, "default", "fixed");
7185: } else {
7186: defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7187: defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7188: }
7189: goto attr_next;
7190: } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7191: /*
7192: * 3.2.3 : 1
7193: * default and fixed must not both be present.
7194: */
7195: if (defValue) {
7196: xmlSchemaPMutualExclAttrErr(pctxt,
7197: XML_SCHEMAP_SRC_ATTRIBUTE_1,
7198: NULL, attr, "default", "fixed");
7199: } else {
7200: defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7201: defValueType = WXS_ATTR_DEF_VAL_FIXED;
7202: }
7203: goto attr_next;
7204: }
7205: } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7206: goto attr_next;
7207:
7208: xmlSchemaPIllegalAttrErr(pctxt,
7209: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7210:
7211: attr_next:
7212: attr = attr->next;
7213: }
7214: /*
7215: * 3.2.3 : 2
7216: * If default and use are both present, use must have
7217: * the actual value optional.
7218: */
7219: if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7220: (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7221: xmlSchemaPSimpleTypeErr(pctxt,
7222: XML_SCHEMAP_SRC_ATTRIBUTE_2,
7223: NULL, node, NULL,
7224: "(optional | prohibited | required)", NULL,
7225: "The value of the attribute 'use' must be 'optional' "
7226: "if the attribute 'default' is present",
7227: NULL, NULL);
7228: }
7229: /*
7230: * We want correct attributes.
7231: */
7232: if (nberrors != pctxt->nberrors)
7233: return(NULL);
7234: if (! isRef) {
7235: xmlSchemaAttributePtr attrDecl;
7236:
7237: /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7238: if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7239: ns = pctxt->targetNamespace;
7240: /*
7241: * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7242: * TODO: Move this to the component layer.
7243: */
7244: if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7245: xmlSchemaCustomErr(ACTXT_CAST pctxt,
7246: XML_SCHEMAP_NO_XSI,
7247: node, NULL,
7248: "The target namespace must not match '%s'",
7249: xmlSchemaInstanceNs, NULL);
7250: }
7251: attr = xmlSchemaGetPropNode(node, "name");
7252: if (attr == NULL) {
7253: xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7254: NULL, node, "name", NULL);
7255: return (NULL);
7256: }
7257: if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7258: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7259: return (NULL);
7260: }
7261: /*
7262: * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7263: * TODO: Move this to the component layer.
7264: */
7265: if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7266: xmlSchemaPSimpleTypeErr(pctxt,
7267: XML_SCHEMAP_NO_XMLNS,
7268: NULL, (xmlNodePtr) attr,
7269: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7270: "The value of the attribute must not match 'xmlns'",
7271: NULL, NULL);
7272: return (NULL);
7273: }
7274: if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7275: goto check_children;
7276: /*
7277: * Create the attribute use component.
7278: */
7279: use = xmlSchemaAddAttributeUse(pctxt, node);
7280: if (use == NULL)
7281: return(NULL);
7282: use->occurs = occurs;
7283: /*
7284: * Create the attribute declaration.
7285: */
7286: attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7287: if (attrDecl == NULL)
7288: return (NULL);
7289: if (tmpName != NULL) {
7290: attrDecl->typeName = tmpName;
7291: attrDecl->typeNs = tmpNs;
7292: }
7293: use->attrDecl = attrDecl;
7294: /*
7295: * Value constraint.
7296: */
7297: if (defValue != NULL) {
7298: attrDecl->defValue = defValue;
7299: if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7300: attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7301: }
7302: } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7303: xmlSchemaQNameRefPtr ref;
7304:
7305: /*
7306: * Create the attribute use component.
7307: */
7308: use = xmlSchemaAddAttributeUse(pctxt, node);
7309: if (use == NULL)
7310: return(NULL);
7311: /*
7312: * We need to resolve the reference at later stage.
7313: */
7314: WXS_ADD_PENDING(pctxt, use);
7315: use->occurs = occurs;
7316: /*
7317: * Create a QName reference to the attribute declaration.
7318: */
7319: ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7320: tmpName, tmpNs);
7321: if (ref == NULL)
7322: return(NULL);
7323: /*
7324: * Assign the reference. This will be substituted for the
7325: * referenced attribute declaration when the QName is resolved.
7326: */
7327: use->attrDecl = WXS_ATTR_CAST ref;
7328: /*
7329: * Value constraint.
7330: */
7331: if (defValue != NULL)
7332: use->defValue = defValue;
7333: if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7334: use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7335: }
7336:
7337: check_children:
7338: /*
7339: * And now for the children...
7340: */
7341: child = node->children;
7342: if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7343: xmlSchemaAttributeUseProhibPtr prohib;
7344:
7345: if (IS_SCHEMA(child, "annotation")) {
7346: xmlSchemaParseAnnotation(pctxt, child, 0);
7347: child = child->next;
7348: }
7349: if (child != NULL) {
7350: xmlSchemaPContentErr(pctxt,
7351: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7352: NULL, node, child, NULL,
7353: "(annotation?)");
7354: }
7355: /*
7356: * Check for pointlessness of attribute prohibitions.
7357: */
7358: if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7359: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7360: XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7361: node, NULL,
7362: "Skipping attribute use prohibition, since it is "
7363: "pointless inside an <attributeGroup>",
7364: NULL, NULL, NULL);
7365: return(NULL);
7366: } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7367: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7368: XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7369: node, NULL,
7370: "Skipping attribute use prohibition, since it is "
7371: "pointless when extending a type",
7372: NULL, NULL, NULL);
7373: return(NULL);
7374: }
7375: if (! isRef) {
7376: tmpName = name;
7377: tmpNs = ns;
7378: }
7379: /*
7380: * Check for duplicate attribute prohibitions.
7381: */
7382: if (uses) {
7383: int i;
7384:
7385: for (i = 0; i < uses->nbItems; i++) {
7386: use = uses->items[i];
7387: if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7388: (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7389: (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7390: {
7391: xmlChar *str = NULL;
7392:
7393: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7394: XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7395: node, NULL,
7396: "Skipping duplicate attribute use prohibition '%s'",
7397: xmlSchemaFormatQName(&str, tmpNs, tmpName),
7398: NULL, NULL);
7399: FREE_AND_NULL(str)
7400: return(NULL);
7401: }
7402: }
7403: }
7404: /*
7405: * Create the attribute prohibition helper component.
7406: */
7407: prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7408: if (prohib == NULL)
7409: return(NULL);
7410: prohib->node = node;
7411: prohib->name = tmpName;
7412: prohib->targetNamespace = tmpNs;
7413: if (isRef) {
7414: /*
7415: * We need at least to resolve to the attribute declaration.
7416: */
7417: WXS_ADD_PENDING(pctxt, prohib);
7418: }
7419: return(WXS_BASIC_CAST prohib);
7420: } else {
7421: if (IS_SCHEMA(child, "annotation")) {
7422: /*
7423: * TODO: Should this go into the attr decl?
7424: */
7425: use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7426: child = child->next;
7427: }
7428: if (isRef) {
7429: if (child != NULL) {
7430: if (IS_SCHEMA(child, "simpleType"))
7431: /*
7432: * 3.2.3 : 3.2
7433: * If ref is present, then all of <simpleType>,
7434: * form and type must be absent.
7435: */
7436: xmlSchemaPContentErr(pctxt,
7437: XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7438: NULL, node, child, NULL,
7439: "(annotation?)");
7440: else
7441: xmlSchemaPContentErr(pctxt,
7442: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7443: NULL, node, child, NULL,
7444: "(annotation?)");
7445: }
7446: } else {
7447: if (IS_SCHEMA(child, "simpleType")) {
7448: if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7449: /*
7450: * 3.2.3 : 4
7451: * type and <simpleType> must not both be present.
7452: */
7453: xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7454: NULL, node, child,
7455: "The attribute 'type' and the <simpleType> child "
7456: "are mutually exclusive", NULL);
7457: } else
7458: WXS_ATTRUSE_TYPEDEF(use) =
7459: xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7460: child = child->next;
7461: }
7462: if (child != NULL)
7463: xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464: NULL, node, child, NULL,
7465: "(annotation?, simpleType?)");
7466: }
7467: }
7468: return (WXS_BASIC_CAST use);
7469: }
7470:
7471:
7472: static xmlSchemaAttributePtr
7473: xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7474: xmlSchemaPtr schema,
7475: xmlNodePtr node)
7476: {
7477: const xmlChar *attrValue;
7478: xmlSchemaAttributePtr ret;
7479: xmlNodePtr child = NULL;
7480: xmlAttrPtr attr;
7481:
7482: /*
7483: * Note that the w3c spec assumes the schema to be validated with schema
7484: * for schemas beforehand.
7485: *
7486: * 3.2.3 Constraints on XML Representations of Attribute Declarations
7487: */
7488: if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7489: return (NULL);
7490: /*
7491: * 3.2.3 : 3.1
7492: * One of ref or name must be present, but not both
7493: */
7494: attr = xmlSchemaGetPropNode(node, "name");
7495: if (attr == NULL) {
7496: xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7497: NULL, node, "name", NULL);
7498: return (NULL);
7499: }
7500: if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7501: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7502: return (NULL);
7503: }
7504: /*
7505: * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7506: * TODO: Move this to the component layer.
7507: */
7508: if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7509: xmlSchemaPSimpleTypeErr(pctxt,
7510: XML_SCHEMAP_NO_XMLNS,
7511: NULL, (xmlNodePtr) attr,
7512: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7513: "The value of the attribute must not match 'xmlns'",
7514: NULL, NULL);
7515: return (NULL);
7516: }
7517: /*
7518: * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7519: * TODO: Move this to the component layer.
7520: * Or better leave it here and add it to the component layer
7521: * if we have a schema construction API.
7522: */
7523: if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7524: xmlSchemaCustomErr(ACTXT_CAST pctxt,
7525: XML_SCHEMAP_NO_XSI, node, NULL,
7526: "The target namespace must not match '%s'",
7527: xmlSchemaInstanceNs, NULL);
7528: }
7529:
7530: ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7531: pctxt->targetNamespace, node, 1);
7532: if (ret == NULL)
7533: return (NULL);
7534: ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7535:
7536: /*
7537: * Check for illegal attributes.
7538: */
7539: attr = node->properties;
7540: while (attr != NULL) {
7541: if (attr->ns == NULL) {
7542: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7543: (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7544: (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7545: (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7546: (!xmlStrEqual(attr->name, BAD_CAST "type")))
7547: {
7548: xmlSchemaPIllegalAttrErr(pctxt,
7549: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7550: }
7551: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7552: xmlSchemaPIllegalAttrErr(pctxt,
7553: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7554: }
7555: attr = attr->next;
7556: }
7557: xmlSchemaPValAttrQName(pctxt, schema, NULL,
7558: node, "type", &ret->typeNs, &ret->typeName);
7559:
7560: xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7561: /*
7562: * Attribute "fixed".
7563: */
7564: ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7565: if (ret->defValue != NULL)
7566: ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7567: /*
7568: * Attribute "default".
7569: */
7570: attr = xmlSchemaGetPropNode(node, "default");
7571: if (attr != NULL) {
7572: /*
7573: * 3.2.3 : 1
7574: * default and fixed must not both be present.
7575: */
7576: if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7577: xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7578: WXS_BASIC_CAST ret, attr, "default", "fixed");
7579: } else
7580: ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7581: }
7582: /*
7583: * And now for the children...
7584: */
7585: child = node->children;
7586: if (IS_SCHEMA(child, "annotation")) {
7587: ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7588: child = child->next;
7589: }
7590: if (IS_SCHEMA(child, "simpleType")) {
7591: if (ret->typeName != NULL) {
7592: /*
7593: * 3.2.3 : 4
7594: * type and <simpleType> must not both be present.
7595: */
7596: xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7597: NULL, node, child,
7598: "The attribute 'type' and the <simpleType> child "
7599: "are mutually exclusive", NULL);
7600: } else
7601: ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7602: child = child->next;
7603: }
7604: if (child != NULL)
7605: xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7606: NULL, node, child, NULL,
7607: "(annotation?, simpleType?)");
7608:
7609: return (ret);
7610: }
7611:
7612: /**
7613: * xmlSchemaParseAttributeGroupRef:
7614: * @ctxt: a schema validation context
7615: * @schema: the schema being built
7616: * @node: a subtree containing XML Schema informations
7617: *
7618: * Parse an attribute group definition reference.
7619: * Note that a reference to an attribute group does not
7620: * correspond to any component at all.
7621: * *WARNING* this interface is highly subject to change
7622: *
7623: * Returns the attribute group or NULL in case of error.
7624: */
7625: static xmlSchemaQNameRefPtr
7626: xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7627: xmlSchemaPtr schema,
7628: xmlNodePtr node)
7629: {
7630: xmlSchemaQNameRefPtr ret;
7631: xmlNodePtr child = NULL;
7632: xmlAttrPtr attr;
7633: const xmlChar *refNs = NULL, *ref = NULL;
7634:
7635: if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7636: return (NULL);
7637:
7638: attr = xmlSchemaGetPropNode(node, "ref");
7639: if (attr == NULL) {
7640: xmlSchemaPMissingAttrErr(pctxt,
7641: XML_SCHEMAP_S4S_ATTR_MISSING,
7642: NULL, node, "ref", NULL);
7643: return (NULL);
7644: }
7645: xmlSchemaPValAttrNodeQName(pctxt, schema,
7646: NULL, attr, &refNs, &ref);
7647: if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7648: return(NULL);
7649:
7650: /*
7651: * Check for illegal attributes.
7652: */
7653: attr = node->properties;
7654: while (attr != NULL) {
7655: if (attr->ns == NULL) {
7656: if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7657: (!xmlStrEqual(attr->name, BAD_CAST "id")))
7658: {
7659: xmlSchemaPIllegalAttrErr(pctxt,
7660: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7661: }
7662: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7663: xmlSchemaPIllegalAttrErr(pctxt,
7664: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7665: }
7666: attr = attr->next;
7667: }
7668: /* Attribute ID */
7669: xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7670:
7671: /*
7672: * And now for the children...
7673: */
7674: child = node->children;
7675: if (IS_SCHEMA(child, "annotation")) {
7676: /*
7677: * TODO: We do not have a place to store the annotation, do we?
7678: */
7679: xmlSchemaParseAnnotation(pctxt, child, 0);
7680: child = child->next;
7681: }
7682: if (child != NULL) {
7683: xmlSchemaPContentErr(pctxt,
7684: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7685: NULL, node, child, NULL,
7686: "(annotation?)");
7687: }
7688:
7689: /*
7690: * Handle attribute group redefinitions.
7691: */
7692: if (pctxt->isRedefine && pctxt->redef &&
7693: (pctxt->redef->item->type ==
7694: XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7695: (ref == pctxt->redef->refName) &&
7696: (refNs == pctxt->redef->refTargetNs))
7697: {
7698: /*
7699: * SPEC src-redefine:
7700: * (7.1) "If it has an <attributeGroup> among its contents
7701: * the �actual value� of whose ref [attribute] is the same
7702: * as the �actual value� of its own name attribute plus
7703: * target namespace, then it must have exactly one such group."
7704: */
7705: if (pctxt->redefCounter != 0) {
7706: xmlChar *str = NULL;
7707:
7708: xmlSchemaCustomErr(ACTXT_CAST pctxt,
7709: XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7710: "The redefining attribute group definition "
7711: "'%s' must not contain more than one "
7712: "reference to the redefined definition",
7713: xmlSchemaFormatQName(&str, refNs, ref), NULL);
7714: FREE_AND_NULL(str);
7715: return(NULL);
7716: }
7717: pctxt->redefCounter++;
7718: /*
7719: * URGENT TODO: How to ensure that the reference will not be
7720: * handled by the normal component resolution mechanism?
7721: */
7722: ret = xmlSchemaNewQNameRef(pctxt,
7723: XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7724: if (ret == NULL)
7725: return(NULL);
7726: ret->node = node;
7727: pctxt->redef->reference = WXS_BASIC_CAST ret;
7728: } else {
7729: /*
7730: * Create a QName-reference helper component. We will substitute this
7731: * component for the attribute uses of the referenced attribute group
7732: * definition.
7733: */
7734: ret = xmlSchemaNewQNameRef(pctxt,
7735: XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7736: if (ret == NULL)
7737: return(NULL);
7738: ret->node = node;
7739: /* Add to pending items, to be able to resolve the reference. */
7740: WXS_ADD_PENDING(pctxt, ret);
7741: }
7742: return (ret);
7743: }
7744:
7745: /**
7746: * xmlSchemaParseAttributeGroupDefinition:
7747: * @pctxt: a schema validation context
7748: * @schema: the schema being built
7749: * @node: a subtree containing XML Schema informations
7750: *
7751: * parse a XML schema Attribute Group declaration
7752: * *WARNING* this interface is highly subject to change
7753: *
7754: * Returns the attribute group definition or NULL in case of error.
7755: */
7756: static xmlSchemaAttributeGroupPtr
7757: xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7758: xmlSchemaPtr schema,
7759: xmlNodePtr node)
7760: {
7761: const xmlChar *name;
7762: xmlSchemaAttributeGroupPtr ret;
7763: xmlNodePtr child = NULL;
7764: xmlAttrPtr attr;
7765: int hasRefs = 0;
7766:
7767: if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7768: return (NULL);
7769:
7770: attr = xmlSchemaGetPropNode(node, "name");
7771: if (attr == NULL) {
7772: xmlSchemaPMissingAttrErr(pctxt,
7773: XML_SCHEMAP_S4S_ATTR_MISSING,
7774: NULL, node, "name", NULL);
7775: return (NULL);
7776: }
7777: /*
7778: * The name is crucial, exit if invalid.
7779: */
7780: if (xmlSchemaPValAttrNode(pctxt,
7781: NULL, attr,
7782: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7783: return (NULL);
7784: }
7785: ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7786: name, pctxt->targetNamespace, node);
7787: if (ret == NULL)
7788: return (NULL);
7789: /*
7790: * Check for illegal attributes.
7791: */
7792: attr = node->properties;
7793: while (attr != NULL) {
7794: if (attr->ns == NULL) {
7795: if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7796: (!xmlStrEqual(attr->name, BAD_CAST "id")))
7797: {
7798: xmlSchemaPIllegalAttrErr(pctxt,
7799: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7800: }
7801: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7802: xmlSchemaPIllegalAttrErr(pctxt,
7803: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7804: }
7805: attr = attr->next;
7806: }
7807: /* Attribute ID */
7808: xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7809: /*
7810: * And now for the children...
7811: */
7812: child = node->children;
7813: if (IS_SCHEMA(child, "annotation")) {
7814: ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7815: child = child->next;
7816: }
7817: /*
7818: * Parse contained attribute decls/refs.
7819: */
7820: if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7821: (xmlSchemaItemListPtr *) &(ret->attrUses),
7822: XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7823: return(NULL);
7824: if (hasRefs)
7825: ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7826: /*
7827: * Parse the attribute wildcard.
7828: */
7829: if (IS_SCHEMA(child, "anyAttribute")) {
7830: ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7831: schema, child);
7832: child = child->next;
7833: }
7834: if (child != NULL) {
7835: xmlSchemaPContentErr(pctxt,
7836: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7837: NULL, node, child, NULL,
7838: "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7839: }
7840: return (ret);
7841: }
7842:
7843: /**
7844: * xmlSchemaPValAttrFormDefault:
7845: * @value: the value
7846: * @flags: the flags to be modified
7847: * @flagQualified: the specific flag for "qualified"
7848: *
7849: * Returns 0 if the value is valid, 1 otherwise.
7850: */
7851: static int
7852: xmlSchemaPValAttrFormDefault(const xmlChar *value,
7853: int *flags,
7854: int flagQualified)
7855: {
7856: if (xmlStrEqual(value, BAD_CAST "qualified")) {
7857: if ((*flags & flagQualified) == 0)
7858: *flags |= flagQualified;
7859: } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7860: return (1);
7861:
7862: return (0);
7863: }
7864:
7865: /**
7866: * xmlSchemaPValAttrBlockFinal:
7867: * @value: the value
7868: * @flags: the flags to be modified
7869: * @flagAll: the specific flag for "#all"
7870: * @flagExtension: the specific flag for "extension"
7871: * @flagRestriction: the specific flag for "restriction"
7872: * @flagSubstitution: the specific flag for "substitution"
7873: * @flagList: the specific flag for "list"
7874: * @flagUnion: the specific flag for "union"
7875: *
7876: * Validates the value of the attribute "final" and "block". The value
7877: * is converted into the specified flag values and returned in @flags.
7878: *
7879: * Returns 0 if the value is valid, 1 otherwise.
7880: */
7881:
7882: static int
7883: xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7884: int *flags,
7885: int flagAll,
7886: int flagExtension,
7887: int flagRestriction,
7888: int flagSubstitution,
7889: int flagList,
7890: int flagUnion)
7891: {
7892: int ret = 0;
7893:
7894: /*
7895: * TODO: This does not check for dublicate entries.
7896: */
7897: if ((flags == NULL) || (value == NULL))
7898: return (-1);
7899: if (value[0] == 0)
7900: return (0);
7901: if (xmlStrEqual(value, BAD_CAST "#all")) {
7902: if (flagAll != -1)
7903: *flags |= flagAll;
7904: else {
7905: if (flagExtension != -1)
7906: *flags |= flagExtension;
7907: if (flagRestriction != -1)
7908: *flags |= flagRestriction;
7909: if (flagSubstitution != -1)
7910: *flags |= flagSubstitution;
7911: if (flagList != -1)
7912: *flags |= flagList;
7913: if (flagUnion != -1)
7914: *flags |= flagUnion;
7915: }
7916: } else {
7917: const xmlChar *end, *cur = value;
7918: xmlChar *item;
7919:
7920: do {
7921: while (IS_BLANK_CH(*cur))
7922: cur++;
7923: end = cur;
7924: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7925: end++;
7926: if (end == cur)
7927: break;
7928: item = xmlStrndup(cur, end - cur);
7929: if (xmlStrEqual(item, BAD_CAST "extension")) {
7930: if (flagExtension != -1) {
7931: if ((*flags & flagExtension) == 0)
7932: *flags |= flagExtension;
7933: } else
7934: ret = 1;
7935: } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7936: if (flagRestriction != -1) {
7937: if ((*flags & flagRestriction) == 0)
7938: *flags |= flagRestriction;
7939: } else
7940: ret = 1;
7941: } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7942: if (flagSubstitution != -1) {
7943: if ((*flags & flagSubstitution) == 0)
7944: *flags |= flagSubstitution;
7945: } else
7946: ret = 1;
7947: } else if (xmlStrEqual(item, BAD_CAST "list")) {
7948: if (flagList != -1) {
7949: if ((*flags & flagList) == 0)
7950: *flags |= flagList;
7951: } else
7952: ret = 1;
7953: } else if (xmlStrEqual(item, BAD_CAST "union")) {
7954: if (flagUnion != -1) {
7955: if ((*flags & flagUnion) == 0)
7956: *flags |= flagUnion;
7957: } else
7958: ret = 1;
7959: } else
7960: ret = 1;
7961: if (item != NULL)
7962: xmlFree(item);
7963: cur = end;
7964: } while ((ret == 0) && (*cur != 0));
7965: }
7966:
7967: return (ret);
7968: }
7969:
7970: static int
7971: xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7972: xmlSchemaIDCPtr idc,
7973: xmlSchemaIDCSelectPtr selector,
7974: xmlAttrPtr attr,
7975: int isField)
7976: {
7977: xmlNodePtr node;
7978:
7979: /*
7980: * c-selector-xpath:
7981: * Schema Component Constraint: Selector Value OK
7982: *
7983: * TODO: 1 The {selector} must be a valid XPath expression, as defined
7984: * in [XPath].
7985: */
7986: if (selector == NULL) {
7987: xmlSchemaPErr(ctxt, idc->node,
7988: XML_SCHEMAP_INTERNAL,
7989: "Internal error: xmlSchemaCheckCSelectorXPath, "
7990: "the selector is not specified.\n", NULL, NULL);
7991: return (-1);
7992: }
7993: if (attr == NULL)
7994: node = idc->node;
7995: else
7996: node = (xmlNodePtr) attr;
7997: if (selector->xpath == NULL) {
7998: xmlSchemaPCustomErr(ctxt,
7999: /* TODO: Adjust error code. */
8000: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8001: NULL, node,
8002: "The XPath expression of the selector is not valid", NULL);
8003: return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8004: } else {
8005: const xmlChar **nsArray = NULL;
8006: xmlNsPtr *nsList = NULL;
8007: /*
8008: * Compile the XPath expression.
8009: */
8010: /*
8011: * TODO: We need the array of in-scope namespaces for compilation.
8012: * TODO: Call xmlPatterncompile with different options for selector/
8013: * field.
8014: */
8015: if (attr == NULL)
8016: nsList = NULL;
8017: else
8018: nsList = xmlGetNsList(attr->doc, attr->parent);
8019: /*
8020: * Build an array of prefixes and namespaces.
8021: */
8022: if (nsList != NULL) {
8023: int i, count = 0;
8024:
8025: for (i = 0; nsList[i] != NULL; i++)
8026: count++;
8027:
8028: nsArray = (const xmlChar **) xmlMalloc(
8029: (count * 2 + 1) * sizeof(const xmlChar *));
8030: if (nsArray == NULL) {
8031: xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8032: NULL);
8033: xmlFree(nsList);
8034: return (-1);
8035: }
8036: for (i = 0; i < count; i++) {
8037: nsArray[2 * i] = nsList[i]->href;
8038: nsArray[2 * i + 1] = nsList[i]->prefix;
8039: }
8040: nsArray[count * 2] = NULL;
8041: xmlFree(nsList);
8042: }
8043: /*
8044: * TODO: Differentiate between "selector" and "field".
8045: */
8046: if (isField)
8047: selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8048: NULL, XML_PATTERN_XSFIELD, nsArray);
8049: else
8050: selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8051: NULL, XML_PATTERN_XSSEL, nsArray);
8052: if (nsArray != NULL)
8053: xmlFree((xmlChar **) nsArray);
8054:
8055: if (selector->xpathComp == NULL) {
8056: xmlSchemaPCustomErr(ctxt,
8057: /* TODO: Adjust error code? */
8058: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8059: NULL, node,
8060: "The XPath expression '%s' could not be "
8061: "compiled", selector->xpath);
8062: return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8063: }
8064: }
8065: return (0);
8066: }
8067:
8068: #define ADD_ANNOTATION(annot) \
8069: xmlSchemaAnnotPtr cur = item->annot; \
8070: if (item->annot == NULL) { \
8071: item->annot = annot; \
8072: return (annot); \
8073: } \
8074: cur = item->annot; \
8075: if (cur->next != NULL) { \
8076: cur = cur->next; \
8077: } \
8078: cur->next = annot;
8079:
8080: /**
8081: * xmlSchemaAssignAnnotation:
8082: * @item: the schema component
8083: * @annot: the annotation
8084: *
8085: * Adds the annotation to the given schema component.
8086: *
8087: * Returns the given annotaion.
8088: */
8089: static xmlSchemaAnnotPtr
8090: xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8091: xmlSchemaAnnotPtr annot)
8092: {
8093: if ((annItem == NULL) || (annot == NULL))
8094: return (NULL);
8095: switch (annItem->type) {
8096: case XML_SCHEMA_TYPE_ELEMENT: {
8097: xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8098: ADD_ANNOTATION(annot)
8099: }
8100: break;
8101: case XML_SCHEMA_TYPE_ATTRIBUTE: {
8102: xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8103: ADD_ANNOTATION(annot)
8104: }
8105: break;
8106: case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8107: case XML_SCHEMA_TYPE_ANY: {
8108: xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8109: ADD_ANNOTATION(annot)
8110: }
8111: break;
8112: case XML_SCHEMA_TYPE_PARTICLE:
8113: case XML_SCHEMA_TYPE_IDC_KEY:
8114: case XML_SCHEMA_TYPE_IDC_KEYREF:
8115: case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8116: xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8117: ADD_ANNOTATION(annot)
8118: }
8119: break;
8120: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8121: xmlSchemaAttributeGroupPtr item =
8122: (xmlSchemaAttributeGroupPtr) annItem;
8123: ADD_ANNOTATION(annot)
8124: }
8125: break;
8126: case XML_SCHEMA_TYPE_NOTATION: {
8127: xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8128: ADD_ANNOTATION(annot)
8129: }
8130: break;
8131: case XML_SCHEMA_FACET_MININCLUSIVE:
8132: case XML_SCHEMA_FACET_MINEXCLUSIVE:
8133: case XML_SCHEMA_FACET_MAXINCLUSIVE:
8134: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8135: case XML_SCHEMA_FACET_TOTALDIGITS:
8136: case XML_SCHEMA_FACET_FRACTIONDIGITS:
8137: case XML_SCHEMA_FACET_PATTERN:
8138: case XML_SCHEMA_FACET_ENUMERATION:
8139: case XML_SCHEMA_FACET_WHITESPACE:
8140: case XML_SCHEMA_FACET_LENGTH:
8141: case XML_SCHEMA_FACET_MAXLENGTH:
8142: case XML_SCHEMA_FACET_MINLENGTH: {
8143: xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8144: ADD_ANNOTATION(annot)
8145: }
8146: break;
8147: case XML_SCHEMA_TYPE_SIMPLE:
8148: case XML_SCHEMA_TYPE_COMPLEX: {
8149: xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8150: ADD_ANNOTATION(annot)
8151: }
8152: break;
8153: case XML_SCHEMA_TYPE_GROUP: {
8154: xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8155: ADD_ANNOTATION(annot)
8156: }
8157: break;
8158: case XML_SCHEMA_TYPE_SEQUENCE:
8159: case XML_SCHEMA_TYPE_CHOICE:
8160: case XML_SCHEMA_TYPE_ALL: {
8161: xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8162: ADD_ANNOTATION(annot)
8163: }
8164: break;
8165: default:
8166: xmlSchemaPCustomErr(NULL,
8167: XML_SCHEMAP_INTERNAL,
8168: NULL, NULL,
8169: "Internal error: xmlSchemaAddAnnotation, "
8170: "The item is not a annotated schema component", NULL);
8171: break;
8172: }
8173: return (annot);
8174: }
8175:
8176: /**
8177: * xmlSchemaParseIDCSelectorAndField:
8178: * @ctxt: a schema validation context
8179: * @schema: the schema being built
8180: * @node: a subtree containing XML Schema informations
8181: *
8182: * Parses a XML Schema identity-contraint definition's
8183: * <selector> and <field> elements.
8184: *
8185: * Returns the parsed identity-constraint definition.
8186: */
8187: static xmlSchemaIDCSelectPtr
8188: xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8189: xmlSchemaIDCPtr idc,
8190: xmlNodePtr node,
8191: int isField)
8192: {
8193: xmlSchemaIDCSelectPtr item;
8194: xmlNodePtr child = NULL;
8195: xmlAttrPtr attr;
8196:
8197: /*
8198: * Check for illegal attributes.
8199: */
8200: attr = node->properties;
8201: while (attr != NULL) {
8202: if (attr->ns == NULL) {
8203: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8204: (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8205: xmlSchemaPIllegalAttrErr(ctxt,
8206: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8207: }
8208: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8209: xmlSchemaPIllegalAttrErr(ctxt,
8210: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8211: }
8212: attr = attr->next;
8213: }
8214: /*
8215: * Create the item.
8216: */
8217: item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8218: if (item == NULL) {
8219: xmlSchemaPErrMemory(ctxt,
8220: "allocating a 'selector' of an identity-constraint definition",
8221: NULL);
8222: return (NULL);
8223: }
8224: memset(item, 0, sizeof(xmlSchemaIDCSelect));
8225: /*
8226: * Attribute "xpath" (mandatory).
8227: */
8228: attr = xmlSchemaGetPropNode(node, "xpath");
8229: if (attr == NULL) {
8230: xmlSchemaPMissingAttrErr(ctxt,
8231: XML_SCHEMAP_S4S_ATTR_MISSING,
8232: NULL, node,
8233: "name", NULL);
8234: } else {
8235: item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8236: /*
8237: * URGENT TODO: "field"s have an other syntax than "selector"s.
8238: */
8239:
8240: if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8241: isField) == -1) {
8242: xmlSchemaPErr(ctxt,
8243: (xmlNodePtr) attr,
8244: XML_SCHEMAP_INTERNAL,
8245: "Internal error: xmlSchemaParseIDCSelectorAndField, "
8246: "validating the XPath expression of a IDC selector.\n",
8247: NULL, NULL);
8248: }
8249:
8250: }
8251: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8252: /*
8253: * And now for the children...
8254: */
8255: child = node->children;
8256: if (IS_SCHEMA(child, "annotation")) {
8257: /*
8258: * Add the annotation to the parent IDC.
8259: */
8260: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8261: xmlSchemaParseAnnotation(ctxt, child, 1));
8262: child = child->next;
8263: }
8264: if (child != NULL) {
8265: xmlSchemaPContentErr(ctxt,
8266: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8267: NULL, node, child,
8268: NULL, "(annotation?)");
8269: }
8270:
8271: return (item);
8272: }
8273:
8274: /**
8275: * xmlSchemaParseIDC:
8276: * @ctxt: a schema validation context
8277: * @schema: the schema being built
8278: * @node: a subtree containing XML Schema informations
8279: *
8280: * Parses a XML Schema identity-contraint definition.
8281: *
8282: * Returns the parsed identity-constraint definition.
8283: */
8284: static xmlSchemaIDCPtr
8285: xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8286: xmlSchemaPtr schema,
8287: xmlNodePtr node,
8288: xmlSchemaTypeType idcCategory,
8289: const xmlChar *targetNamespace)
8290: {
8291: xmlSchemaIDCPtr item = NULL;
8292: xmlNodePtr child = NULL;
8293: xmlAttrPtr attr;
8294: const xmlChar *name = NULL;
8295: xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8296:
8297: /*
8298: * Check for illegal attributes.
8299: */
8300: attr = node->properties;
8301: while (attr != NULL) {
8302: if (attr->ns == NULL) {
8303: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8304: (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8305: ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8306: (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8307: xmlSchemaPIllegalAttrErr(ctxt,
8308: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8309: }
8310: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8311: xmlSchemaPIllegalAttrErr(ctxt,
8312: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8313: }
8314: attr = attr->next;
8315: }
8316: /*
8317: * Attribute "name" (mandatory).
8318: */
8319: attr = xmlSchemaGetPropNode(node, "name");
8320: if (attr == NULL) {
8321: xmlSchemaPMissingAttrErr(ctxt,
8322: XML_SCHEMAP_S4S_ATTR_MISSING,
8323: NULL, node,
8324: "name", NULL);
8325: return (NULL);
8326: } else if (xmlSchemaPValAttrNode(ctxt,
8327: NULL, attr,
8328: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8329: return (NULL);
8330: }
8331: /* Create the component. */
8332: item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8333: idcCategory, node);
8334: if (item == NULL)
8335: return(NULL);
8336:
8337: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8338: if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8339: /*
8340: * Attribute "refer" (mandatory).
8341: */
8342: attr = xmlSchemaGetPropNode(node, "refer");
8343: if (attr == NULL) {
8344: xmlSchemaPMissingAttrErr(ctxt,
8345: XML_SCHEMAP_S4S_ATTR_MISSING,
8346: NULL, node,
8347: "refer", NULL);
8348: } else {
8349: /*
8350: * Create a reference item.
8351: */
8352: item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8353: NULL, NULL);
8354: if (item->ref == NULL)
8355: return (NULL);
8356: xmlSchemaPValAttrNodeQName(ctxt, schema,
8357: NULL, attr,
8358: &(item->ref->targetNamespace),
8359: &(item->ref->name));
8360: xmlSchemaCheckReference(ctxt, schema, node, attr,
8361: item->ref->targetNamespace);
8362: }
8363: }
8364: /*
8365: * And now for the children...
8366: */
8367: child = node->children;
8368: if (IS_SCHEMA(child, "annotation")) {
8369: item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8370: child = child->next;
8371: }
8372: if (child == NULL) {
8373: xmlSchemaPContentErr(ctxt,
8374: XML_SCHEMAP_S4S_ELEM_MISSING,
8375: NULL, node, child,
8376: "A child element is missing",
8377: "(annotation?, (selector, field+))");
8378: }
8379: /*
8380: * Child element <selector>.
8381: */
8382: if (IS_SCHEMA(child, "selector")) {
8383: item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8384: item, child, 0);
8385: child = child->next;
8386: /*
8387: * Child elements <field>.
8388: */
8389: if (IS_SCHEMA(child, "field")) {
8390: do {
8391: field = xmlSchemaParseIDCSelectorAndField(ctxt,
8392: item, child, 1);
8393: if (field != NULL) {
8394: field->index = item->nbFields;
8395: item->nbFields++;
8396: if (lastField != NULL)
8397: lastField->next = field;
8398: else
8399: item->fields = field;
8400: lastField = field;
8401: }
8402: child = child->next;
8403: } while (IS_SCHEMA(child, "field"));
8404: } else {
8405: xmlSchemaPContentErr(ctxt,
8406: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8407: NULL, node, child,
8408: NULL, "(annotation?, (selector, field+))");
8409: }
8410: }
8411: if (child != NULL) {
8412: xmlSchemaPContentErr(ctxt,
8413: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8414: NULL, node, child,
8415: NULL, "(annotation?, (selector, field+))");
8416: }
8417:
8418: return (item);
8419: }
8420:
8421: /**
8422: * xmlSchemaParseElement:
8423: * @ctxt: a schema validation context
8424: * @schema: the schema being built
8425: * @node: a subtree containing XML Schema informations
8426: * @topLevel: indicates if this is global declaration
8427: *
8428: * Parses a XML schema element declaration.
8429: * *WARNING* this interface is highly subject to change
8430: *
8431: * Returns the element declaration or a particle; NULL in case
8432: * of an error or if the particle has minOccurs==maxOccurs==0.
8433: */
8434: static xmlSchemaBasicItemPtr
8435: xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8436: xmlNodePtr node, int *isElemRef, int topLevel)
8437: {
8438: xmlSchemaElementPtr decl = NULL;
8439: xmlSchemaParticlePtr particle = NULL;
8440: xmlSchemaAnnotPtr annot = NULL;
8441: xmlNodePtr child = NULL;
8442: xmlAttrPtr attr, nameAttr;
8443: int min, max, isRef = 0;
8444: xmlChar *des = NULL;
8445:
8446: /* 3.3.3 Constraints on XML Representations of Element Declarations */
8447: /* TODO: Complete implementation of 3.3.6 */
8448:
8449: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8450: return (NULL);
8451:
8452: if (isElemRef != NULL)
8453: *isElemRef = 0;
8454: /*
8455: * If we get a "ref" attribute on a local <element> we will assume it's
8456: * a reference - even if there's a "name" attribute; this seems to be more
8457: * robust.
8458: */
8459: nameAttr = xmlSchemaGetPropNode(node, "name");
8460: attr = xmlSchemaGetPropNode(node, "ref");
8461: if ((topLevel) || (attr == NULL)) {
8462: if (nameAttr == NULL) {
8463: xmlSchemaPMissingAttrErr(ctxt,
8464: XML_SCHEMAP_S4S_ATTR_MISSING,
8465: NULL, node, "name", NULL);
8466: return (NULL);
8467: }
8468: } else
8469: isRef = 1;
8470:
8471: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8472: child = node->children;
8473: if (IS_SCHEMA(child, "annotation")) {
8474: annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8475: child = child->next;
8476: }
8477: /*
8478: * Skip particle part if a global declaration.
8479: */
8480: if (topLevel)
8481: goto declaration_part;
8482: /*
8483: * The particle part ==================================================
8484: */
8485: min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8486: max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8487: xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8488: particle = xmlSchemaAddParticle(ctxt, node, min, max);
8489: if (particle == NULL)
8490: goto return_null;
8491:
8492: /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8493:
8494: if (isRef) {
8495: const xmlChar *refNs = NULL, *ref = NULL;
8496: xmlSchemaQNameRefPtr refer = NULL;
8497: /*
8498: * The reference part =============================================
8499: */
8500: if (isElemRef != NULL)
8501: *isElemRef = 1;
8502:
8503: xmlSchemaPValAttrNodeQName(ctxt, schema,
8504: NULL, attr, &refNs, &ref);
8505: xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8506: /*
8507: * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8508: */
8509: if (nameAttr != NULL) {
8510: xmlSchemaPMutualExclAttrErr(ctxt,
8511: XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8512: }
8513: /*
8514: * Check for illegal attributes.
8515: */
8516: attr = node->properties;
8517: while (attr != NULL) {
8518: if (attr->ns == NULL) {
8519: if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8520: xmlStrEqual(attr->name, BAD_CAST "name") ||
8521: xmlStrEqual(attr->name, BAD_CAST "id") ||
8522: xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8523: xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8524: {
8525: attr = attr->next;
8526: continue;
8527: } else {
8528: /* SPEC (3.3.3 : 2.2) */
8529: xmlSchemaPCustomAttrErr(ctxt,
8530: XML_SCHEMAP_SRC_ELEMENT_2_2,
8531: NULL, NULL, attr,
8532: "Only the attributes 'minOccurs', 'maxOccurs' and "
8533: "'id' are allowed in addition to 'ref'");
8534: break;
8535: }
8536: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8537: xmlSchemaPIllegalAttrErr(ctxt,
8538: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8539: }
8540: attr = attr->next;
8541: }
8542: /*
8543: * No children except <annotation> expected.
8544: */
8545: if (child != NULL) {
8546: xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8547: NULL, node, child, NULL, "(annotation?)");
8548: }
8549: if ((min == 0) && (max == 0))
8550: goto return_null;
8551: /*
8552: * Create the reference item and attach it to the particle.
8553: */
8554: refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8555: ref, refNs);
8556: if (refer == NULL)
8557: goto return_null;
8558: particle->children = (xmlSchemaTreeItemPtr) refer;
8559: particle->annot = annot;
8560: /*
8561: * Add the particle to pending components, since the reference
8562: * need to be resolved.
8563: */
8564: WXS_ADD_PENDING(ctxt, particle);
8565: return ((xmlSchemaBasicItemPtr) particle);
8566: }
8567: /*
8568: * The declaration part ===============================================
8569: */
8570: declaration_part:
8571: {
8572: const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8573: xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8574:
8575: if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8576: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8577: goto return_null;
8578: /*
8579: * Evaluate the target namespace.
8580: */
8581: if (topLevel) {
8582: ns = ctxt->targetNamespace;
8583: } else {
8584: attr = xmlSchemaGetPropNode(node, "form");
8585: if (attr != NULL) {
8586: attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8587: if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8588: ns = ctxt->targetNamespace;
8589: } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8590: xmlSchemaPSimpleTypeErr(ctxt,
8591: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8592: NULL, (xmlNodePtr) attr,
8593: NULL, "(qualified | unqualified)",
8594: attrValue, NULL, NULL, NULL);
8595: }
8596: } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8597: ns = ctxt->targetNamespace;
8598: }
8599: decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8600: if (decl == NULL) {
8601: goto return_null;
8602: }
8603: /*
8604: * Check for illegal attributes.
8605: */
8606: attr = node->properties;
8607: while (attr != NULL) {
8608: if (attr->ns == NULL) {
8609: if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8610: (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8611: (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8612: (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8613: (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8614: (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8615: (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8616: {
8617: if (topLevel == 0) {
8618: if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8619: (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8620: (!xmlStrEqual(attr->name, BAD_CAST "form")))
8621: {
8622: xmlSchemaPIllegalAttrErr(ctxt,
8623: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8624: }
8625: } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8626: (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8627: (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8628:
8629: xmlSchemaPIllegalAttrErr(ctxt,
8630: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8631: }
8632: }
8633: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8634:
8635: xmlSchemaPIllegalAttrErr(ctxt,
8636: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8637: }
8638: attr = attr->next;
8639: }
8640: /*
8641: * Extract/validate attributes.
8642: */
8643: if (topLevel) {
8644: /*
8645: * Process top attributes of global element declarations here.
8646: */
8647: decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8648: decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8649: xmlSchemaPValAttrQName(ctxt, schema,
8650: NULL, node, "substitutionGroup",
8651: &(decl->substGroupNs), &(decl->substGroup));
8652: if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8653: decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8654: /*
8655: * Attribute "final".
8656: */
8657: attr = xmlSchemaGetPropNode(node, "final");
8658: if (attr == NULL) {
8659: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8660: decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8661: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8662: decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8663: } else {
8664: attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8665: if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8666: -1,
8667: XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8668: XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8669: xmlSchemaPSimpleTypeErr(ctxt,
8670: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8671: NULL, (xmlNodePtr) attr,
8672: NULL, "(#all | List of (extension | restriction))",
8673: attrValue, NULL, NULL, NULL);
8674: }
8675: }
8676: }
8677: /*
8678: * Attribute "block".
8679: */
8680: attr = xmlSchemaGetPropNode(node, "block");
8681: if (attr == NULL) {
8682: /*
8683: * Apply default "block" values.
8684: */
8685: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8686: decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8687: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8688: decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8689: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8690: decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8691: } else {
8692: attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8693: if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8694: -1,
8695: XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8696: XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8697: XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8698: xmlSchemaPSimpleTypeErr(ctxt,
8699: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8700: NULL, (xmlNodePtr) attr,
8701: NULL, "(#all | List of (extension | "
8702: "restriction | substitution))", attrValue,
8703: NULL, NULL, NULL);
8704: }
8705: }
8706: if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8707: decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8708:
8709: attr = xmlSchemaGetPropNode(node, "type");
8710: if (attr != NULL) {
8711: xmlSchemaPValAttrNodeQName(ctxt, schema,
8712: NULL, attr,
8713: &(decl->namedTypeNs), &(decl->namedType));
8714: xmlSchemaCheckReference(ctxt, schema, node,
8715: attr, decl->namedTypeNs);
8716: }
8717: decl->value = xmlSchemaGetProp(ctxt, node, "default");
8718: attr = xmlSchemaGetPropNode(node, "fixed");
8719: if (attr != NULL) {
8720: fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8721: if (decl->value != NULL) {
8722: /*
8723: * 3.3.3 : 1
8724: * default and fixed must not both be present.
8725: */
8726: xmlSchemaPMutualExclAttrErr(ctxt,
8727: XML_SCHEMAP_SRC_ELEMENT_1,
8728: NULL, attr, "default", "fixed");
8729: } else {
8730: decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8731: decl->value = fixed;
8732: }
8733: }
8734: /*
8735: * And now for the children...
8736: */
8737: if (IS_SCHEMA(child, "complexType")) {
8738: /*
8739: * 3.3.3 : 3
8740: * "type" and either <simpleType> or <complexType> are mutually
8741: * exclusive
8742: */
8743: if (decl->namedType != NULL) {
8744: xmlSchemaPContentErr(ctxt,
8745: XML_SCHEMAP_SRC_ELEMENT_3,
8746: NULL, node, child,
8747: "The attribute 'type' and the <complexType> child are "
8748: "mutually exclusive", NULL);
8749: } else
8750: WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8751: child = child->next;
8752: } else if (IS_SCHEMA(child, "simpleType")) {
8753: /*
8754: * 3.3.3 : 3
8755: * "type" and either <simpleType> or <complexType> are
8756: * mutually exclusive
8757: */
8758: if (decl->namedType != NULL) {
8759: xmlSchemaPContentErr(ctxt,
8760: XML_SCHEMAP_SRC_ELEMENT_3,
8761: NULL, node, child,
8762: "The attribute 'type' and the <simpleType> child are "
8763: "mutually exclusive", NULL);
8764: } else
8765: WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8766: child = child->next;
8767: }
8768: while ((IS_SCHEMA(child, "unique")) ||
8769: (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8770: if (IS_SCHEMA(child, "unique")) {
8771: curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8772: XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8773: } else if (IS_SCHEMA(child, "key")) {
8774: curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8775: XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8776: } else if (IS_SCHEMA(child, "keyref")) {
8777: curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8778: XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8779: }
8780: if (lastIDC != NULL)
8781: lastIDC->next = curIDC;
8782: else
8783: decl->idcs = (void *) curIDC;
8784: lastIDC = curIDC;
8785: child = child->next;
8786: }
8787: if (child != NULL) {
8788: xmlSchemaPContentErr(ctxt,
8789: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8790: NULL, node, child,
8791: NULL, "(annotation?, ((simpleType | complexType)?, "
8792: "(unique | key | keyref)*))");
8793: }
8794: decl->annot = annot;
8795: }
8796: /*
8797: * NOTE: Element Declaration Representation OK 4. will be checked at a
8798: * different layer.
8799: */
8800: FREE_AND_NULL(des)
8801: if (topLevel)
8802: return ((xmlSchemaBasicItemPtr) decl);
8803: else {
8804: particle->children = (xmlSchemaTreeItemPtr) decl;
8805: return ((xmlSchemaBasicItemPtr) particle);
8806: }
8807:
8808: return_null:
8809: FREE_AND_NULL(des);
8810: if (annot != NULL) {
8811: if (particle != NULL)
8812: particle->annot = NULL;
8813: if (decl != NULL)
8814: decl->annot = NULL;
8815: xmlSchemaFreeAnnot(annot);
8816: }
8817: return (NULL);
8818: }
8819:
8820: /**
8821: * xmlSchemaParseUnion:
8822: * @ctxt: a schema validation context
8823: * @schema: the schema being built
8824: * @node: a subtree containing XML Schema informations
8825: *
8826: * parse a XML schema Union definition
8827: * *WARNING* this interface is highly subject to change
8828: *
8829: * Returns -1 in case of internal error, 0 in case of success and a positive
8830: * error code otherwise.
8831: */
8832: static int
8833: xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8834: xmlNodePtr node)
8835: {
8836: xmlSchemaTypePtr type;
8837: xmlNodePtr child = NULL;
8838: xmlAttrPtr attr;
8839: const xmlChar *cur = NULL;
8840:
8841: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8842: return (-1);
8843: /* Not a component, don't create it. */
8844: type = ctxt->ctxtType;
8845: /*
8846: * Mark the simple type as being of variety "union".
8847: */
8848: type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8849: /*
8850: * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8851: * then the �simple ur-type definition�."
8852: */
8853: type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8854: /*
8855: * Check for illegal attributes.
8856: */
8857: attr = node->properties;
8858: while (attr != NULL) {
8859: if (attr->ns == NULL) {
8860: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8861: (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8862: xmlSchemaPIllegalAttrErr(ctxt,
8863: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8864: }
8865: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8866: xmlSchemaPIllegalAttrErr(ctxt,
8867: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8868: }
8869: attr = attr->next;
8870: }
8871: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8872: /*
8873: * Attribute "memberTypes". This is a list of QNames.
8874: * TODO: Check the value to contain anything.
8875: */
8876: attr = xmlSchemaGetPropNode(node, "memberTypes");
8877: if (attr != NULL) {
8878: const xmlChar *end;
8879: xmlChar *tmp;
8880: const xmlChar *localName, *nsName;
8881: xmlSchemaTypeLinkPtr link, lastLink = NULL;
8882: xmlSchemaQNameRefPtr ref;
8883:
8884: cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8885: type->base = cur;
8886: do {
8887: while (IS_BLANK_CH(*cur))
8888: cur++;
8889: end = cur;
8890: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8891: end++;
8892: if (end == cur)
8893: break;
8894: tmp = xmlStrndup(cur, end - cur);
8895: if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8896: NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8897: /*
8898: * Create the member type link.
8899: */
8900: link = (xmlSchemaTypeLinkPtr)
8901: xmlMalloc(sizeof(xmlSchemaTypeLink));
8902: if (link == NULL) {
8903: xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8904: "allocating a type link", NULL);
8905: return (-1);
8906: }
8907: link->type = NULL;
8908: link->next = NULL;
8909: if (lastLink == NULL)
8910: type->memberTypes = link;
8911: else
8912: lastLink->next = link;
8913: lastLink = link;
8914: /*
8915: * Create a reference item.
8916: */
8917: ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8918: localName, nsName);
8919: if (ref == NULL) {
8920: FREE_AND_NULL(tmp)
8921: return (-1);
8922: }
8923: /*
8924: * Assign the reference to the link, it will be resolved
8925: * later during fixup of the union simple type.
8926: */
8927: link->type = (xmlSchemaTypePtr) ref;
8928: }
8929: FREE_AND_NULL(tmp)
8930: cur = end;
8931: } while (*cur != 0);
8932:
8933: }
8934: /*
8935: * And now for the children...
8936: */
8937: child = node->children;
8938: if (IS_SCHEMA(child, "annotation")) {
8939: /*
8940: * Add the annotation to the simple type ancestor.
8941: */
8942: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8943: xmlSchemaParseAnnotation(ctxt, child, 1));
8944: child = child->next;
8945: }
8946: if (IS_SCHEMA(child, "simpleType")) {
8947: xmlSchemaTypePtr subtype, last = NULL;
8948:
8949: /*
8950: * Anchor the member types in the "subtypes" field of the
8951: * simple type.
8952: */
8953: while (IS_SCHEMA(child, "simpleType")) {
8954: subtype = (xmlSchemaTypePtr)
8955: xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8956: if (subtype != NULL) {
8957: if (last == NULL) {
8958: type->subtypes = subtype;
8959: last = subtype;
8960: } else {
8961: last->next = subtype;
8962: last = subtype;
8963: }
8964: last->next = NULL;
8965: }
8966: child = child->next;
8967: }
8968: }
8969: if (child != NULL) {
8970: xmlSchemaPContentErr(ctxt,
8971: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8972: NULL, node, child, NULL, "(annotation?, simpleType*)");
8973: }
8974: if ((attr == NULL) && (type->subtypes == NULL)) {
8975: /*
8976: * src-union-memberTypes-or-simpleTypes
8977: * Either the memberTypes [attribute] of the <union> element must
8978: * be non-empty or there must be at least one simpleType [child].
8979: */
8980: xmlSchemaPCustomErr(ctxt,
8981: XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8982: NULL, node,
8983: "Either the attribute 'memberTypes' or "
8984: "at least one <simpleType> child must be present", NULL);
8985: }
8986: return (0);
8987: }
8988:
8989: /**
8990: * xmlSchemaParseList:
8991: * @ctxt: a schema validation context
8992: * @schema: the schema being built
8993: * @node: a subtree containing XML Schema informations
8994: *
8995: * parse a XML schema List definition
8996: * *WARNING* this interface is highly subject to change
8997: *
8998: * Returns -1 in case of error, 0 if the declaration is improper and
8999: * 1 in case of success.
9000: */
9001: static xmlSchemaTypePtr
9002: xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9003: xmlNodePtr node)
9004: {
9005: xmlSchemaTypePtr type;
9006: xmlNodePtr child = NULL;
9007: xmlAttrPtr attr;
9008:
9009: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9010: return (NULL);
9011: /* Not a component, don't create it. */
9012: type = ctxt->ctxtType;
9013: /*
9014: * Mark the type as being of variety "list".
9015: */
9016: type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9017: /*
9018: * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9019: * then the �simple ur-type definition�."
9020: */
9021: type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9022: /*
9023: * Check for illegal attributes.
9024: */
9025: attr = node->properties;
9026: while (attr != NULL) {
9027: if (attr->ns == NULL) {
9028: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9029: (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9030: xmlSchemaPIllegalAttrErr(ctxt,
9031: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9032: }
9033: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9034: xmlSchemaPIllegalAttrErr(ctxt,
9035: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9036: }
9037: attr = attr->next;
9038: }
9039:
9040: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9041:
9042: /*
9043: * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9044: * fields for holding the reference to the itemType.
9045: *
9046: * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9047: * the "ref" fields.
9048: */
9049: xmlSchemaPValAttrQName(ctxt, schema, NULL,
9050: node, "itemType", &(type->baseNs), &(type->base));
9051: /*
9052: * And now for the children...
9053: */
9054: child = node->children;
9055: if (IS_SCHEMA(child, "annotation")) {
9056: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9057: xmlSchemaParseAnnotation(ctxt, child, 1));
9058: child = child->next;
9059: }
9060: if (IS_SCHEMA(child, "simpleType")) {
9061: /*
9062: * src-list-itemType-or-simpleType
9063: * Either the itemType [attribute] or the <simpleType> [child] of
9064: * the <list> element must be present, but not both.
9065: */
9066: if (type->base != NULL) {
9067: xmlSchemaPCustomErr(ctxt,
9068: XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9069: NULL, node,
9070: "The attribute 'itemType' and the <simpleType> child "
9071: "are mutually exclusive", NULL);
9072: } else {
9073: type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9074: }
9075: child = child->next;
9076: } else if (type->base == NULL) {
9077: xmlSchemaPCustomErr(ctxt,
9078: XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9079: NULL, node,
9080: "Either the attribute 'itemType' or the <simpleType> child "
9081: "must be present", NULL);
9082: }
9083: if (child != NULL) {
9084: xmlSchemaPContentErr(ctxt,
9085: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9086: NULL, node, child, NULL, "(annotation?, simpleType?)");
9087: }
9088: if ((type->base == NULL) &&
9089: (type->subtypes == NULL) &&
9090: (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9091: xmlSchemaPCustomErr(ctxt,
9092: XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9093: NULL, node,
9094: "Either the attribute 'itemType' or the <simpleType> child "
9095: "must be present", NULL);
9096: }
9097: return (NULL);
9098: }
9099:
9100: /**
9101: * xmlSchemaParseSimpleType:
9102: * @ctxt: a schema validation context
9103: * @schema: the schema being built
9104: * @node: a subtree containing XML Schema informations
9105: *
9106: * parse a XML schema Simple Type definition
9107: * *WARNING* this interface is highly subject to change
9108: *
9109: * Returns -1 in case of error, 0 if the declaration is improper and
9110: * 1 in case of success.
9111: */
9112: static xmlSchemaTypePtr
9113: xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9114: xmlNodePtr node, int topLevel)
9115: {
9116: xmlSchemaTypePtr type, oldCtxtType;
9117: xmlNodePtr child = NULL;
9118: const xmlChar *attrValue = NULL;
9119: xmlAttrPtr attr;
9120: int hasRestriction = 0;
9121:
9122: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9123: return (NULL);
9124:
9125: if (topLevel) {
9126: attr = xmlSchemaGetPropNode(node, "name");
9127: if (attr == NULL) {
9128: xmlSchemaPMissingAttrErr(ctxt,
9129: XML_SCHEMAP_S4S_ATTR_MISSING,
9130: NULL, node,
9131: "name", NULL);
9132: return (NULL);
9133: } else {
9134: if (xmlSchemaPValAttrNode(ctxt,
9135: NULL, attr,
9136: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9137: return (NULL);
9138: /*
9139: * Skip built-in types.
9140: */
9141: if (ctxt->isS4S) {
9142: xmlSchemaTypePtr biType;
9143:
9144: if (ctxt->isRedefine) {
9145: /*
9146: * REDEFINE: Disallow redefinition of built-in-types.
9147: * TODO: It seems that the spec does not say anything
9148: * about this case.
9149: */
9150: xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9151: NULL, node,
9152: "Redefinition of built-in simple types is not "
9153: "supported", NULL);
9154: return(NULL);
9155: }
9156: biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9157: if (biType != NULL)
9158: return (biType);
9159: }
9160: }
9161: }
9162: /*
9163: * TargetNamespace:
9164: * SPEC "The �actual value� of the targetNamespace [attribute]
9165: * of the <schema> ancestor element information item if present,
9166: * otherwise �absent�.
9167: */
9168: if (topLevel == 0) {
9169: #ifdef ENABLE_NAMED_LOCALS
9170: char buf[40];
9171: #endif
9172: /*
9173: * Parse as local simple type definition.
9174: */
9175: #ifdef ENABLE_NAMED_LOCALS
9176: snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9177: type = xmlSchemaAddType(ctxt, schema,
9178: XML_SCHEMA_TYPE_SIMPLE,
9179: xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9180: ctxt->targetNamespace, node, 0);
9181: #else
9182: type = xmlSchemaAddType(ctxt, schema,
9183: XML_SCHEMA_TYPE_SIMPLE,
9184: NULL, ctxt->targetNamespace, node, 0);
9185: #endif
9186: if (type == NULL)
9187: return (NULL);
9188: type->type = XML_SCHEMA_TYPE_SIMPLE;
9189: type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9190: /*
9191: * Check for illegal attributes.
9192: */
9193: attr = node->properties;
9194: while (attr != NULL) {
9195: if (attr->ns == NULL) {
9196: if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9197: xmlSchemaPIllegalAttrErr(ctxt,
9198: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9199: }
9200: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9201: xmlSchemaPIllegalAttrErr(ctxt,
9202: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9203: }
9204: attr = attr->next;
9205: }
9206: } else {
9207: /*
9208: * Parse as global simple type definition.
9209: *
9210: * Note that attrValue is the value of the attribute "name" here.
9211: */
9212: type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9213: attrValue, ctxt->targetNamespace, node, 1);
9214: if (type == NULL)
9215: return (NULL);
9216: type->type = XML_SCHEMA_TYPE_SIMPLE;
9217: type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9218: type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9219: /*
9220: * Check for illegal attributes.
9221: */
9222: attr = node->properties;
9223: while (attr != NULL) {
9224: if (attr->ns == NULL) {
9225: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9226: (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9227: (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9228: xmlSchemaPIllegalAttrErr(ctxt,
9229: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9230: }
9231: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9232: xmlSchemaPIllegalAttrErr(ctxt,
9233: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9234: }
9235: attr = attr->next;
9236: }
9237: /*
9238: * Attribute "final".
9239: */
9240: attr = xmlSchemaGetPropNode(node, "final");
9241: if (attr == NULL) {
9242: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9243: type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9244: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9245: type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9246: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9247: type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9248: } else {
9249: attrValue = xmlSchemaGetProp(ctxt, node, "final");
9250: if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9251: -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9252: XML_SCHEMAS_TYPE_FINAL_LIST,
9253: XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9254:
9255: xmlSchemaPSimpleTypeErr(ctxt,
9256: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9257: WXS_BASIC_CAST type, (xmlNodePtr) attr,
9258: NULL, "(#all | List of (list | union | restriction)",
9259: attrValue, NULL, NULL, NULL);
9260: }
9261: }
9262: }
9263: type->targetNamespace = ctxt->targetNamespace;
9264: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9265: /*
9266: * And now for the children...
9267: */
9268: oldCtxtType = ctxt->ctxtType;
9269:
9270: ctxt->ctxtType = type;
9271:
9272: child = node->children;
9273: if (IS_SCHEMA(child, "annotation")) {
9274: type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9275: child = child->next;
9276: }
9277: if (child == NULL) {
9278: xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9279: NULL, node, child, NULL,
9280: "(annotation?, (restriction | list | union))");
9281: } else if (IS_SCHEMA(child, "restriction")) {
9282: xmlSchemaParseRestriction(ctxt, schema, child,
9283: XML_SCHEMA_TYPE_SIMPLE);
9284: hasRestriction = 1;
9285: child = child->next;
9286: } else if (IS_SCHEMA(child, "list")) {
9287: xmlSchemaParseList(ctxt, schema, child);
9288: child = child->next;
9289: } else if (IS_SCHEMA(child, "union")) {
9290: xmlSchemaParseUnion(ctxt, schema, child);
9291: child = child->next;
9292: }
9293: if (child != NULL) {
9294: xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9295: NULL, node, child, NULL,
9296: "(annotation?, (restriction | list | union))");
9297: }
9298: /*
9299: * REDEFINE: SPEC src-redefine (5)
9300: * "Within the [children], each <simpleType> must have a
9301: * <restriction> among its [children] ... the �actual value� of whose
9302: * base [attribute] must be the same as the �actual value� of its own
9303: * name attribute plus target namespace;"
9304: */
9305: if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9306: xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9307: NULL, node, "This is a redefinition, thus the "
9308: "<simpleType> must have a <restriction> child", NULL);
9309: }
9310:
9311: ctxt->ctxtType = oldCtxtType;
9312: return (type);
9313: }
9314:
9315: /**
9316: * xmlSchemaParseModelGroupDefRef:
9317: * @ctxt: the parser context
9318: * @schema: the schema being built
9319: * @node: the node
9320: *
9321: * Parses a reference to a model group definition.
9322: *
9323: * We will return a particle component with a qname-component or
9324: * NULL in case of an error.
9325: */
9326: static xmlSchemaTreeItemPtr
9327: xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9328: xmlSchemaPtr schema,
9329: xmlNodePtr node)
9330: {
9331: xmlSchemaParticlePtr item;
9332: xmlNodePtr child = NULL;
9333: xmlAttrPtr attr;
9334: const xmlChar *ref = NULL, *refNs = NULL;
9335: int min, max;
9336:
9337: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9338: return (NULL);
9339:
9340: attr = xmlSchemaGetPropNode(node, "ref");
9341: if (attr == NULL) {
9342: xmlSchemaPMissingAttrErr(ctxt,
9343: XML_SCHEMAP_S4S_ATTR_MISSING,
9344: NULL, node, "ref", NULL);
9345: return (NULL);
9346: } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9347: attr, &refNs, &ref) != 0) {
9348: return (NULL);
9349: }
9350: xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9351: min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9352: max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9353: "(xs:nonNegativeInteger | unbounded)");
9354: /*
9355: * Check for illegal attributes.
9356: */
9357: attr = node->properties;
9358: while (attr != NULL) {
9359: if (attr->ns == NULL) {
9360: if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9361: (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9362: (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9363: (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9364: xmlSchemaPIllegalAttrErr(ctxt,
9365: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9366: }
9367: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9368: xmlSchemaPIllegalAttrErr(ctxt,
9369: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9370: }
9371: attr = attr->next;
9372: }
9373: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9374: item = xmlSchemaAddParticle(ctxt, node, min, max);
9375: if (item == NULL)
9376: return (NULL);
9377: /*
9378: * Create a qname-reference and set as the term; it will be substituted
9379: * for the model group after the reference has been resolved.
9380: */
9381: item->children = (xmlSchemaTreeItemPtr)
9382: xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9383: xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9384: /*
9385: * And now for the children...
9386: */
9387: child = node->children;
9388: /* TODO: Is annotation even allowed for a model group reference? */
9389: if (IS_SCHEMA(child, "annotation")) {
9390: /*
9391: * TODO: What to do exactly with the annotation?
9392: */
9393: item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9394: child = child->next;
9395: }
9396: if (child != NULL) {
9397: xmlSchemaPContentErr(ctxt,
9398: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9399: NULL, node, child, NULL,
9400: "(annotation?)");
9401: }
9402: /*
9403: * Corresponds to no component at all if minOccurs==maxOccurs==0.
9404: */
9405: if ((min == 0) && (max == 0))
9406: return (NULL);
9407:
9408: return ((xmlSchemaTreeItemPtr) item);
9409: }
9410:
9411: /**
9412: * xmlSchemaParseModelGroupDefinition:
9413: * @ctxt: a schema validation context
9414: * @schema: the schema being built
9415: * @node: a subtree containing XML Schema informations
9416: *
9417: * Parses a XML schema model group definition.
9418: *
9419: * Note that the contraint src-redefine (6.2) can't be applied until
9420: * references have been resolved. So we will do this at the
9421: * component fixup level.
9422: *
9423: * *WARNING* this interface is highly subject to change
9424: *
9425: * Returns -1 in case of error, 0 if the declaration is improper and
9426: * 1 in case of success.
9427: */
9428: static xmlSchemaModelGroupDefPtr
9429: xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9430: xmlSchemaPtr schema,
9431: xmlNodePtr node)
9432: {
9433: xmlSchemaModelGroupDefPtr item;
9434: xmlNodePtr child = NULL;
9435: xmlAttrPtr attr;
9436: const xmlChar *name;
9437:
9438: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9439: return (NULL);
9440:
9441: attr = xmlSchemaGetPropNode(node, "name");
9442: if (attr == NULL) {
9443: xmlSchemaPMissingAttrErr(ctxt,
9444: XML_SCHEMAP_S4S_ATTR_MISSING,
9445: NULL, node,
9446: "name", NULL);
9447: return (NULL);
9448: } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9449: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9450: return (NULL);
9451: }
9452: item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9453: ctxt->targetNamespace, node);
9454: if (item == NULL)
9455: return (NULL);
9456: /*
9457: * Check for illegal attributes.
9458: */
9459: attr = node->properties;
9460: while (attr != NULL) {
9461: if (attr->ns == NULL) {
9462: if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9463: (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9464: xmlSchemaPIllegalAttrErr(ctxt,
9465: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9466: }
9467: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9468: xmlSchemaPIllegalAttrErr(ctxt,
9469: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9470: }
9471: attr = attr->next;
9472: }
9473: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9474: /*
9475: * And now for the children...
9476: */
9477: child = node->children;
9478: if (IS_SCHEMA(child, "annotation")) {
9479: item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9480: child = child->next;
9481: }
9482: if (IS_SCHEMA(child, "all")) {
9483: item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9484: XML_SCHEMA_TYPE_ALL, 0);
9485: child = child->next;
9486: } else if (IS_SCHEMA(child, "choice")) {
9487: item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9488: XML_SCHEMA_TYPE_CHOICE, 0);
9489: child = child->next;
9490: } else if (IS_SCHEMA(child, "sequence")) {
9491: item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9492: XML_SCHEMA_TYPE_SEQUENCE, 0);
9493: child = child->next;
9494: }
9495:
9496:
9497:
9498: if (child != NULL) {
9499: xmlSchemaPContentErr(ctxt,
9500: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9501: NULL, node, child, NULL,
9502: "(annotation?, (all | choice | sequence)?)");
9503: }
9504: return (item);
9505: }
9506:
9507: /**
9508: * xmlSchemaCleanupDoc:
9509: * @ctxt: a schema validation context
9510: * @node: the root of the document.
9511: *
9512: * removes unwanted nodes in a schemas document tree
9513: */
9514: static void
9515: xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9516: {
9517: xmlNodePtr delete, cur;
9518:
9519: if ((ctxt == NULL) || (root == NULL)) return;
9520:
9521: /*
9522: * Remove all the blank text nodes
9523: */
9524: delete = NULL;
9525: cur = root;
9526: while (cur != NULL) {
9527: if (delete != NULL) {
9528: xmlUnlinkNode(delete);
9529: xmlFreeNode(delete);
9530: delete = NULL;
9531: }
9532: if (cur->type == XML_TEXT_NODE) {
9533: if (IS_BLANK_NODE(cur)) {
9534: if (xmlNodeGetSpacePreserve(cur) != 1) {
9535: delete = cur;
9536: }
9537: }
9538: } else if ((cur->type != XML_ELEMENT_NODE) &&
9539: (cur->type != XML_CDATA_SECTION_NODE)) {
9540: delete = cur;
9541: goto skip_children;
9542: }
9543:
9544: /*
9545: * Skip to next node
9546: */
9547: if (cur->children != NULL) {
9548: if ((cur->children->type != XML_ENTITY_DECL) &&
9549: (cur->children->type != XML_ENTITY_REF_NODE) &&
9550: (cur->children->type != XML_ENTITY_NODE)) {
9551: cur = cur->children;
9552: continue;
9553: }
9554: }
9555: skip_children:
9556: if (cur->next != NULL) {
9557: cur = cur->next;
9558: continue;
9559: }
9560:
9561: do {
9562: cur = cur->parent;
9563: if (cur == NULL)
9564: break;
9565: if (cur == root) {
9566: cur = NULL;
9567: break;
9568: }
9569: if (cur->next != NULL) {
9570: cur = cur->next;
9571: break;
9572: }
9573: } while (cur != NULL);
9574: }
9575: if (delete != NULL) {
9576: xmlUnlinkNode(delete);
9577: xmlFreeNode(delete);
9578: delete = NULL;
9579: }
9580: }
9581:
9582:
9583: static void
9584: xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9585: {
9586: if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9587: schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9588:
9589: if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9590: schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9591:
9592: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9593: schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9594: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9595: schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9596: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9597: schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9598: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9599: schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9600:
9601: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9602: schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9603: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9604: schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9605: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9606: schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9607: }
9608:
9609: static int
9610: xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9611: xmlSchemaPtr schema,
9612: xmlNodePtr node)
9613: {
9614: xmlAttrPtr attr;
9615: const xmlChar *val;
9616: int res = 0, oldErrs = ctxt->nberrors;
9617:
9618: /*
9619: * Those flags should be moved to the parser context flags,
9620: * since they are not visible at the component level. I.e.
9621: * they are used if processing schema *documents* only.
9622: */
9623: res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9624: HFAILURE;
9625:
9626: /*
9627: * Since the version is of type xs:token, we won't bother to
9628: * check it.
9629: */
9630: /* REMOVED:
9631: attr = xmlSchemaGetPropNode(node, "version");
9632: if (attr != NULL) {
9633: res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9634: xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9635: HFAILURE;
9636: }
9637: */
9638: attr = xmlSchemaGetPropNode(node, "targetNamespace");
9639: if (attr != NULL) {
9640: res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9641: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9642: HFAILURE;
9643: if (res != 0) {
9644: ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9645: goto exit;
9646: }
9647: }
9648: attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9649: if (attr != NULL) {
9650: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9651: res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9652: XML_SCHEMAS_QUALIF_ELEM);
9653: HFAILURE;
9654: if (res != 0) {
9655: xmlSchemaPSimpleTypeErr(ctxt,
9656: XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9657: NULL, (xmlNodePtr) attr, NULL,
9658: "(qualified | unqualified)", val, NULL, NULL, NULL);
9659: }
9660: }
9661: attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9662: if (attr != NULL) {
9663: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9664: res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9665: XML_SCHEMAS_QUALIF_ATTR);
9666: HFAILURE;
9667: if (res != 0) {
9668: xmlSchemaPSimpleTypeErr(ctxt,
9669: XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9670: NULL, (xmlNodePtr) attr, NULL,
9671: "(qualified | unqualified)", val, NULL, NULL, NULL);
9672: }
9673: }
9674: attr = xmlSchemaGetPropNode(node, "finalDefault");
9675: if (attr != NULL) {
9676: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9677: res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9678: XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9679: XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9680: -1,
9681: XML_SCHEMAS_FINAL_DEFAULT_LIST,
9682: XML_SCHEMAS_FINAL_DEFAULT_UNION);
9683: HFAILURE;
9684: if (res != 0) {
9685: xmlSchemaPSimpleTypeErr(ctxt,
9686: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9687: NULL, (xmlNodePtr) attr, NULL,
9688: "(#all | List of (extension | restriction | list | union))",
9689: val, NULL, NULL, NULL);
9690: }
9691: }
9692: attr = xmlSchemaGetPropNode(node, "blockDefault");
9693: if (attr != NULL) {
9694: val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9695: res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9696: XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9697: XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9698: XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9699: HFAILURE;
9700: if (res != 0) {
9701: xmlSchemaPSimpleTypeErr(ctxt,
9702: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9703: NULL, (xmlNodePtr) attr, NULL,
9704: "(#all | List of (extension | restriction | substitution))",
9705: val, NULL, NULL, NULL);
9706: }
9707: }
9708:
9709: exit:
9710: if (oldErrs != ctxt->nberrors)
9711: res = ctxt->err;
9712: return(res);
9713: exit_failure:
9714: return(-1);
9715: }
9716:
9717: /**
9718: * xmlSchemaParseSchemaTopLevel:
9719: * @ctxt: a schema validation context
9720: * @schema: the schemas
9721: * @nodes: the list of top level nodes
9722: *
9723: * Returns the internal XML Schema structure built from the resource or
9724: * NULL in case of error
9725: */
9726: static int
9727: xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9728: xmlSchemaPtr schema, xmlNodePtr nodes)
9729: {
9730: xmlNodePtr child;
9731: xmlSchemaAnnotPtr annot;
9732: int res = 0, oldErrs, tmpOldErrs;
9733:
9734: if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9735: return(-1);
9736:
9737: oldErrs = ctxt->nberrors;
9738: child = nodes;
9739: while ((IS_SCHEMA(child, "include")) ||
9740: (IS_SCHEMA(child, "import")) ||
9741: (IS_SCHEMA(child, "redefine")) ||
9742: (IS_SCHEMA(child, "annotation"))) {
9743: if (IS_SCHEMA(child, "annotation")) {
9744: annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9745: if (schema->annot == NULL)
9746: schema->annot = annot;
9747: else
9748: xmlSchemaFreeAnnot(annot);
9749: } else if (IS_SCHEMA(child, "import")) {
9750: tmpOldErrs = ctxt->nberrors;
9751: res = xmlSchemaParseImport(ctxt, schema, child);
9752: HFAILURE;
9753: HSTOP(ctxt);
9754: if (tmpOldErrs != ctxt->nberrors)
9755: goto exit;
9756: } else if (IS_SCHEMA(child, "include")) {
9757: tmpOldErrs = ctxt->nberrors;
9758: res = xmlSchemaParseInclude(ctxt, schema, child);
9759: HFAILURE;
9760: HSTOP(ctxt);
9761: if (tmpOldErrs != ctxt->nberrors)
9762: goto exit;
9763: } else if (IS_SCHEMA(child, "redefine")) {
9764: tmpOldErrs = ctxt->nberrors;
9765: res = xmlSchemaParseRedefine(ctxt, schema, child);
9766: HFAILURE;
9767: HSTOP(ctxt);
9768: if (tmpOldErrs != ctxt->nberrors)
9769: goto exit;
9770: }
9771: child = child->next;
9772: }
9773: /*
9774: * URGENT TODO: Change the functions to return int results.
9775: * We need especially to catch internal errors.
9776: */
9777: while (child != NULL) {
9778: if (IS_SCHEMA(child, "complexType")) {
9779: xmlSchemaParseComplexType(ctxt, schema, child, 1);
9780: child = child->next;
9781: } else if (IS_SCHEMA(child, "simpleType")) {
9782: xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9783: child = child->next;
9784: } else if (IS_SCHEMA(child, "element")) {
9785: xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9786: child = child->next;
9787: } else if (IS_SCHEMA(child, "attribute")) {
9788: xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9789: child = child->next;
9790: } else if (IS_SCHEMA(child, "attributeGroup")) {
9791: xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9792: child = child->next;
9793: } else if (IS_SCHEMA(child, "group")) {
9794: xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9795: child = child->next;
9796: } else if (IS_SCHEMA(child, "notation")) {
9797: xmlSchemaParseNotation(ctxt, schema, child);
9798: child = child->next;
9799: } else {
9800: xmlSchemaPContentErr(ctxt,
9801: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9802: NULL, child->parent, child,
9803: NULL, "((include | import | redefine | annotation)*, "
9804: "(((simpleType | complexType | group | attributeGroup) "
9805: "| element | attribute | notation), annotation*)*)");
9806: child = child->next;
9807: }
9808: while (IS_SCHEMA(child, "annotation")) {
9809: /*
9810: * TODO: We should add all annotations.
9811: */
9812: annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9813: if (schema->annot == NULL)
9814: schema->annot = annot;
9815: else
9816: xmlSchemaFreeAnnot(annot);
9817: child = child->next;
9818: }
9819: }
9820: exit:
9821: ctxt->ctxtType = NULL;
9822: if (oldErrs != ctxt->nberrors)
9823: res = ctxt->err;
9824: return(res);
9825: exit_failure:
9826: return(-1);
9827: }
9828:
9829: static xmlSchemaSchemaRelationPtr
9830: xmlSchemaSchemaRelationCreate(void)
9831: {
9832: xmlSchemaSchemaRelationPtr ret;
9833:
9834: ret = (xmlSchemaSchemaRelationPtr)
9835: xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9836: if (ret == NULL) {
9837: xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9838: return(NULL);
9839: }
9840: memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9841: return(ret);
9842: }
9843:
9844: #if 0
9845: static void
9846: xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9847: {
9848: xmlFree(rel);
9849: }
9850: #endif
9851:
9852: static void
9853: xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9854: {
9855: xmlSchemaRedefPtr prev;
9856:
9857: while (redef != NULL) {
9858: prev = redef;
9859: redef = redef->next;
9860: xmlFree(prev);
9861: }
9862: }
9863:
9864: static void
9865: xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9866: {
9867: /*
9868: * After the construction context has been freed, there will be
9869: * no schema graph available any more. Only the schema buckets
9870: * will stay alive, which are put into the "schemasImports" and
9871: * "includes" slots of the xmlSchema.
9872: */
9873: if (con->buckets != NULL)
9874: xmlSchemaItemListFree(con->buckets);
9875: if (con->pending != NULL)
9876: xmlSchemaItemListFree(con->pending);
9877: if (con->substGroups != NULL)
9878: xmlHashFree(con->substGroups,
9879: (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9880: if (con->redefs != NULL)
9881: xmlSchemaRedefListFree(con->redefs);
9882: if (con->dict != NULL)
9883: xmlDictFree(con->dict);
9884: xmlFree(con);
9885: }
9886:
9887: static xmlSchemaConstructionCtxtPtr
9888: xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9889: {
9890: xmlSchemaConstructionCtxtPtr ret;
9891:
9892: ret = (xmlSchemaConstructionCtxtPtr)
9893: xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9894: if (ret == NULL) {
9895: xmlSchemaPErrMemory(NULL,
9896: "allocating schema construction context", NULL);
9897: return (NULL);
9898: }
9899: memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9900:
9901: ret->buckets = xmlSchemaItemListCreate();
9902: if (ret->buckets == NULL) {
9903: xmlSchemaPErrMemory(NULL,
9904: "allocating list of schema buckets", NULL);
9905: xmlFree(ret);
9906: return (NULL);
9907: }
9908: ret->pending = xmlSchemaItemListCreate();
9909: if (ret->pending == NULL) {
9910: xmlSchemaPErrMemory(NULL,
9911: "allocating list of pending global components", NULL);
9912: xmlSchemaConstructionCtxtFree(ret);
9913: return (NULL);
9914: }
9915: ret->dict = dict;
9916: xmlDictReference(dict);
9917: return(ret);
9918: }
9919:
9920: static xmlSchemaParserCtxtPtr
9921: xmlSchemaParserCtxtCreate(void)
9922: {
9923: xmlSchemaParserCtxtPtr ret;
9924:
9925: ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9926: if (ret == NULL) {
9927: xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9928: NULL);
9929: return (NULL);
9930: }
9931: memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9932: ret->type = XML_SCHEMA_CTXT_PARSER;
9933: ret->attrProhibs = xmlSchemaItemListCreate();
9934: if (ret->attrProhibs == NULL) {
9935: xmlFree(ret);
9936: return(NULL);
9937: }
9938: return(ret);
9939: }
9940:
9941: /**
9942: * xmlSchemaNewParserCtxtUseDict:
9943: * @URL: the location of the schema
9944: * @dict: the dictionary to be used
9945: *
9946: * Create an XML Schemas parse context for that file/resource expected
9947: * to contain an XML Schemas file.
9948: *
9949: * Returns the parser context or NULL in case of error
9950: */
9951: static xmlSchemaParserCtxtPtr
9952: xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9953: {
9954: xmlSchemaParserCtxtPtr ret;
9955:
9956: ret = xmlSchemaParserCtxtCreate();
9957: if (ret == NULL)
9958: return (NULL);
9959: ret->dict = dict;
9960: xmlDictReference(dict);
9961: if (URL != NULL)
9962: ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9963: return (ret);
9964: }
9965:
9966: static int
9967: xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9968: {
9969: if (vctxt->pctxt == NULL) {
9970: if (vctxt->schema != NULL)
9971: vctxt->pctxt =
9972: xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9973: else
9974: vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9975: if (vctxt->pctxt == NULL) {
9976: VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9977: "failed to create a temp. parser context");
9978: return (-1);
9979: }
9980: /* TODO: Pass user data. */
9981: xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9982: vctxt->warning, vctxt->errCtxt);
9983: xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9984: vctxt->errCtxt);
9985: }
9986: return (0);
9987: }
9988:
9989: /**
9990: * xmlSchemaGetSchemaBucket:
9991: * @pctxt: the schema parser context
9992: * @schemaLocation: the URI of the schema document
9993: *
9994: * Returns a schema bucket if it was already parsed.
9995: *
9996: * Returns a schema bucket if it was already parsed from
9997: * @schemaLocation, NULL otherwise.
9998: */
9999: static xmlSchemaBucketPtr
10000: xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10001: const xmlChar *schemaLocation)
10002: {
10003: xmlSchemaBucketPtr cur;
10004: xmlSchemaItemListPtr list;
10005:
10006: list = pctxt->constructor->buckets;
10007: if (list->nbItems == 0)
10008: return(NULL);
10009: else {
10010: int i;
10011: for (i = 0; i < list->nbItems; i++) {
10012: cur = (xmlSchemaBucketPtr) list->items[i];
10013: /* Pointer comparison! */
10014: if (cur->schemaLocation == schemaLocation)
10015: return(cur);
10016: }
10017: }
10018: return(NULL);
10019: }
10020:
10021: static xmlSchemaBucketPtr
10022: xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10023: const xmlChar *schemaLocation,
10024: const xmlChar *targetNamespace)
10025: {
10026: xmlSchemaBucketPtr cur;
10027: xmlSchemaItemListPtr list;
10028:
10029: list = pctxt->constructor->buckets;
10030: if (list->nbItems == 0)
10031: return(NULL);
10032: else {
10033: int i;
10034: for (i = 0; i < list->nbItems; i++) {
10035: cur = (xmlSchemaBucketPtr) list->items[i];
10036: /* Pointer comparison! */
10037: if ((cur->origTargetNamespace == NULL) &&
10038: (cur->schemaLocation == schemaLocation) &&
10039: (cur->targetNamespace == targetNamespace))
10040: return(cur);
10041: }
10042: }
10043: return(NULL);
10044: }
10045:
10046:
10047: #define IS_BAD_SCHEMA_DOC(b) \
10048: (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10049:
10050: static xmlSchemaBucketPtr
10051: xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10052: const xmlChar *targetNamespace,
10053: int imported)
10054: {
10055: xmlSchemaBucketPtr cur;
10056: xmlSchemaItemListPtr list;
10057:
10058: list = pctxt->constructor->buckets;
10059: if (list->nbItems == 0)
10060: return(NULL);
10061: else {
10062: int i;
10063: for (i = 0; i < list->nbItems; i++) {
10064: cur = (xmlSchemaBucketPtr) list->items[i];
10065: if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10066: (cur->origTargetNamespace == targetNamespace) &&
10067: ((imported && cur->imported) ||
10068: ((!imported) && (!cur->imported))))
10069: return(cur);
10070: }
10071: }
10072: return(NULL);
10073: }
10074:
10075: static int
10076: xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10077: xmlSchemaPtr schema,
10078: xmlSchemaBucketPtr bucket)
10079: {
10080: int oldFlags;
10081: xmlDocPtr oldDoc;
10082: xmlNodePtr node;
10083: int ret, oldErrs;
10084: xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10085:
10086: /*
10087: * Save old values; reset the *main* schema.
10088: * URGENT TODO: This is not good; move the per-document information
10089: * to the parser. Get rid of passing the main schema to the
10090: * parsing functions.
10091: */
10092: oldFlags = schema->flags;
10093: oldDoc = schema->doc;
10094: if (schema->flags != 0)
10095: xmlSchemaClearSchemaDefaults(schema);
10096: schema->doc = bucket->doc;
10097: pctxt->schema = schema;
10098: /*
10099: * Keep the current target namespace on the parser *not* on the
10100: * main schema.
10101: */
10102: pctxt->targetNamespace = bucket->targetNamespace;
10103: WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10104:
10105: if ((bucket->targetNamespace != NULL) &&
10106: xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10107: /*
10108: * We are parsing the schema for schemas!
10109: */
10110: pctxt->isS4S = 1;
10111: }
10112: /* Mark it as parsed, even if parsing fails. */
10113: bucket->parsed++;
10114: /* Compile the schema doc. */
10115: node = xmlDocGetRootElement(bucket->doc);
10116: ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10117: if (ret != 0)
10118: goto exit;
10119: /* An empty schema; just get out. */
10120: if (node->children == NULL)
10121: goto exit;
10122: oldErrs = pctxt->nberrors;
10123: ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10124: if (ret != 0)
10125: goto exit;
10126: /*
10127: * TODO: Not nice, but I'm not 100% sure we will get always an error
10128: * as a result of the obove functions; so better rely on pctxt->err
10129: * as well.
10130: */
10131: if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10132: ret = pctxt->err;
10133: goto exit;
10134: }
10135:
10136: exit:
10137: WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10138: /* Restore schema values. */
10139: schema->doc = oldDoc;
10140: schema->flags = oldFlags;
10141: return(ret);
10142: }
10143:
10144: static int
10145: xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10146: xmlSchemaPtr schema,
10147: xmlSchemaBucketPtr bucket)
10148: {
10149: xmlSchemaParserCtxtPtr newpctxt;
10150: int res = 0;
10151:
10152: if (bucket == NULL)
10153: return(0);
10154: if (bucket->parsed) {
10155: PERROR_INT("xmlSchemaParseNewDoc",
10156: "reparsing a schema doc");
10157: return(-1);
10158: }
10159: if (bucket->doc == NULL) {
10160: PERROR_INT("xmlSchemaParseNewDoc",
10161: "parsing a schema doc, but there's no doc");
10162: return(-1);
10163: }
10164: if (pctxt->constructor == NULL) {
10165: PERROR_INT("xmlSchemaParseNewDoc",
10166: "no constructor");
10167: return(-1);
10168: }
10169: /* Create and init the temporary parser context. */
10170: newpctxt = xmlSchemaNewParserCtxtUseDict(
10171: (const char *) bucket->schemaLocation, pctxt->dict);
10172: if (newpctxt == NULL)
10173: return(-1);
10174: newpctxt->constructor = pctxt->constructor;
10175: /*
10176: * TODO: Can we avoid that the parser knows about the main schema?
10177: * It would be better if he knows about the current schema bucket
10178: * only.
10179: */
10180: newpctxt->schema = schema;
10181: xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10182: pctxt->errCtxt);
10183: xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10184: pctxt->errCtxt);
10185: newpctxt->counter = pctxt->counter;
10186:
10187:
10188: res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10189:
10190: /* Channel back errors and cleanup the temporary parser context. */
10191: if (res != 0)
10192: pctxt->err = res;
10193: pctxt->nberrors += newpctxt->nberrors;
10194: pctxt->counter = newpctxt->counter;
10195: newpctxt->constructor = NULL;
10196: /* Free the parser context. */
10197: xmlSchemaFreeParserCtxt(newpctxt);
10198: return(res);
10199: }
10200:
10201: static void
10202: xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10203: xmlSchemaSchemaRelationPtr rel)
10204: {
10205: xmlSchemaSchemaRelationPtr cur = bucket->relations;
10206:
10207: if (cur == NULL) {
10208: bucket->relations = rel;
10209: return;
10210: }
10211: while (cur->next != NULL)
10212: cur = cur->next;
10213: cur->next = rel;
10214: }
10215:
10216:
10217: static const xmlChar *
10218: xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10219: xmlNodePtr ctxtNode)
10220: {
10221: /*
10222: * Build an absolue location URI.
10223: */
10224: if (location != NULL) {
10225: if (ctxtNode == NULL)
10226: return(location);
10227: else {
10228: xmlChar *base, *URI;
10229: const xmlChar *ret = NULL;
10230:
10231: base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10232: if (base == NULL) {
10233: URI = xmlBuildURI(location, ctxtNode->doc->URL);
10234: } else {
10235: URI = xmlBuildURI(location, base);
10236: xmlFree(base);
10237: }
10238: if (URI != NULL) {
10239: ret = xmlDictLookup(dict, URI, -1);
10240: xmlFree(URI);
10241: return(ret);
10242: }
10243: }
10244: }
10245: return(NULL);
10246: }
10247:
10248:
10249:
10250: /**
10251: * xmlSchemaAddSchemaDoc:
10252: * @pctxt: a schema validation context
10253: * @schema: the schema being built
10254: * @node: a subtree containing XML Schema informations
10255: *
10256: * Parse an included (and to-be-redefined) XML schema document.
10257: *
10258: * Returns 0 on success, a positive error code on errors and
10259: * -1 in case of an internal or API error.
10260: */
10261:
10262: static int
10263: xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10264: int type, /* import or include or redefine */
10265: const xmlChar *schemaLocation,
10266: xmlDocPtr schemaDoc,
10267: const char *schemaBuffer,
10268: int schemaBufferLen,
10269: xmlNodePtr invokingNode,
10270: const xmlChar *sourceTargetNamespace,
10271: const xmlChar *importNamespace,
10272: xmlSchemaBucketPtr *bucket)
10273: {
10274: const xmlChar *targetNamespace = NULL;
10275: xmlSchemaSchemaRelationPtr relation = NULL;
10276: xmlDocPtr doc = NULL;
10277: int res = 0, err = 0, located = 0, preserveDoc = 0;
10278: xmlSchemaBucketPtr bkt = NULL;
10279:
10280: if (bucket != NULL)
10281: *bucket = NULL;
10282:
10283: switch (type) {
10284: case XML_SCHEMA_SCHEMA_IMPORT:
10285: case XML_SCHEMA_SCHEMA_MAIN:
10286: err = XML_SCHEMAP_SRC_IMPORT;
10287: break;
10288: case XML_SCHEMA_SCHEMA_INCLUDE:
10289: err = XML_SCHEMAP_SRC_INCLUDE;
10290: break;
10291: case XML_SCHEMA_SCHEMA_REDEFINE:
10292: err = XML_SCHEMAP_SRC_REDEFINE;
10293: break;
10294: }
10295:
10296:
10297: /* Special handling for the main schema:
10298: * skip the location and relation logic and just parse the doc.
10299: * We need just a bucket to be returned in this case.
10300: */
10301: if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10302: goto doc_load;
10303:
10304: /* Note that we expect the location to be an absulute URI. */
10305: if (schemaLocation != NULL) {
10306: bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10307: if ((bkt != NULL) &&
10308: (pctxt->constructor->bucket == bkt)) {
10309: /* Report self-imports/inclusions/redefinitions. */
10310:
10311: xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10312: invokingNode, NULL,
10313: "The schema must not import/include/redefine itself",
10314: NULL, NULL);
10315: goto exit;
10316: }
10317: }
10318: /*
10319: * Create a relation for the graph of schemas.
10320: */
10321: relation = xmlSchemaSchemaRelationCreate();
10322: if (relation == NULL)
10323: return(-1);
10324: xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10325: relation);
10326: relation->type = type;
10327:
10328: /*
10329: * Save the namespace import information.
10330: */
10331: if (WXS_IS_BUCKET_IMPMAIN(type)) {
10332: relation->importNamespace = importNamespace;
10333: if (schemaLocation == NULL) {
10334: /*
10335: * No location; this is just an import of the namespace.
10336: * Note that we don't assign a bucket to the relation
10337: * in this case.
10338: */
10339: goto exit;
10340: }
10341: targetNamespace = importNamespace;
10342: }
10343:
10344: /* Did we already fetch the doc? */
10345: if (bkt != NULL) {
10346: if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10347: /*
10348: * We included/redefined and then try to import a schema,
10349: * but the new location provided for import was different.
10350: */
10351: if (schemaLocation == NULL)
10352: schemaLocation = BAD_CAST "in_memory_buffer";
10353: if (!xmlStrEqual(schemaLocation,
10354: bkt->schemaLocation)) {
10355: xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10356: invokingNode, NULL,
10357: "The schema document '%s' cannot be imported, since "
10358: "it was already included or redefined",
10359: schemaLocation, NULL);
10360: goto exit;
10361: }
10362: } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10363: /*
10364: * We imported and then try to include/redefine a schema,
10365: * but the new location provided for the include/redefine
10366: * was different.
10367: */
10368: if (schemaLocation == NULL)
10369: schemaLocation = BAD_CAST "in_memory_buffer";
10370: if (!xmlStrEqual(schemaLocation,
10371: bkt->schemaLocation)) {
10372: xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10373: invokingNode, NULL,
10374: "The schema document '%s' cannot be included or "
10375: "redefined, since it was already imported",
10376: schemaLocation, NULL);
10377: goto exit;
10378: }
10379: }
10380: }
10381:
10382: if (WXS_IS_BUCKET_IMPMAIN(type)) {
10383: /*
10384: * Given that the schemaLocation [attribute] is only a hint, it is open
10385: * to applications to ignore all but the first <import> for a given
10386: * namespace, regardless of the �actual value� of schemaLocation, but
10387: * such a strategy risks missing useful information when new
10388: * schemaLocations are offered.
10389: *
10390: * We will use the first <import> that comes with a location.
10391: * Further <import>s *with* a location, will result in an error.
10392: * TODO: Better would be to just report a warning here, but
10393: * we'll try it this way until someone complains.
10394: *
10395: * Schema Document Location Strategy:
10396: * 3 Based on the namespace name, identify an existing schema document,
10397: * either as a resource which is an XML document or a <schema> element
10398: * information item, in some local schema repository;
10399: * 5 Attempt to resolve the namespace name to locate such a resource.
10400: *
10401: * NOTE: (3) and (5) are not supported.
10402: */
10403: if (bkt != NULL) {
10404: relation->bucket = bkt;
10405: goto exit;
10406: }
10407: bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10408: importNamespace, 1);
10409:
10410: if (bkt != NULL) {
10411: relation->bucket = bkt;
10412: if (bkt->schemaLocation == NULL) {
10413: /* First given location of the schema; load the doc. */
10414: bkt->schemaLocation = schemaLocation;
10415: } else {
10416: if (!xmlStrEqual(schemaLocation,
10417: bkt->schemaLocation)) {
10418: /*
10419: * Additional location given; just skip it.
10420: * URGENT TODO: We should report a warning here.
10421: * res = XML_SCHEMAP_SRC_IMPORT;
10422: */
10423: if (schemaLocation == NULL)
10424: schemaLocation = BAD_CAST "in_memory_buffer";
10425:
10426: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10427: XML_SCHEMAP_WARN_SKIP_SCHEMA,
10428: invokingNode, NULL,
10429: "Skipping import of schema located at '%s' for the "
10430: "namespace '%s', since this namespace was already "
10431: "imported with the schema located at '%s'",
10432: schemaLocation, importNamespace, bkt->schemaLocation);
10433: }
10434: goto exit;
10435: }
10436: }
10437: /*
10438: * No bucket + first location: load the doc and create a
10439: * bucket.
10440: */
10441: } else {
10442: /* <include> and <redefine> */
10443: if (bkt != NULL) {
10444:
10445: if ((bkt->origTargetNamespace == NULL) &&
10446: (bkt->targetNamespace != sourceTargetNamespace)) {
10447: xmlSchemaBucketPtr chamel;
10448:
10449: /*
10450: * Chameleon include/redefine: skip loading only if it was
10451: * aleady build for the targetNamespace of the including
10452: * schema.
10453: */
10454: /*
10455: * URGENT TODO: If the schema is a chameleon-include then copy
10456: * the components into the including schema and modify the
10457: * targetNamespace of those components, do nothing otherwise.
10458: * NOTE: This is currently worked-around by compiling the
10459: * chameleon for every destinct including targetNamespace; thus
10460: * not performant at the moment.
10461: * TODO: Check when the namespace in wildcards for chameleons
10462: * needs to be converted: before we built wildcard intersections
10463: * or after.
10464: * Answer: after!
10465: */
10466: chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10467: schemaLocation, sourceTargetNamespace);
10468: if (chamel != NULL) {
10469: /* A fitting chameleon was already parsed; NOP. */
10470: relation->bucket = chamel;
10471: goto exit;
10472: }
10473: /*
10474: * We need to parse the chameleon again for a different
10475: * targetNamespace.
10476: * CHAMELEON TODO: Optimize this by only parsing the
10477: * chameleon once, and then copying the components to
10478: * the new targetNamespace.
10479: */
10480: bkt = NULL;
10481: } else {
10482: relation->bucket = bkt;
10483: goto exit;
10484: }
10485: }
10486: }
10487: if ((bkt != NULL) && (bkt->doc != NULL)) {
10488: PERROR_INT("xmlSchemaAddSchemaDoc",
10489: "trying to load a schema doc, but a doc is already "
10490: "assigned to the schema bucket");
10491: goto exit_failure;
10492: }
10493:
10494: doc_load:
10495: /*
10496: * Load the document.
10497: */
10498: if (schemaDoc != NULL) {
10499: doc = schemaDoc;
10500: /* Don' free this one, since it was provided by the caller. */
10501: preserveDoc = 1;
10502: /* TODO: Does the context or the doc hold the location? */
10503: if (schemaDoc->URL != NULL)
10504: schemaLocation = xmlDictLookup(pctxt->dict,
10505: schemaDoc->URL, -1);
10506: else
10507: schemaLocation = BAD_CAST "in_memory_buffer";
10508: } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10509: xmlParserCtxtPtr parserCtxt;
10510:
10511: parserCtxt = xmlNewParserCtxt();
10512: if (parserCtxt == NULL) {
10513: xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10514: "allocating a parser context", NULL);
10515: goto exit_failure;
10516: }
10517: if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10518: /*
10519: * TODO: Do we have to burden the schema parser dict with all
10520: * the content of the schema doc?
10521: */
10522: xmlDictFree(parserCtxt->dict);
10523: parserCtxt->dict = pctxt->dict;
10524: xmlDictReference(parserCtxt->dict);
10525: }
10526: if (schemaLocation != NULL) {
10527: /* Parse from file. */
10528: doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10529: NULL, SCHEMAS_PARSE_OPTIONS);
10530: } else if (schemaBuffer != NULL) {
10531: /* Parse from memory buffer. */
10532: doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10533: NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10534: schemaLocation = BAD_CAST "in_memory_buffer";
10535: if (doc != NULL)
10536: doc->URL = xmlStrdup(schemaLocation);
10537: }
10538: /*
10539: * For <import>:
10540: * 2.1 The referent is (a fragment of) a resource which is an
10541: * XML document (see clause 1.1), which in turn corresponds to
10542: * a <schema> element information item in a well-formed information
10543: * set, which in turn corresponds to a valid schema.
10544: * TODO: (2.1) fragments of XML documents are not supported.
10545: *
10546: * 2.2 The referent is a <schema> element information item in
10547: * a well-formed information set, which in turn corresponds
10548: * to a valid schema.
10549: * TODO: (2.2) is not supported.
10550: */
10551: if (doc == NULL) {
10552: xmlErrorPtr lerr;
10553: lerr = xmlGetLastError();
10554: /*
10555: * Check if this a parser error, or if the document could
10556: * just not be located.
10557: * TODO: Try to find specific error codes to react only on
10558: * localisation failures.
10559: */
10560: if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10561: /*
10562: * We assume a parser error here.
10563: */
10564: located = 1;
10565: /* TODO: Error code ?? */
10566: res = XML_SCHEMAP_SRC_IMPORT_2_1;
10567: xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10568: invokingNode, NULL,
10569: "Failed to parse the XML resource '%s'",
10570: schemaLocation, NULL);
10571: }
10572: }
10573: xmlFreeParserCtxt(parserCtxt);
10574: if ((doc == NULL) && located)
10575: goto exit_error;
10576: } else {
10577: xmlSchemaPErr(pctxt, NULL,
10578: XML_SCHEMAP_NOTHING_TO_PARSE,
10579: "No information for parsing was provided with the "
10580: "given schema parser context.\n",
10581: NULL, NULL);
10582: goto exit_failure;
10583: }
10584: /*
10585: * Preprocess the document.
10586: */
10587: if (doc != NULL) {
10588: xmlNodePtr docElem = NULL;
10589:
10590: located = 1;
10591: docElem = xmlDocGetRootElement(doc);
10592: if (docElem == NULL) {
10593: xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10594: invokingNode, NULL,
10595: "The document '%s' has no document element",
10596: schemaLocation, NULL);
10597: goto exit_error;
10598: }
10599: /*
10600: * Remove all the blank text nodes.
10601: */
10602: xmlSchemaCleanupDoc(pctxt, docElem);
10603: /*
10604: * Check the schema's top level element.
10605: */
10606: if (!IS_SCHEMA(docElem, "schema")) {
10607: xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10608: invokingNode, NULL,
10609: "The XML document '%s' is not a schema document",
10610: schemaLocation, NULL);
10611: goto exit_error;
10612: }
10613: /*
10614: * Note that we don't apply a type check for the
10615: * targetNamespace value here.
10616: */
10617: targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10618: "targetNamespace");
10619: }
10620:
10621: /* after_doc_loading: */
10622: if ((bkt == NULL) && located) {
10623: /* Only create a bucket if the schema was located. */
10624: bkt = xmlSchemaBucketCreate(pctxt, type,
10625: targetNamespace);
10626: if (bkt == NULL)
10627: goto exit_failure;
10628: }
10629: if (bkt != NULL) {
10630: bkt->schemaLocation = schemaLocation;
10631: bkt->located = located;
10632: if (doc != NULL) {
10633: bkt->doc = doc;
10634: bkt->targetNamespace = targetNamespace;
10635: bkt->origTargetNamespace = targetNamespace;
10636: if (preserveDoc)
10637: bkt->preserveDoc = 1;
10638: }
10639: if (WXS_IS_BUCKET_IMPMAIN(type))
10640: bkt->imported++;
10641: /*
10642: * Add it to the graph of schemas.
10643: */
10644: if (relation != NULL)
10645: relation->bucket = bkt;
10646: }
10647:
10648: exit:
10649: /*
10650: * Return the bucket explicitely; this is needed for the
10651: * main schema.
10652: */
10653: if (bucket != NULL)
10654: *bucket = bkt;
10655: return (0);
10656:
10657: exit_error:
10658: if ((doc != NULL) && (! preserveDoc)) {
10659: xmlFreeDoc(doc);
10660: if (bkt != NULL)
10661: bkt->doc = NULL;
10662: }
10663: return(pctxt->err);
10664:
10665: exit_failure:
10666: if ((doc != NULL) && (! preserveDoc)) {
10667: xmlFreeDoc(doc);
10668: if (bkt != NULL)
10669: bkt->doc = NULL;
10670: }
10671: return (-1);
10672: }
10673:
10674: /**
10675: * xmlSchemaParseImport:
10676: * @ctxt: a schema validation context
10677: * @schema: the schema being built
10678: * @node: a subtree containing XML Schema informations
10679: *
10680: * parse a XML schema Import definition
10681: * *WARNING* this interface is highly subject to change
10682: *
10683: * Returns 0 in case of success, a positive error code if
10684: * not valid and -1 in case of an internal error.
10685: */
10686: static int
10687: xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10688: xmlNodePtr node)
10689: {
10690: xmlNodePtr child;
10691: const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10692: const xmlChar *thisTargetNamespace;
10693: xmlAttrPtr attr;
10694: int ret = 0;
10695: xmlSchemaBucketPtr bucket = NULL;
10696:
10697: if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10698: return (-1);
10699:
10700: /*
10701: * Check for illegal attributes.
10702: */
10703: attr = node->properties;
10704: while (attr != NULL) {
10705: if (attr->ns == NULL) {
10706: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10707: (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10708: (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10709: xmlSchemaPIllegalAttrErr(pctxt,
10710: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10711: }
10712: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10713: xmlSchemaPIllegalAttrErr(pctxt,
10714: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10715: }
10716: attr = attr->next;
10717: }
10718: /*
10719: * Extract and validate attributes.
10720: */
10721: if (xmlSchemaPValAttr(pctxt, NULL, node,
10722: "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10723: &namespaceName) != 0) {
10724: xmlSchemaPSimpleTypeErr(pctxt,
10725: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10726: NULL, node,
10727: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10728: NULL, namespaceName, NULL, NULL, NULL);
10729: return (pctxt->err);
10730: }
10731:
10732: if (xmlSchemaPValAttr(pctxt, NULL, node,
10733: "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10734: &schemaLocation) != 0) {
10735: xmlSchemaPSimpleTypeErr(pctxt,
10736: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10737: NULL, node,
10738: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10739: NULL, namespaceName, NULL, NULL, NULL);
10740: return (pctxt->err);
10741: }
10742: /*
10743: * And now for the children...
10744: */
10745: child = node->children;
10746: if (IS_SCHEMA(child, "annotation")) {
10747: /*
10748: * the annotation here is simply discarded ...
10749: * TODO: really?
10750: */
10751: child = child->next;
10752: }
10753: if (child != NULL) {
10754: xmlSchemaPContentErr(pctxt,
10755: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10756: NULL, node, child, NULL,
10757: "(annotation?)");
10758: }
10759: /*
10760: * Apply additional constraints.
10761: *
10762: * Note that it is important to use the original @targetNamespace
10763: * (or none at all), to rule out imports of schemas _with_ a
10764: * @targetNamespace if the importing schema is a chameleon schema
10765: * (with no @targetNamespace).
10766: */
10767: thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10768: if (namespaceName != NULL) {
10769: /*
10770: * 1.1 If the namespace [attribute] is present, then its �actual value�
10771: * must not match the �actual value� of the enclosing <schema>'s
10772: * targetNamespace [attribute].
10773: */
10774: if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10775: xmlSchemaPCustomErr(pctxt,
10776: XML_SCHEMAP_SRC_IMPORT_1_1,
10777: NULL, node,
10778: "The value of the attribute 'namespace' must not match "
10779: "the target namespace '%s' of the importing schema",
10780: thisTargetNamespace);
10781: return (pctxt->err);
10782: }
10783: } else {
10784: /*
10785: * 1.2 If the namespace [attribute] is not present, then the enclosing
10786: * <schema> must have a targetNamespace [attribute].
10787: */
10788: if (thisTargetNamespace == NULL) {
10789: xmlSchemaPCustomErr(pctxt,
10790: XML_SCHEMAP_SRC_IMPORT_1_2,
10791: NULL, node,
10792: "The attribute 'namespace' must be existent if "
10793: "the importing schema has no target namespace",
10794: NULL);
10795: return (pctxt->err);
10796: }
10797: }
10798: /*
10799: * Locate and acquire the schema document.
10800: */
10801: if (schemaLocation != NULL)
10802: schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10803: schemaLocation, node);
10804: ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10805: schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10806: namespaceName, &bucket);
10807:
10808: if (ret != 0)
10809: return(ret);
10810:
10811: /*
10812: * For <import>: "It is *not* an error for the application
10813: * schema reference strategy to fail."
10814: * So just don't parse if no schema document was found.
10815: * Note that we will get no bucket if the schema could not be
10816: * located or if there was no schemaLocation.
10817: */
10818: if ((bucket == NULL) && (schemaLocation != NULL)) {
10819: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10820: XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10821: node, NULL,
10822: "Failed to locate a schema at location '%s'. "
10823: "Skipping the import", schemaLocation, NULL, NULL);
10824: }
10825:
10826: if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10827: ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10828: }
10829:
10830: return (ret);
10831: }
10832:
10833: static int
10834: xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10835: xmlSchemaPtr schema,
10836: xmlNodePtr node,
10837: xmlChar **schemaLocation,
10838: int type)
10839: {
10840: xmlAttrPtr attr;
10841:
10842: if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10843: (schemaLocation == NULL))
10844: return (-1);
10845:
10846: *schemaLocation = NULL;
10847: /*
10848: * Check for illegal attributes.
10849: * Applies for both <include> and <redefine>.
10850: */
10851: attr = node->properties;
10852: while (attr != NULL) {
10853: if (attr->ns == NULL) {
10854: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10855: (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10856: xmlSchemaPIllegalAttrErr(pctxt,
10857: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10858: }
10859: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10860: xmlSchemaPIllegalAttrErr(pctxt,
10861: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10862: }
10863: attr = attr->next;
10864: }
10865: xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10866: /*
10867: * Preliminary step, extract the URI-Reference and make an URI
10868: * from the base.
10869: */
10870: /*
10871: * Attribute "schemaLocation" is mandatory.
10872: */
10873: attr = xmlSchemaGetPropNode(node, "schemaLocation");
10874: if (attr != NULL) {
10875: xmlChar *base = NULL;
10876: xmlChar *uri = NULL;
10877:
10878: if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10879: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10880: (const xmlChar **) schemaLocation) != 0)
10881: goto exit_error;
10882: base = xmlNodeGetBase(node->doc, node);
10883: if (base == NULL) {
10884: uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10885: } else {
10886: uri = xmlBuildURI(*schemaLocation, base);
10887: xmlFree(base);
10888: }
10889: if (uri == NULL) {
10890: PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10891: "could not build an URI from the schemaLocation")
10892: goto exit_failure;
10893: }
10894: (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10895: xmlFree(uri);
10896: } else {
10897: xmlSchemaPMissingAttrErr(pctxt,
10898: XML_SCHEMAP_S4S_ATTR_MISSING,
10899: NULL, node, "schemaLocation", NULL);
10900: goto exit_error;
10901: }
10902: /*
10903: * Report self-inclusion and self-redefinition.
10904: */
10905: if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10906: if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10907: xmlSchemaPCustomErr(pctxt,
10908: XML_SCHEMAP_SRC_REDEFINE,
10909: NULL, node,
10910: "The schema document '%s' cannot redefine itself.",
10911: *schemaLocation);
10912: } else {
10913: xmlSchemaPCustomErr(pctxt,
10914: XML_SCHEMAP_SRC_INCLUDE,
10915: NULL, node,
10916: "The schema document '%s' cannot include itself.",
10917: *schemaLocation);
10918: }
10919: goto exit_error;
10920: }
10921:
10922: return(0);
10923: exit_error:
10924: return(pctxt->err);
10925: exit_failure:
10926: return(-1);
10927: }
10928:
10929: static int
10930: xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10931: xmlSchemaPtr schema,
10932: xmlNodePtr node,
10933: int type)
10934: {
10935: xmlNodePtr child = NULL;
10936: const xmlChar *schemaLocation = NULL;
10937: int res = 0; /* hasRedefinitions = 0 */
10938: int isChameleon = 0, wasChameleon = 0;
10939: xmlSchemaBucketPtr bucket = NULL;
10940:
10941: if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10942: return (-1);
10943:
10944: /*
10945: * Parse attributes. Note that the returned schemaLocation will
10946: * be already converted to an absolute URI.
10947: */
10948: res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10949: node, (xmlChar **) (&schemaLocation), type);
10950: if (res != 0)
10951: return(res);
10952: /*
10953: * Load and add the schema document.
10954: */
10955: res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10956: NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10957: if (res != 0)
10958: return(res);
10959: /*
10960: * If we get no schema bucket back, then this means that the schema
10961: * document could not be located or was broken XML or was not
10962: * a schema document.
10963: */
10964: if ((bucket == NULL) || (bucket->doc == NULL)) {
10965: if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10966: /*
10967: * WARNING for <include>:
10968: * We will raise an error if the schema cannot be located
10969: * for inclusions, since the that was the feedback from the
10970: * schema people. I.e. the following spec piece will *not* be
10971: * satisfied:
10972: * SPEC src-include: "It is not an error for the �actual value� of the
10973: * schemaLocation [attribute] to fail to resolve it all, in which
10974: * case no corresponding inclusion is performed.
10975: * So do we need a warning report here?"
10976: */
10977: res = XML_SCHEMAP_SRC_INCLUDE;
10978: xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10979: node, NULL,
10980: "Failed to load the document '%s' for inclusion",
10981: schemaLocation, NULL);
10982: } else {
10983: /*
10984: * NOTE: This was changed to raise an error even if no redefinitions
10985: * are specified.
10986: *
10987: * SPEC src-redefine (1)
10988: * "If there are any element information items among the [children]
10989: * other than <annotation> then the �actual value� of the
10990: * schemaLocation [attribute] must successfully resolve."
10991: * TODO: Ask the WG if a the location has always to resolve
10992: * here as well!
10993: */
10994: res = XML_SCHEMAP_SRC_REDEFINE;
10995: xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10996: node, NULL,
10997: "Failed to load the document '%s' for redefinition",
10998: schemaLocation, NULL);
10999: }
11000: } else {
11001: /*
11002: * Check targetNamespace sanity before parsing the new schema.
11003: * TODO: Note that we won't check further content if the
11004: * targetNamespace was bad.
11005: */
11006: if (bucket->origTargetNamespace != NULL) {
11007: /*
11008: * SPEC src-include (2.1)
11009: * "SII has a targetNamespace [attribute], and its �actual
11010: * value� is identical to the �actual value� of the targetNamespace
11011: * [attribute] of SII� (which must have such an [attribute])."
11012: */
11013: if (pctxt->targetNamespace == NULL) {
11014: xmlSchemaCustomErr(ACTXT_CAST pctxt,
11015: XML_SCHEMAP_SRC_INCLUDE,
11016: node, NULL,
11017: "The target namespace of the included/redefined schema "
11018: "'%s' has to be absent, since the including/redefining "
11019: "schema has no target namespace",
11020: schemaLocation, NULL);
11021: goto exit_error;
11022: } else if (!xmlStrEqual(bucket->origTargetNamespace,
11023: pctxt->targetNamespace)) {
11024: /* TODO: Change error function. */
11025: xmlSchemaPCustomErrExt(pctxt,
11026: XML_SCHEMAP_SRC_INCLUDE,
11027: NULL, node,
11028: "The target namespace '%s' of the included/redefined "
11029: "schema '%s' differs from '%s' of the "
11030: "including/redefining schema",
11031: bucket->origTargetNamespace, schemaLocation,
11032: pctxt->targetNamespace);
11033: goto exit_error;
11034: }
11035: } else if (pctxt->targetNamespace != NULL) {
11036: /*
11037: * Chameleons: the original target namespace will
11038: * differ from the resulting namespace.
11039: */
11040: isChameleon = 1;
11041: if (bucket->parsed &&
11042: bucket->origTargetNamespace != NULL) {
11043: xmlSchemaCustomErr(ACTXT_CAST pctxt,
11044: XML_SCHEMAP_SRC_INCLUDE,
11045: node, NULL,
11046: "The target namespace of the included/redefined schema "
11047: "'%s' has to be absent or the same as the "
11048: "including/redefining schema's target namespace",
11049: schemaLocation, NULL);
11050: goto exit_error;
11051: }
11052: bucket->targetNamespace = pctxt->targetNamespace;
11053: }
11054: }
11055: /*
11056: * Parse the schema.
11057: */
11058: if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11059: if (isChameleon) {
11060: /* TODO: Get rid of this flag on the schema itself. */
11061: if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11062: schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11063: } else
11064: wasChameleon = 1;
11065: }
11066: xmlSchemaParseNewDoc(pctxt, schema, bucket);
11067: /* Restore chameleon flag. */
11068: if (isChameleon && (!wasChameleon))
11069: schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11070: }
11071: /*
11072: * And now for the children...
11073: */
11074: child = node->children;
11075: if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11076: /*
11077: * Parse (simpleType | complexType | group | attributeGroup))*
11078: */
11079: pctxt->redefined = bucket;
11080: /*
11081: * How to proceed if the redefined schema was not located?
11082: */
11083: pctxt->isRedefine = 1;
11084: while (IS_SCHEMA(child, "annotation") ||
11085: IS_SCHEMA(child, "simpleType") ||
11086: IS_SCHEMA(child, "complexType") ||
11087: IS_SCHEMA(child, "group") ||
11088: IS_SCHEMA(child, "attributeGroup")) {
11089: if (IS_SCHEMA(child, "annotation")) {
11090: /*
11091: * TODO: discard or not?
11092: */
11093: } else if (IS_SCHEMA(child, "simpleType")) {
11094: xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11095: } else if (IS_SCHEMA(child, "complexType")) {
11096: xmlSchemaParseComplexType(pctxt, schema, child, 1);
11097: /* hasRedefinitions = 1; */
11098: } else if (IS_SCHEMA(child, "group")) {
11099: /* hasRedefinitions = 1; */
11100: xmlSchemaParseModelGroupDefinition(pctxt,
11101: schema, child);
11102: } else if (IS_SCHEMA(child, "attributeGroup")) {
11103: /* hasRedefinitions = 1; */
11104: xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11105: child);
11106: }
11107: child = child->next;
11108: }
11109: pctxt->redefined = NULL;
11110: pctxt->isRedefine = 0;
11111: } else {
11112: if (IS_SCHEMA(child, "annotation")) {
11113: /*
11114: * TODO: discard or not?
11115: */
11116: child = child->next;
11117: }
11118: }
11119: if (child != NULL) {
11120: res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11121: if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11122: xmlSchemaPContentErr(pctxt, res,
11123: NULL, node, child, NULL,
11124: "(annotation | (simpleType | complexType | group | attributeGroup))*");
11125: } else {
11126: xmlSchemaPContentErr(pctxt, res,
11127: NULL, node, child, NULL,
11128: "(annotation?)");
11129: }
11130: }
11131: return(res);
11132:
11133: exit_error:
11134: return(pctxt->err);
11135: }
11136:
11137: static int
11138: xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11139: xmlNodePtr node)
11140: {
11141: int res;
11142: #ifndef ENABLE_REDEFINE
11143: TODO
11144: return(0);
11145: #endif
11146: res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11147: XML_SCHEMA_SCHEMA_REDEFINE);
11148: if (res != 0)
11149: return(res);
11150: return(0);
11151: }
11152:
11153: static int
11154: xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11155: xmlNodePtr node)
11156: {
11157: int res;
11158:
11159: res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11160: XML_SCHEMA_SCHEMA_INCLUDE);
11161: if (res != 0)
11162: return(res);
11163: return(0);
11164: }
11165:
11166: /**
11167: * xmlSchemaParseModelGroup:
11168: * @ctxt: a schema validation context
11169: * @schema: the schema being built
11170: * @node: a subtree containing XML Schema informations
11171: * @type: the "compositor" type
11172: * @particleNeeded: if a a model group with a particle
11173: *
11174: * parse a XML schema Sequence definition.
11175: * Applies parts of:
11176: * Schema Representation Constraint:
11177: * Redefinition Constraints and Semantics (src-redefine)
11178: * (6.1), (6.1.1), (6.1.2)
11179: *
11180: * Schema Component Constraint:
11181: * All Group Limited (cos-all-limited) (2)
11182: * TODO: Actually this should go to component-level checks,
11183: * but is done here due to performance. Move it to an other layer
11184: * is schema construction via an API is implemented.
11185: *
11186: * *WARNING* this interface is highly subject to change
11187: *
11188: * Returns -1 in case of error, 0 if the declaration is improper and
11189: * 1 in case of success.
11190: */
11191: static xmlSchemaTreeItemPtr
11192: xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11193: xmlNodePtr node, xmlSchemaTypeType type,
11194: int withParticle)
11195: {
11196: xmlSchemaModelGroupPtr item;
11197: xmlSchemaParticlePtr particle = NULL;
11198: xmlNodePtr child = NULL;
11199: xmlAttrPtr attr;
11200: int min = 1, max = 1, isElemRef, hasRefs = 0;
11201:
11202: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11203: return (NULL);
11204: /*
11205: * Create a model group with the given compositor.
11206: */
11207: item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11208: if (item == NULL)
11209: return (NULL);
11210:
11211: if (withParticle) {
11212: if (type == XML_SCHEMA_TYPE_ALL) {
11213: min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11214: max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11215: } else {
11216: /* choice + sequence */
11217: min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11218: max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11219: "(xs:nonNegativeInteger | unbounded)");
11220: }
11221: xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11222: /*
11223: * Create a particle
11224: */
11225: particle = xmlSchemaAddParticle(ctxt, node, min, max);
11226: if (particle == NULL)
11227: return (NULL);
11228: particle->children = (xmlSchemaTreeItemPtr) item;
11229: /*
11230: * Check for illegal attributes.
11231: */
11232: attr = node->properties;
11233: while (attr != NULL) {
11234: if (attr->ns == NULL) {
11235: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11236: (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11237: (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11238: xmlSchemaPIllegalAttrErr(ctxt,
11239: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11240: }
11241: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11242: xmlSchemaPIllegalAttrErr(ctxt,
11243: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11244: }
11245: attr = attr->next;
11246: }
11247: } else {
11248: /*
11249: * Check for illegal attributes.
11250: */
11251: attr = node->properties;
11252: while (attr != NULL) {
11253: if (attr->ns == NULL) {
11254: if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11255: xmlSchemaPIllegalAttrErr(ctxt,
11256: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11257: }
11258: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11259: xmlSchemaPIllegalAttrErr(ctxt,
11260: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11261: }
11262: attr = attr->next;
11263: }
11264: }
11265:
11266: /*
11267: * Extract and validate attributes.
11268: */
11269: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11270: /*
11271: * And now for the children...
11272: */
11273: child = node->children;
11274: if (IS_SCHEMA(child, "annotation")) {
11275: item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11276: child = child->next;
11277: }
11278: if (type == XML_SCHEMA_TYPE_ALL) {
11279: xmlSchemaParticlePtr part, last = NULL;
11280:
11281: while (IS_SCHEMA(child, "element")) {
11282: part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11283: schema, child, &isElemRef, 0);
11284: /*
11285: * SPEC cos-all-limited (2)
11286: * "The {max occurs} of all the particles in the {particles}
11287: * of the ('all') group must be 0 or 1.
11288: */
11289: if (part != NULL) {
11290: if (isElemRef)
11291: hasRefs++;
11292: if (part->minOccurs > 1) {
11293: xmlSchemaPCustomErr(ctxt,
11294: XML_SCHEMAP_COS_ALL_LIMITED,
11295: NULL, child,
11296: "Invalid value for minOccurs (must be 0 or 1)",
11297: NULL);
11298: /* Reset to 1. */
11299: part->minOccurs = 1;
11300: }
11301: if (part->maxOccurs > 1) {
11302: xmlSchemaPCustomErr(ctxt,
11303: XML_SCHEMAP_COS_ALL_LIMITED,
11304: NULL, child,
11305: "Invalid value for maxOccurs (must be 0 or 1)",
11306: NULL);
11307: /* Reset to 1. */
11308: part->maxOccurs = 1;
11309: }
11310: if (last == NULL)
11311: item->children = (xmlSchemaTreeItemPtr) part;
11312: else
11313: last->next = (xmlSchemaTreeItemPtr) part;
11314: last = part;
11315: }
11316: child = child->next;
11317: }
11318: if (child != NULL) {
11319: xmlSchemaPContentErr(ctxt,
11320: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11321: NULL, node, child, NULL,
11322: "(annotation?, (annotation?, element*)");
11323: }
11324: } else {
11325: /* choice + sequence */
11326: xmlSchemaTreeItemPtr part = NULL, last = NULL;
11327:
11328: while ((IS_SCHEMA(child, "element")) ||
11329: (IS_SCHEMA(child, "group")) ||
11330: (IS_SCHEMA(child, "any")) ||
11331: (IS_SCHEMA(child, "choice")) ||
11332: (IS_SCHEMA(child, "sequence"))) {
11333:
11334: if (IS_SCHEMA(child, "element")) {
11335: part = (xmlSchemaTreeItemPtr)
11336: xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11337: if (part && isElemRef)
11338: hasRefs++;
11339: } else if (IS_SCHEMA(child, "group")) {
11340: part =
11341: xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11342: if (part != NULL)
11343: hasRefs++;
11344: /*
11345: * Handle redefinitions.
11346: */
11347: if (ctxt->isRedefine && ctxt->redef &&
11348: (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11349: part && part->children)
11350: {
11351: if ((xmlSchemaGetQNameRefName(part->children) ==
11352: ctxt->redef->refName) &&
11353: (xmlSchemaGetQNameRefTargetNs(part->children) ==
11354: ctxt->redef->refTargetNs))
11355: {
11356: /*
11357: * SPEC src-redefine:
11358: * (6.1) "If it has a <group> among its contents at
11359: * some level the �actual value� of whose ref
11360: * [attribute] is the same as the �actual value� of
11361: * its own name attribute plus target namespace, then
11362: * all of the following must be true:"
11363: * (6.1.1) "It must have exactly one such group."
11364: */
11365: if (ctxt->redefCounter != 0) {
11366: xmlChar *str = NULL;
11367:
11368: xmlSchemaCustomErr(ACTXT_CAST ctxt,
11369: XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11370: "The redefining model group definition "
11371: "'%s' must not contain more than one "
11372: "reference to the redefined definition",
11373: xmlSchemaFormatQName(&str,
11374: ctxt->redef->refTargetNs,
11375: ctxt->redef->refName),
11376: NULL);
11377: FREE_AND_NULL(str)
11378: part = NULL;
11379: } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11380: ((WXS_PARTICLE(part))->maxOccurs != 1))
11381: {
11382: xmlChar *str = NULL;
11383: /*
11384: * SPEC src-redefine:
11385: * (6.1.2) "The �actual value� of both that
11386: * group's minOccurs and maxOccurs [attribute]
11387: * must be 1 (or �absent�).
11388: */
11389: xmlSchemaCustomErr(ACTXT_CAST ctxt,
11390: XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11391: "The redefining model group definition "
11392: "'%s' must not contain a reference to the "
11393: "redefined definition with a "
11394: "maxOccurs/minOccurs other than 1",
11395: xmlSchemaFormatQName(&str,
11396: ctxt->redef->refTargetNs,
11397: ctxt->redef->refName),
11398: NULL);
11399: FREE_AND_NULL(str)
11400: part = NULL;
11401: }
11402: ctxt->redef->reference = WXS_BASIC_CAST part;
11403: ctxt->redefCounter++;
11404: }
11405: }
11406: } else if (IS_SCHEMA(child, "any")) {
11407: part = (xmlSchemaTreeItemPtr)
11408: xmlSchemaParseAny(ctxt, schema, child);
11409: } else if (IS_SCHEMA(child, "choice")) {
11410: part = xmlSchemaParseModelGroup(ctxt, schema, child,
11411: XML_SCHEMA_TYPE_CHOICE, 1);
11412: } else if (IS_SCHEMA(child, "sequence")) {
11413: part = xmlSchemaParseModelGroup(ctxt, schema, child,
11414: XML_SCHEMA_TYPE_SEQUENCE, 1);
11415: }
11416: if (part != NULL) {
11417: if (last == NULL)
11418: item->children = part;
11419: else
11420: last->next = part;
11421: last = part;
11422: }
11423: child = child->next;
11424: }
11425: if (child != NULL) {
11426: xmlSchemaPContentErr(ctxt,
11427: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11428: NULL, node, child, NULL,
11429: "(annotation?, (element | group | choice | sequence | any)*)");
11430: }
11431: }
11432: if ((max == 0) && (min == 0))
11433: return (NULL);
11434: if (hasRefs) {
11435: /*
11436: * We need to resolve references.
11437: */
11438: WXS_ADD_PENDING(ctxt, item);
11439: }
11440: if (withParticle)
11441: return ((xmlSchemaTreeItemPtr) particle);
11442: else
11443: return ((xmlSchemaTreeItemPtr) item);
11444: }
11445:
11446: /**
11447: * xmlSchemaParseRestriction:
11448: * @ctxt: a schema validation context
11449: * @schema: the schema being built
11450: * @node: a subtree containing XML Schema informations
11451: *
11452: * parse a XML schema Restriction definition
11453: * *WARNING* this interface is highly subject to change
11454: *
11455: * Returns the type definition or NULL in case of error
11456: */
11457: static xmlSchemaTypePtr
11458: xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11459: xmlNodePtr node, xmlSchemaTypeType parentType)
11460: {
11461: xmlSchemaTypePtr type;
11462: xmlNodePtr child = NULL;
11463: xmlAttrPtr attr;
11464:
11465: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11466: return (NULL);
11467: /* Not a component, don't create it. */
11468: type = ctxt->ctxtType;
11469: type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11470:
11471: /*
11472: * Check for illegal attributes.
11473: */
11474: attr = node->properties;
11475: while (attr != NULL) {
11476: if (attr->ns == NULL) {
11477: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11478: (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11479: xmlSchemaPIllegalAttrErr(ctxt,
11480: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11481: }
11482: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11483: xmlSchemaPIllegalAttrErr(ctxt,
11484: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11485: }
11486: attr = attr->next;
11487: }
11488: /*
11489: * Extract and validate attributes.
11490: */
11491: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11492: /*
11493: * Attribute
11494: */
11495: /*
11496: * Extract the base type. The "base" attribute is mandatory if inside
11497: * a complex type or if redefining.
11498: *
11499: * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11500: * among its [children]), the simple type definition which is
11501: * the {content type} of the type definition �resolved� to by
11502: * the �actual value� of the base [attribute]"
11503: */
11504: if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11505: &(type->baseNs), &(type->base)) == 0)
11506: {
11507: if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11508: xmlSchemaPMissingAttrErr(ctxt,
11509: XML_SCHEMAP_S4S_ATTR_MISSING,
11510: NULL, node, "base", NULL);
11511: } else if ((ctxt->isRedefine) &&
11512: (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11513: {
11514: if (type->base == NULL) {
11515: xmlSchemaPMissingAttrErr(ctxt,
11516: XML_SCHEMAP_S4S_ATTR_MISSING,
11517: NULL, node, "base", NULL);
11518: } else if ((! xmlStrEqual(type->base, type->name)) ||
11519: (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11520: {
11521: xmlChar *str1 = NULL, *str2 = NULL;
11522: /*
11523: * REDEFINE: SPEC src-redefine (5)
11524: * "Within the [children], each <simpleType> must have a
11525: * <restriction> among its [children] ... the �actual value� of
11526: * whose base [attribute] must be the same as the �actual value�
11527: * of its own name attribute plus target namespace;"
11528: */
11529: xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11530: NULL, node, "This is a redefinition, but the QName "
11531: "value '%s' of the 'base' attribute does not match the "
11532: "type's designation '%s'",
11533: xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11534: xmlSchemaFormatQName(&str2, type->targetNamespace,
11535: type->name), NULL);
11536: FREE_AND_NULL(str1);
11537: FREE_AND_NULL(str2);
11538: /* Avoid confusion and erase the values. */
11539: type->base = NULL;
11540: type->baseNs = NULL;
11541: }
11542: }
11543: }
11544: /*
11545: * And now for the children...
11546: */
11547: child = node->children;
11548: if (IS_SCHEMA(child, "annotation")) {
11549: /*
11550: * Add the annotation to the simple type ancestor.
11551: */
11552: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11553: xmlSchemaParseAnnotation(ctxt, child, 1));
11554: child = child->next;
11555: }
11556: if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11557: /*
11558: * Corresponds to <simpleType><restriction><simpleType>.
11559: */
11560: if (IS_SCHEMA(child, "simpleType")) {
11561: if (type->base != NULL) {
11562: /*
11563: * src-restriction-base-or-simpleType
11564: * Either the base [attribute] or the simpleType [child] of the
11565: * <restriction> element must be present, but not both.
11566: */
11567: xmlSchemaPContentErr(ctxt,
11568: XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11569: NULL, node, child,
11570: "The attribute 'base' and the <simpleType> child are "
11571: "mutually exclusive", NULL);
11572: } else {
11573: type->baseType = (xmlSchemaTypePtr)
11574: xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11575: }
11576: child = child->next;
11577: } else if (type->base == NULL) {
11578: xmlSchemaPContentErr(ctxt,
11579: XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11580: NULL, node, child,
11581: "Either the attribute 'base' or a <simpleType> child "
11582: "must be present", NULL);
11583: }
11584: } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11585: /*
11586: * Corresponds to <complexType><complexContent><restriction>...
11587: * followed by:
11588: *
11589: * Model groups <all>, <choice> and <sequence>.
11590: */
11591: if (IS_SCHEMA(child, "all")) {
11592: type->subtypes = (xmlSchemaTypePtr)
11593: xmlSchemaParseModelGroup(ctxt, schema, child,
11594: XML_SCHEMA_TYPE_ALL, 1);
11595: child = child->next;
11596: } else if (IS_SCHEMA(child, "choice")) {
11597: type->subtypes = (xmlSchemaTypePtr)
11598: xmlSchemaParseModelGroup(ctxt,
11599: schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11600: child = child->next;
11601: } else if (IS_SCHEMA(child, "sequence")) {
11602: type->subtypes = (xmlSchemaTypePtr)
11603: xmlSchemaParseModelGroup(ctxt, schema, child,
11604: XML_SCHEMA_TYPE_SEQUENCE, 1);
11605: child = child->next;
11606: /*
11607: * Model group reference <group>.
11608: */
11609: } else if (IS_SCHEMA(child, "group")) {
11610: type->subtypes = (xmlSchemaTypePtr)
11611: xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11612: /*
11613: * Note that the reference will be resolved in
11614: * xmlSchemaResolveTypeReferences();
11615: */
11616: child = child->next;
11617: }
11618: } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11619: /*
11620: * Corresponds to <complexType><simpleContent><restriction>...
11621: *
11622: * "1.1 the simple type definition corresponding to the <simpleType>
11623: * among the [children] of <restriction> if there is one;"
11624: */
11625: if (IS_SCHEMA(child, "simpleType")) {
11626: /*
11627: * We will store the to-be-restricted simple type in
11628: * type->contentTypeDef *temporarily*.
11629: */
11630: type->contentTypeDef = (xmlSchemaTypePtr)
11631: xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11632: if ( type->contentTypeDef == NULL)
11633: return (NULL);
11634: child = child->next;
11635: }
11636: }
11637:
11638: if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11639: (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11640: xmlSchemaFacetPtr facet, lastfacet = NULL;
11641: /*
11642: * Corresponds to <complexType><simpleContent><restriction>...
11643: * <simpleType><restriction>...
11644: */
11645:
11646: /*
11647: * Add the facets to the simple type ancestor.
11648: */
11649: /*
11650: * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11651: * Simple Type Definition Schema Representation Constraint:
11652: * *Single Facet Value*
11653: */
11654: while ((IS_SCHEMA(child, "minInclusive")) ||
11655: (IS_SCHEMA(child, "minExclusive")) ||
11656: (IS_SCHEMA(child, "maxInclusive")) ||
11657: (IS_SCHEMA(child, "maxExclusive")) ||
11658: (IS_SCHEMA(child, "totalDigits")) ||
11659: (IS_SCHEMA(child, "fractionDigits")) ||
11660: (IS_SCHEMA(child, "pattern")) ||
11661: (IS_SCHEMA(child, "enumeration")) ||
11662: (IS_SCHEMA(child, "whiteSpace")) ||
11663: (IS_SCHEMA(child, "length")) ||
11664: (IS_SCHEMA(child, "maxLength")) ||
11665: (IS_SCHEMA(child, "minLength"))) {
11666: facet = xmlSchemaParseFacet(ctxt, schema, child);
11667: if (facet != NULL) {
11668: if (lastfacet == NULL)
11669: type->facets = facet;
11670: else
11671: lastfacet->next = facet;
11672: lastfacet = facet;
11673: lastfacet->next = NULL;
11674: }
11675: child = child->next;
11676: }
11677: /*
11678: * Create links for derivation and validation.
11679: */
11680: if (type->facets != NULL) {
11681: xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11682:
11683: facet = type->facets;
11684: do {
11685: facetLink = (xmlSchemaFacetLinkPtr)
11686: xmlMalloc(sizeof(xmlSchemaFacetLink));
11687: if (facetLink == NULL) {
11688: xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11689: xmlFree(facetLink);
11690: return (NULL);
11691: }
11692: facetLink->facet = facet;
11693: facetLink->next = NULL;
11694: if (lastFacetLink == NULL)
11695: type->facetSet = facetLink;
11696: else
11697: lastFacetLink->next = facetLink;
11698: lastFacetLink = facetLink;
11699: facet = facet->next;
11700: } while (facet != NULL);
11701: }
11702: }
11703: if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11704: /*
11705: * Attribute uses/declarations.
11706: */
11707: if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11708: (xmlSchemaItemListPtr *) &(type->attrUses),
11709: XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11710: return(NULL);
11711: /*
11712: * Attribute wildcard.
11713: */
11714: if (IS_SCHEMA(child, "anyAttribute")) {
11715: type->attributeWildcard =
11716: xmlSchemaParseAnyAttribute(ctxt, schema, child);
11717: child = child->next;
11718: }
11719: }
11720: if (child != NULL) {
11721: if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11722: xmlSchemaPContentErr(ctxt,
11723: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11724: NULL, node, child, NULL,
11725: "annotation?, (group | all | choice | sequence)?, "
11726: "((attribute | attributeGroup)*, anyAttribute?))");
11727: } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11728: xmlSchemaPContentErr(ctxt,
11729: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11730: NULL, node, child, NULL,
11731: "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11732: "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11733: "length | minLength | maxLength | enumeration | whiteSpace | "
11734: "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11735: } else {
11736: /* Simple type */
11737: xmlSchemaPContentErr(ctxt,
11738: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11739: NULL, node, child, NULL,
11740: "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11741: "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11742: "length | minLength | maxLength | enumeration | whiteSpace | "
11743: "pattern)*))");
11744: }
11745: }
11746: return (NULL);
11747: }
11748:
11749: /**
11750: * xmlSchemaParseExtension:
11751: * @ctxt: a schema validation context
11752: * @schema: the schema being built
11753: * @node: a subtree containing XML Schema informations
11754: *
11755: * Parses an <extension>, which is found inside a
11756: * <simpleContent> or <complexContent>.
11757: * *WARNING* this interface is highly subject to change.
11758: *
11759: * TODO: Returns the type definition or NULL in case of error
11760: */
11761: static xmlSchemaTypePtr
11762: xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11763: xmlNodePtr node, xmlSchemaTypeType parentType)
11764: {
11765: xmlSchemaTypePtr type;
11766: xmlNodePtr child = NULL;
11767: xmlAttrPtr attr;
11768:
11769: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11770: return (NULL);
11771: /* Not a component, don't create it. */
11772: type = ctxt->ctxtType;
11773: type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11774:
11775: /*
11776: * Check for illegal attributes.
11777: */
11778: attr = node->properties;
11779: while (attr != NULL) {
11780: if (attr->ns == NULL) {
11781: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11782: (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11783: xmlSchemaPIllegalAttrErr(ctxt,
11784: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11785: }
11786: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11787: xmlSchemaPIllegalAttrErr(ctxt,
11788: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11789: }
11790: attr = attr->next;
11791: }
11792:
11793: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11794:
11795: /*
11796: * Attribute "base" - mandatory.
11797: */
11798: if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11799: "base", &(type->baseNs), &(type->base)) == 0) &&
11800: (type->base == NULL)) {
11801: xmlSchemaPMissingAttrErr(ctxt,
11802: XML_SCHEMAP_S4S_ATTR_MISSING,
11803: NULL, node, "base", NULL);
11804: }
11805: /*
11806: * And now for the children...
11807: */
11808: child = node->children;
11809: if (IS_SCHEMA(child, "annotation")) {
11810: /*
11811: * Add the annotation to the type ancestor.
11812: */
11813: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11814: xmlSchemaParseAnnotation(ctxt, child, 1));
11815: child = child->next;
11816: }
11817: if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11818: /*
11819: * Corresponds to <complexType><complexContent><extension>... and:
11820: *
11821: * Model groups <all>, <choice>, <sequence> and <group>.
11822: */
11823: if (IS_SCHEMA(child, "all")) {
11824: type->subtypes = (xmlSchemaTypePtr)
11825: xmlSchemaParseModelGroup(ctxt, schema,
11826: child, XML_SCHEMA_TYPE_ALL, 1);
11827: child = child->next;
11828: } else if (IS_SCHEMA(child, "choice")) {
11829: type->subtypes = (xmlSchemaTypePtr)
11830: xmlSchemaParseModelGroup(ctxt, schema,
11831: child, XML_SCHEMA_TYPE_CHOICE, 1);
11832: child = child->next;
11833: } else if (IS_SCHEMA(child, "sequence")) {
11834: type->subtypes = (xmlSchemaTypePtr)
11835: xmlSchemaParseModelGroup(ctxt, schema,
11836: child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11837: child = child->next;
11838: } else if (IS_SCHEMA(child, "group")) {
11839: type->subtypes = (xmlSchemaTypePtr)
11840: xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11841: /*
11842: * Note that the reference will be resolved in
11843: * xmlSchemaResolveTypeReferences();
11844: */
11845: child = child->next;
11846: }
11847: }
11848: if (child != NULL) {
11849: /*
11850: * Attribute uses/declarations.
11851: */
11852: if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11853: (xmlSchemaItemListPtr *) &(type->attrUses),
11854: XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11855: return(NULL);
11856: /*
11857: * Attribute wildcard.
11858: */
11859: if (IS_SCHEMA(child, "anyAttribute")) {
11860: ctxt->ctxtType->attributeWildcard =
11861: xmlSchemaParseAnyAttribute(ctxt, schema, child);
11862: child = child->next;
11863: }
11864: }
11865: if (child != NULL) {
11866: if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11867: /* Complex content extension. */
11868: xmlSchemaPContentErr(ctxt,
11869: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11870: NULL, node, child, NULL,
11871: "(annotation?, ((group | all | choice | sequence)?, "
11872: "((attribute | attributeGroup)*, anyAttribute?)))");
11873: } else {
11874: /* Simple content extension. */
11875: xmlSchemaPContentErr(ctxt,
11876: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11877: NULL, node, child, NULL,
11878: "(annotation?, ((attribute | attributeGroup)*, "
11879: "anyAttribute?))");
11880: }
11881: }
11882: return (NULL);
11883: }
11884:
11885: /**
11886: * xmlSchemaParseSimpleContent:
11887: * @ctxt: a schema validation context
11888: * @schema: the schema being built
11889: * @node: a subtree containing XML Schema informations
11890: *
11891: * parse a XML schema SimpleContent definition
11892: * *WARNING* this interface is highly subject to change
11893: *
11894: * Returns the type definition or NULL in case of error
11895: */
11896: static int
11897: xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11898: xmlSchemaPtr schema, xmlNodePtr node,
11899: int *hasRestrictionOrExtension)
11900: {
11901: xmlSchemaTypePtr type;
11902: xmlNodePtr child = NULL;
11903: xmlAttrPtr attr;
11904:
11905: if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11906: (hasRestrictionOrExtension == NULL))
11907: return (-1);
11908: *hasRestrictionOrExtension = 0;
11909: /* Not a component, don't create it. */
11910: type = ctxt->ctxtType;
11911: type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11912: /*
11913: * Check for illegal attributes.
11914: */
11915: attr = node->properties;
11916: while (attr != NULL) {
11917: if (attr->ns == NULL) {
11918: if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11919: xmlSchemaPIllegalAttrErr(ctxt,
11920: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11921: }
11922: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11923: xmlSchemaPIllegalAttrErr(ctxt,
11924: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11925: }
11926: attr = attr->next;
11927: }
11928:
11929: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11930:
11931: /*
11932: * And now for the children...
11933: */
11934: child = node->children;
11935: if (IS_SCHEMA(child, "annotation")) {
11936: /*
11937: * Add the annotation to the complex type ancestor.
11938: */
11939: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11940: xmlSchemaParseAnnotation(ctxt, child, 1));
11941: child = child->next;
11942: }
11943: if (child == NULL) {
11944: xmlSchemaPContentErr(ctxt,
11945: XML_SCHEMAP_S4S_ELEM_MISSING,
11946: NULL, node, NULL, NULL,
11947: "(annotation?, (restriction | extension))");
11948: }
11949: if (child == NULL) {
11950: xmlSchemaPContentErr(ctxt,
11951: XML_SCHEMAP_S4S_ELEM_MISSING,
11952: NULL, node, NULL, NULL,
11953: "(annotation?, (restriction | extension))");
11954: }
11955: if (IS_SCHEMA(child, "restriction")) {
11956: xmlSchemaParseRestriction(ctxt, schema, child,
11957: XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11958: (*hasRestrictionOrExtension) = 1;
11959: child = child->next;
11960: } else if (IS_SCHEMA(child, "extension")) {
11961: xmlSchemaParseExtension(ctxt, schema, child,
11962: XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11963: (*hasRestrictionOrExtension) = 1;
11964: child = child->next;
11965: }
11966: if (child != NULL) {
11967: xmlSchemaPContentErr(ctxt,
11968: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11969: NULL, node, child, NULL,
11970: "(annotation?, (restriction | extension))");
11971: }
11972: return (0);
11973: }
11974:
11975: /**
11976: * xmlSchemaParseComplexContent:
11977: * @ctxt: a schema validation context
11978: * @schema: the schema being built
11979: * @node: a subtree containing XML Schema informations
11980: *
11981: * parse a XML schema ComplexContent definition
11982: * *WARNING* this interface is highly subject to change
11983: *
11984: * Returns the type definition or NULL in case of error
11985: */
11986: static int
11987: xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11988: xmlSchemaPtr schema, xmlNodePtr node,
11989: int *hasRestrictionOrExtension)
11990: {
11991: xmlSchemaTypePtr type;
11992: xmlNodePtr child = NULL;
11993: xmlAttrPtr attr;
11994:
11995: if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11996: (hasRestrictionOrExtension == NULL))
11997: return (-1);
11998: *hasRestrictionOrExtension = 0;
11999: /* Not a component, don't create it. */
12000: type = ctxt->ctxtType;
12001: /*
12002: * Check for illegal attributes.
12003: */
12004: attr = node->properties;
12005: while (attr != NULL) {
12006: if (attr->ns == NULL) {
12007: if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12008: (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12009: {
12010: xmlSchemaPIllegalAttrErr(ctxt,
12011: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12012: }
12013: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12014: xmlSchemaPIllegalAttrErr(ctxt,
12015: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12016: }
12017: attr = attr->next;
12018: }
12019:
12020: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12021:
12022: /*
12023: * Set the 'mixed' on the complex type ancestor.
12024: */
12025: if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
12026: if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12027: type->flags |= XML_SCHEMAS_TYPE_MIXED;
12028: }
12029: child = node->children;
12030: if (IS_SCHEMA(child, "annotation")) {
12031: /*
12032: * Add the annotation to the complex type ancestor.
12033: */
12034: xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12035: xmlSchemaParseAnnotation(ctxt, child, 1));
12036: child = child->next;
12037: }
12038: if (child == NULL) {
12039: xmlSchemaPContentErr(ctxt,
12040: XML_SCHEMAP_S4S_ELEM_MISSING,
12041: NULL, node, NULL,
12042: NULL, "(annotation?, (restriction | extension))");
12043: }
12044: if (child == NULL) {
12045: xmlSchemaPContentErr(ctxt,
12046: XML_SCHEMAP_S4S_ELEM_MISSING,
12047: NULL, node, NULL,
12048: NULL, "(annotation?, (restriction | extension))");
12049: }
12050: if (IS_SCHEMA(child, "restriction")) {
12051: xmlSchemaParseRestriction(ctxt, schema, child,
12052: XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12053: (*hasRestrictionOrExtension) = 1;
12054: child = child->next;
12055: } else if (IS_SCHEMA(child, "extension")) {
12056: xmlSchemaParseExtension(ctxt, schema, child,
12057: XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12058: (*hasRestrictionOrExtension) = 1;
12059: child = child->next;
12060: }
12061: if (child != NULL) {
12062: xmlSchemaPContentErr(ctxt,
12063: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12064: NULL, node, child,
12065: NULL, "(annotation?, (restriction | extension))");
12066: }
12067: return (0);
12068: }
12069:
12070: /**
12071: * xmlSchemaParseComplexType:
12072: * @ctxt: a schema validation context
12073: * @schema: the schema being built
12074: * @node: a subtree containing XML Schema informations
12075: *
12076: * parse a XML schema Complex Type definition
12077: * *WARNING* this interface is highly subject to change
12078: *
12079: * Returns the type definition or NULL in case of error
12080: */
12081: static xmlSchemaTypePtr
12082: xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12083: xmlNodePtr node, int topLevel)
12084: {
12085: xmlSchemaTypePtr type, ctxtType;
12086: xmlNodePtr child = NULL;
12087: const xmlChar *name = NULL;
12088: xmlAttrPtr attr;
12089: const xmlChar *attrValue;
12090: #ifdef ENABLE_NAMED_LOCALS
12091: char buf[40];
12092: #endif
12093: int final = 0, block = 0, hasRestrictionOrExtension = 0;
12094:
12095:
12096: if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12097: return (NULL);
12098:
12099: ctxtType = ctxt->ctxtType;
12100:
12101: if (topLevel) {
12102: attr = xmlSchemaGetPropNode(node, "name");
12103: if (attr == NULL) {
12104: xmlSchemaPMissingAttrErr(ctxt,
12105: XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12106: return (NULL);
12107: } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12108: xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12109: return (NULL);
12110: }
12111: }
12112:
12113: if (topLevel == 0) {
12114: /*
12115: * Parse as local complex type definition.
12116: */
12117: #ifdef ENABLE_NAMED_LOCALS
12118: snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12119: type = xmlSchemaAddType(ctxt, schema,
12120: XML_SCHEMA_TYPE_COMPLEX,
12121: xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12122: ctxt->targetNamespace, node, 0);
12123: #else
12124: type = xmlSchemaAddType(ctxt, schema,
12125: XML_SCHEMA_TYPE_COMPLEX,
12126: NULL, ctxt->targetNamespace, node, 0);
12127: #endif
12128: if (type == NULL)
12129: return (NULL);
12130: name = type->name;
12131: type->node = node;
12132: type->type = XML_SCHEMA_TYPE_COMPLEX;
12133: /*
12134: * TODO: We need the target namespace.
12135: */
12136: } else {
12137: /*
12138: * Parse as global complex type definition.
12139: */
12140: type = xmlSchemaAddType(ctxt, schema,
12141: XML_SCHEMA_TYPE_COMPLEX,
12142: name, ctxt->targetNamespace, node, 1);
12143: if (type == NULL)
12144: return (NULL);
12145: type->node = node;
12146: type->type = XML_SCHEMA_TYPE_COMPLEX;
12147: type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12148: }
12149: type->targetNamespace = ctxt->targetNamespace;
12150: /*
12151: * Handle attributes.
12152: */
12153: attr = node->properties;
12154: while (attr != NULL) {
12155: if (attr->ns == NULL) {
12156: if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12157: /*
12158: * Attribute "id".
12159: */
12160: xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12161: } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12162: /*
12163: * Attribute "mixed".
12164: */
12165: if (xmlSchemaPGetBoolNodeValue(ctxt,
12166: NULL, (xmlNodePtr) attr))
12167: type->flags |= XML_SCHEMAS_TYPE_MIXED;
12168: } else if (topLevel) {
12169: /*
12170: * Attributes of global complex type definitions.
12171: */
12172: if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12173: /* Pass. */
12174: } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12175: /*
12176: * Attribute "abstract".
12177: */
12178: if (xmlSchemaPGetBoolNodeValue(ctxt,
12179: NULL, (xmlNodePtr) attr))
12180: type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12181: } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12182: /*
12183: * Attribute "final".
12184: */
12185: attrValue = xmlSchemaGetNodeContent(ctxt,
12186: (xmlNodePtr) attr);
12187: if (xmlSchemaPValAttrBlockFinal(attrValue,
12188: &(type->flags),
12189: -1,
12190: XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12191: XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12192: -1, -1, -1) != 0)
12193: {
12194: xmlSchemaPSimpleTypeErr(ctxt,
12195: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12196: NULL, (xmlNodePtr) attr, NULL,
12197: "(#all | List of (extension | restriction))",
12198: attrValue, NULL, NULL, NULL);
12199: } else
12200: final = 1;
12201: } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12202: /*
12203: * Attribute "block".
12204: */
12205: attrValue = xmlSchemaGetNodeContent(ctxt,
12206: (xmlNodePtr) attr);
12207: if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12208: -1,
12209: XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12210: XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12211: -1, -1, -1) != 0) {
12212: xmlSchemaPSimpleTypeErr(ctxt,
12213: XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12214: NULL, (xmlNodePtr) attr, NULL,
12215: "(#all | List of (extension | restriction)) ",
12216: attrValue, NULL, NULL, NULL);
12217: } else
12218: block = 1;
12219: } else {
12220: xmlSchemaPIllegalAttrErr(ctxt,
12221: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12222: }
12223: } else {
12224: xmlSchemaPIllegalAttrErr(ctxt,
12225: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12226: }
12227: } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12228: xmlSchemaPIllegalAttrErr(ctxt,
12229: XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12230: }
12231: attr = attr->next;
12232: }
12233: if (! block) {
12234: /*
12235: * Apply default "block" values.
12236: */
12237: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12238: type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12239: if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12240: type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12241: }
12242: if (! final) {
12243: /*
12244: * Apply default "block" values.
12245: */
12246: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12247: type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12248: if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12249: type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12250: }
12251: /*
12252: * And now for the children...
12253: */
12254: child = node->children;
12255: if (IS_SCHEMA(child, "annotation")) {
12256: type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12257: child = child->next;
12258: }
12259: ctxt->ctxtType = type;
12260: if (IS_SCHEMA(child, "simpleContent")) {
12261: /*
12262: * <complexType><simpleContent>...
12263: * 3.4.3 : 2.2
12264: * Specifying mixed='true' when the <simpleContent>
12265: * alternative is chosen has no effect
12266: */
12267: if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12268: type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12269: xmlSchemaParseSimpleContent(ctxt, schema, child,
12270: &hasRestrictionOrExtension);
12271: child = child->next;
12272: } else if (IS_SCHEMA(child, "complexContent")) {
12273: /*
12274: * <complexType><complexContent>...
12275: */
12276: type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12277: xmlSchemaParseComplexContent(ctxt, schema, child,
12278: &hasRestrictionOrExtension);
12279: child = child->next;
12280: } else {
12281: /*
12282: * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12283: *
12284: * SPEC
12285: * "...the third alternative (neither <simpleContent> nor
12286: * <complexContent>) is chosen. This case is understood as shorthand
12287: * for complex content restricting the �ur-type definition�, and the
12288: * details of the mappings should be modified as necessary.
12289: */
12290: type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12291: type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12292: /*
12293: * Parse model groups.
12294: */
12295: if (IS_SCHEMA(child, "all")) {
12296: type->subtypes = (xmlSchemaTypePtr)
12297: xmlSchemaParseModelGroup(ctxt, schema, child,
12298: XML_SCHEMA_TYPE_ALL, 1);
12299: child = child->next;
12300: } else if (IS_SCHEMA(child, "choice")) {
12301: type->subtypes = (xmlSchemaTypePtr)
12302: xmlSchemaParseModelGroup(ctxt, schema, child,
12303: XML_SCHEMA_TYPE_CHOICE, 1);
12304: child = child->next;
12305: } else if (IS_SCHEMA(child, "sequence")) {
12306: type->subtypes = (xmlSchemaTypePtr)
12307: xmlSchemaParseModelGroup(ctxt, schema, child,
12308: XML_SCHEMA_TYPE_SEQUENCE, 1);
12309: child = child->next;
12310: } else if (IS_SCHEMA(child, "group")) {
12311: type->subtypes = (xmlSchemaTypePtr)
12312: xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12313: /*
12314: * Note that the reference will be resolved in
12315: * xmlSchemaResolveTypeReferences();
12316: */
12317: child = child->next;
12318: }
12319: /*
12320: * Parse attribute decls/refs.
12321: */
12322: if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12323: (xmlSchemaItemListPtr *) &(type->attrUses),
12324: XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12325: return(NULL);
12326: /*
12327: * Parse attribute wildcard.
12328: */
12329: if (IS_SCHEMA(child, "anyAttribute")) {
12330: type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12331: child = child->next;
12332: }
12333: }
12334: if (child != NULL) {
12335: xmlSchemaPContentErr(ctxt,
12336: XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12337: NULL, node, child,
12338: NULL, "(annotation?, (simpleContent | complexContent | "
12339: "((group | all | choice | sequence)?, ((attribute | "
12340: "attributeGroup)*, anyAttribute?))))");
12341: }
12342: /*
12343: * REDEFINE: SPEC src-redefine (5)
12344: */
12345: if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12346: xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12347: NULL, node, "This is a redefinition, thus the "
12348: "<complexType> must have a <restriction> or <extension> "
12349: "grand-child", NULL);
12350: }
12351: ctxt->ctxtType = ctxtType;
12352: return (type);
12353: }
12354:
12355: /************************************************************************
12356: * *
12357: * Validating using Schemas *
12358: * *
12359: ************************************************************************/
12360:
12361: /************************************************************************
12362: * *
12363: * Reading/Writing Schemas *
12364: * *
12365: ************************************************************************/
12366:
12367: #if 0 /* Will be enabled if it is clear what options are needed. */
12368: /**
12369: * xmlSchemaParserCtxtSetOptions:
12370: * @ctxt: a schema parser context
12371: * @options: a combination of xmlSchemaParserOption
12372: *
12373: * Sets the options to be used during the parse.
12374: *
12375: * Returns 0 in case of success, -1 in case of an
12376: * API error.
12377: */
12378: static int
12379: xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12380: int options)
12381:
12382: {
12383: int i;
12384:
12385: if (ctxt == NULL)
12386: return (-1);
12387: /*
12388: * WARNING: Change the start value if adding to the
12389: * xmlSchemaParseOption.
12390: */
12391: for (i = 1; i < (int) sizeof(int) * 8; i++) {
12392: if (options & 1<<i) {
12393: return (-1);
12394: }
12395: }
12396: ctxt->options = options;
12397: return (0);
12398: }
12399:
12400: /**
12401: * xmlSchemaValidCtxtGetOptions:
12402: * @ctxt: a schema parser context
12403: *
12404: * Returns the option combination of the parser context.
12405: */
12406: static int
12407: xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12408:
12409: {
12410: if (ctxt == NULL)
12411: return (-1);
12412: else
12413: return (ctxt->options);
12414: }
12415: #endif
12416:
12417: /**
12418: * xmlSchemaNewParserCtxt:
12419: * @URL: the location of the schema
12420: *
12421: * Create an XML Schemas parse context for that file/resource expected
12422: * to contain an XML Schemas file.
12423: *
12424: * Returns the parser context or NULL in case of error
12425: */
12426: xmlSchemaParserCtxtPtr
12427: xmlSchemaNewParserCtxt(const char *URL)
12428: {
12429: xmlSchemaParserCtxtPtr ret;
12430:
12431: if (URL == NULL)
12432: return (NULL);
12433:
12434: ret = xmlSchemaParserCtxtCreate();
12435: if (ret == NULL)
12436: return(NULL);
12437: ret->dict = xmlDictCreate();
12438: ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12439: return (ret);
12440: }
12441:
12442: /**
12443: * xmlSchemaNewMemParserCtxt:
12444: * @buffer: a pointer to a char array containing the schemas
12445: * @size: the size of the array
12446: *
12447: * Create an XML Schemas parse context for that memory buffer expected
12448: * to contain an XML Schemas file.
12449: *
12450: * Returns the parser context or NULL in case of error
12451: */
12452: xmlSchemaParserCtxtPtr
12453: xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12454: {
12455: xmlSchemaParserCtxtPtr ret;
12456:
12457: if ((buffer == NULL) || (size <= 0))
12458: return (NULL);
12459: ret = xmlSchemaParserCtxtCreate();
12460: if (ret == NULL)
12461: return(NULL);
12462: ret->buffer = buffer;
12463: ret->size = size;
12464: ret->dict = xmlDictCreate();
12465: return (ret);
12466: }
12467:
12468: /**
12469: * xmlSchemaNewDocParserCtxt:
12470: * @doc: a preparsed document tree
12471: *
12472: * Create an XML Schemas parse context for that document.
12473: * NB. The document may be modified during the parsing process.
12474: *
12475: * Returns the parser context or NULL in case of error
12476: */
12477: xmlSchemaParserCtxtPtr
12478: xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12479: {
12480: xmlSchemaParserCtxtPtr ret;
12481:
12482: if (doc == NULL)
12483: return (NULL);
12484: ret = xmlSchemaParserCtxtCreate();
12485: if (ret == NULL)
12486: return(NULL);
12487: ret->doc = doc;
12488: ret->dict = xmlDictCreate();
12489: /* The application has responsibility for the document */
12490: ret->preserve = 1;
12491:
12492: return (ret);
12493: }
12494:
12495: /**
12496: * xmlSchemaFreeParserCtxt:
12497: * @ctxt: the schema parser context
12498: *
12499: * Free the resources associated to the schema parser context
12500: */
12501: void
12502: xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12503: {
12504: if (ctxt == NULL)
12505: return;
12506: if (ctxt->doc != NULL && !ctxt->preserve)
12507: xmlFreeDoc(ctxt->doc);
12508: if (ctxt->vctxt != NULL) {
12509: xmlSchemaFreeValidCtxt(ctxt->vctxt);
12510: }
12511: if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12512: xmlSchemaConstructionCtxtFree(ctxt->constructor);
12513: ctxt->constructor = NULL;
12514: ctxt->ownsConstructor = 0;
12515: }
12516: if (ctxt->attrProhibs != NULL)
12517: xmlSchemaItemListFree(ctxt->attrProhibs);
12518: xmlDictFree(ctxt->dict);
12519: xmlFree(ctxt);
12520: }
12521:
12522: /************************************************************************
12523: * *
12524: * Building the content models *
12525: * *
12526: ************************************************************************/
12527:
12528: /**
12529: * xmlSchemaBuildContentModelForSubstGroup:
12530: *
12531: * Returns 1 if nillable, 0 otherwise
12532: */
12533: static int
12534: xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12535: xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12536: {
12537: xmlAutomataStatePtr start, tmp;
12538: xmlSchemaElementPtr elemDecl, member;
12539: xmlSchemaSubstGroupPtr substGroup;
12540: int i;
12541: int ret = 0;
12542:
12543: elemDecl = (xmlSchemaElementPtr) particle->children;
12544: /*
12545: * Wrap the substitution group with a CHOICE.
12546: */
12547: start = pctxt->state;
12548: if (end == NULL)
12549: end = xmlAutomataNewState(pctxt->am);
12550: substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12551: if (substGroup == NULL) {
12552: xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12553: XML_SCHEMAP_INTERNAL,
12554: "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12555: "declaration is marked having a subst. group but none "
12556: "available.\n", elemDecl->name, NULL);
12557: return(0);
12558: }
12559: if (counter >= 0) {
12560: /*
12561: * NOTE that we put the declaration in, even if it's abstract.
12562: * However, an error will be raised during *validation* if an element
12563: * information item shall be validated against an abstract element
12564: * declaration.
12565: */
12566: tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12567: xmlAutomataNewTransition2(pctxt->am, tmp, end,
12568: elemDecl->name, elemDecl->targetNamespace, elemDecl);
12569: /*
12570: * Add subst. group members.
12571: */
12572: for (i = 0; i < substGroup->members->nbItems; i++) {
12573: member = (xmlSchemaElementPtr) substGroup->members->items[i];
12574: xmlAutomataNewTransition2(pctxt->am, tmp, end,
12575: member->name, member->targetNamespace, member);
12576: }
12577: } else if (particle->maxOccurs == 1) {
12578: /*
12579: * NOTE that we put the declaration in, even if it's abstract,
12580: */
12581: xmlAutomataNewEpsilon(pctxt->am,
12582: xmlAutomataNewTransition2(pctxt->am,
12583: start, NULL,
12584: elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12585: /*
12586: * Add subst. group members.
12587: */
12588: for (i = 0; i < substGroup->members->nbItems; i++) {
12589: member = (xmlSchemaElementPtr) substGroup->members->items[i];
12590: /*
12591: * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12592: * was incorrectly used instead of xmlAutomataNewTransition2()
12593: * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12594: * section in xmlSchemaBuildAContentModel() ).
12595: * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12596: * intended for the above "counter" section originally. I.e.,
12597: * check xs:all with subst-groups.
12598: *
12599: * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12600: * member->name, member->targetNamespace,
12601: * 1, 1, member);
12602: */
12603: tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12604: member->name, member->targetNamespace, member);
12605: xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12606: }
12607: } else {
12608: xmlAutomataStatePtr hop;
12609: int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12610: UNBOUNDED : particle->maxOccurs - 1;
12611: int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12612:
12613: counter =
12614: xmlAutomataNewCounter(pctxt->am, minOccurs,
12615: maxOccurs);
12616: hop = xmlAutomataNewState(pctxt->am);
12617:
12618: xmlAutomataNewEpsilon(pctxt->am,
12619: xmlAutomataNewTransition2(pctxt->am,
12620: start, NULL,
12621: elemDecl->name, elemDecl->targetNamespace, elemDecl),
12622: hop);
12623: /*
12624: * Add subst. group members.
12625: */
12626: for (i = 0; i < substGroup->members->nbItems; i++) {
12627: member = (xmlSchemaElementPtr) substGroup->members->items[i];
12628: xmlAutomataNewEpsilon(pctxt->am,
12629: xmlAutomataNewTransition2(pctxt->am,
12630: start, NULL,
12631: member->name, member->targetNamespace, member),
12632: hop);
12633: }
12634: xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12635: xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12636: }
12637: if (particle->minOccurs == 0) {
12638: xmlAutomataNewEpsilon(pctxt->am, start, end);
12639: ret = 1;
12640: }
12641: pctxt->state = end;
12642: return(ret);
12643: }
12644:
12645: /**
12646: * xmlSchemaBuildContentModelForElement:
12647: *
12648: * Returns 1 if nillable, 0 otherwise
12649: */
12650: static int
12651: xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12652: xmlSchemaParticlePtr particle)
12653: {
12654: int ret = 0;
12655:
12656: if (((xmlSchemaElementPtr) particle->children)->flags &
12657: XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12658: /*
12659: * Substitution groups.
12660: */
12661: ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12662: } else {
12663: xmlSchemaElementPtr elemDecl;
12664: xmlAutomataStatePtr start;
12665:
12666: elemDecl = (xmlSchemaElementPtr) particle->children;
12667:
12668: if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12669: return(0);
12670: if (particle->maxOccurs == 1) {
12671: start = ctxt->state;
12672: ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12673: elemDecl->name, elemDecl->targetNamespace, elemDecl);
12674: } else if ((particle->maxOccurs >= UNBOUNDED) &&
12675: (particle->minOccurs < 2)) {
12676: /* Special case. */
12677: start = ctxt->state;
12678: ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12679: elemDecl->name, elemDecl->targetNamespace, elemDecl);
12680: ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12681: elemDecl->name, elemDecl->targetNamespace, elemDecl);
12682: } else {
12683: int counter;
12684: int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12685: UNBOUNDED : particle->maxOccurs - 1;
12686: int minOccurs = particle->minOccurs < 1 ?
12687: 0 : particle->minOccurs - 1;
12688:
12689: start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12690: counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12691: ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12692: elemDecl->name, elemDecl->targetNamespace, elemDecl);
12693: xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12694: ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12695: NULL, counter);
12696: }
12697: if (particle->minOccurs == 0) {
12698: xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12699: ret = 1;
12700: }
12701: }
12702: return(ret);
12703: }
12704:
12705: /**
12706: * xmlSchemaBuildAContentModel:
12707: * @ctxt: the schema parser context
12708: * @particle: the particle component
12709: * @name: the complex type's name whose content is being built
12710: *
12711: * Create the automaton for the {content type} of a complex type.
12712: *
12713: * Returns 1 if the content is nillable, 0 otherwise
12714: */
12715: static int
12716: xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12717: xmlSchemaParticlePtr particle)
12718: {
12719: int ret = 0, tmp2;
12720:
12721: if (particle == NULL) {
12722: PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12723: return(1);
12724: }
12725: if (particle->children == NULL) {
12726: /*
12727: * Just return in this case. A missing "term" of the particle
12728: * might arise due to an invalid "term" component.
12729: */
12730: return(1);
12731: }
12732:
12733: switch (particle->children->type) {
12734: case XML_SCHEMA_TYPE_ANY: {
12735: xmlAutomataStatePtr start, end;
12736: xmlSchemaWildcardPtr wild;
12737: xmlSchemaWildcardNsPtr ns;
12738:
12739: wild = (xmlSchemaWildcardPtr) particle->children;
12740:
12741: start = pctxt->state;
12742: end = xmlAutomataNewState(pctxt->am);
12743:
12744: if (particle->maxOccurs == 1) {
12745: if (wild->any == 1) {
12746: /*
12747: * We need to add both transitions:
12748: *
12749: * 1. the {"*", "*"} for elements in a namespace.
12750: */
12751: pctxt->state =
12752: xmlAutomataNewTransition2(pctxt->am,
12753: start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12754: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12755: /*
12756: * 2. the {"*"} for elements in no namespace.
12757: */
12758: pctxt->state =
12759: xmlAutomataNewTransition2(pctxt->am,
12760: start, NULL, BAD_CAST "*", NULL, wild);
12761: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12762:
12763: } else if (wild->nsSet != NULL) {
12764: ns = wild->nsSet;
12765: do {
12766: pctxt->state = start;
12767: pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12768: pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12769: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12770: ns = ns->next;
12771: } while (ns != NULL);
12772:
12773: } else if (wild->negNsSet != NULL) {
12774: pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12775: start, end, BAD_CAST "*", wild->negNsSet->value,
12776: wild);
12777: }
12778: } else {
12779: int counter;
12780: xmlAutomataStatePtr hop;
12781: int maxOccurs =
12782: particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12783: particle->maxOccurs - 1;
12784: int minOccurs =
12785: particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12786:
12787: counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12788: hop = xmlAutomataNewState(pctxt->am);
12789: if (wild->any == 1) {
12790: pctxt->state =
12791: xmlAutomataNewTransition2(pctxt->am,
12792: start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12793: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12794: pctxt->state =
12795: xmlAutomataNewTransition2(pctxt->am,
12796: start, NULL, BAD_CAST "*", NULL, wild);
12797: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12798: } else if (wild->nsSet != NULL) {
12799: ns = wild->nsSet;
12800: do {
12801: pctxt->state =
12802: xmlAutomataNewTransition2(pctxt->am,
12803: start, NULL, BAD_CAST "*", ns->value, wild);
12804: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12805: ns = ns->next;
12806: } while (ns != NULL);
12807:
12808: } else if (wild->negNsSet != NULL) {
12809: pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12810: start, hop, BAD_CAST "*", wild->negNsSet->value,
12811: wild);
12812: }
12813: xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12814: xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12815: }
12816: if (particle->minOccurs == 0) {
12817: xmlAutomataNewEpsilon(pctxt->am, start, end);
12818: ret = 1;
12819: }
12820: pctxt->state = end;
12821: break;
12822: }
12823: case XML_SCHEMA_TYPE_ELEMENT:
12824: ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12825: break;
12826: case XML_SCHEMA_TYPE_SEQUENCE:{
12827: xmlSchemaTreeItemPtr sub;
12828:
12829: ret = 1;
12830: /*
12831: * If max and min occurances are default (1) then
12832: * simply iterate over the particles of the <sequence>.
12833: */
12834: if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12835: sub = particle->children->children;
12836:
12837: while (sub != NULL) {
12838: tmp2 = xmlSchemaBuildAContentModel(pctxt,
12839: (xmlSchemaParticlePtr) sub);
12840: if (tmp2 != 1) ret = 0;
12841: sub = sub->next;
12842: }
12843: } else {
12844: xmlAutomataStatePtr oldstate = pctxt->state;
12845:
12846: if (particle->maxOccurs >= UNBOUNDED) {
12847: if (particle->minOccurs > 1) {
12848: xmlAutomataStatePtr tmp;
12849: int counter;
12850:
12851: pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12852: oldstate, NULL);
12853: oldstate = pctxt->state;
12854:
12855: counter = xmlAutomataNewCounter(pctxt->am,
12856: particle->minOccurs - 1, UNBOUNDED);
12857:
12858: sub = particle->children->children;
12859: while (sub != NULL) {
12860: tmp2 = xmlSchemaBuildAContentModel(pctxt,
12861: (xmlSchemaParticlePtr) sub);
12862: if (tmp2 != 1) ret = 0;
12863: sub = sub->next;
12864: }
12865: tmp = pctxt->state;
12866: xmlAutomataNewCountedTrans(pctxt->am, tmp,
12867: oldstate, counter);
12868: pctxt->state =
12869: xmlAutomataNewCounterTrans(pctxt->am, tmp,
12870: NULL, counter);
12871: if (ret == 1)
12872: xmlAutomataNewEpsilon(pctxt->am,
12873: oldstate, pctxt->state);
12874:
12875: } else {
12876: pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12877: oldstate, NULL);
12878: oldstate = pctxt->state;
12879:
12880: sub = particle->children->children;
12881: while (sub != NULL) {
12882: tmp2 = xmlSchemaBuildAContentModel(pctxt,
12883: (xmlSchemaParticlePtr) sub);
12884: if (tmp2 != 1) ret = 0;
12885: sub = sub->next;
12886: }
12887: xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12888: oldstate);
12889: /*
12890: * epsilon needed to block previous trans from
12891: * being allowed to enter back from another
12892: * construct
12893: */
12894: pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12895: pctxt->state, NULL);
12896: if (particle->minOccurs == 0) {
12897: xmlAutomataNewEpsilon(pctxt->am,
12898: oldstate, pctxt->state);
12899: ret = 1;
12900: }
12901: }
12902: } else if ((particle->maxOccurs > 1)
12903: || (particle->minOccurs > 1)) {
12904: xmlAutomataStatePtr tmp;
12905: int counter;
12906:
12907: pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12908: oldstate, NULL);
12909: oldstate = pctxt->state;
12910:
12911: counter = xmlAutomataNewCounter(pctxt->am,
12912: particle->minOccurs - 1,
12913: particle->maxOccurs - 1);
12914:
12915: sub = particle->children->children;
12916: while (sub != NULL) {
12917: tmp2 = xmlSchemaBuildAContentModel(pctxt,
12918: (xmlSchemaParticlePtr) sub);
12919: if (tmp2 != 1) ret = 0;
12920: sub = sub->next;
12921: }
12922: tmp = pctxt->state;
12923: xmlAutomataNewCountedTrans(pctxt->am,
12924: tmp, oldstate, counter);
12925: pctxt->state =
12926: xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12927: counter);
12928: if ((particle->minOccurs == 0) || (ret == 1)) {
12929: xmlAutomataNewEpsilon(pctxt->am,
12930: oldstate, pctxt->state);
12931: ret = 1;
12932: }
12933: } else {
12934: sub = particle->children->children;
12935: while (sub != NULL) {
12936: tmp2 = xmlSchemaBuildAContentModel(pctxt,
12937: (xmlSchemaParticlePtr) sub);
12938: if (tmp2 != 1) ret = 0;
12939: sub = sub->next;
12940: }
12941: if (particle->minOccurs == 0) {
12942: xmlAutomataNewEpsilon(pctxt->am, oldstate,
12943: pctxt->state);
12944: ret = 1;
12945: }
12946: }
12947: }
12948: break;
12949: }
12950: case XML_SCHEMA_TYPE_CHOICE:{
12951: xmlSchemaTreeItemPtr sub;
12952: xmlAutomataStatePtr start, end;
12953:
12954: ret = 0;
12955: start = pctxt->state;
12956: end = xmlAutomataNewState(pctxt->am);
12957:
12958: /*
12959: * iterate over the subtypes and remerge the end with an
12960: * epsilon transition
12961: */
12962: if (particle->maxOccurs == 1) {
12963: sub = particle->children->children;
12964: while (sub != NULL) {
12965: pctxt->state = start;
12966: tmp2 = xmlSchemaBuildAContentModel(pctxt,
12967: (xmlSchemaParticlePtr) sub);
12968: if (tmp2 == 1) ret = 1;
12969: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12970: sub = sub->next;
12971: }
12972: } else {
12973: int counter;
12974: xmlAutomataStatePtr hop, base;
12975: int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12976: UNBOUNDED : particle->maxOccurs - 1;
12977: int minOccurs =
12978: particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12979:
12980: /*
12981: * use a counter to keep track of the number of transtions
12982: * which went through the choice.
12983: */
12984: counter =
12985: xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12986: hop = xmlAutomataNewState(pctxt->am);
12987: base = xmlAutomataNewState(pctxt->am);
12988:
12989: sub = particle->children->children;
12990: while (sub != NULL) {
12991: pctxt->state = base;
12992: tmp2 = xmlSchemaBuildAContentModel(pctxt,
12993: (xmlSchemaParticlePtr) sub);
12994: if (tmp2 == 1) ret = 1;
12995: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12996: sub = sub->next;
12997: }
12998: xmlAutomataNewEpsilon(pctxt->am, start, base);
12999: xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13000: xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13001: if (ret == 1)
13002: xmlAutomataNewEpsilon(pctxt->am, base, end);
13003: }
13004: if (particle->minOccurs == 0) {
13005: xmlAutomataNewEpsilon(pctxt->am, start, end);
13006: ret = 1;
13007: }
13008: pctxt->state = end;
13009: break;
13010: }
13011: case XML_SCHEMA_TYPE_ALL:{
13012: xmlAutomataStatePtr start, tmp;
13013: xmlSchemaParticlePtr sub;
13014: xmlSchemaElementPtr elemDecl;
13015:
13016: ret = 1;
13017:
13018: sub = (xmlSchemaParticlePtr) particle->children->children;
13019: if (sub == NULL)
13020: break;
13021:
13022: ret = 0;
13023:
13024: start = pctxt->state;
13025: tmp = xmlAutomataNewState(pctxt->am);
13026: xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13027: pctxt->state = tmp;
13028: while (sub != NULL) {
13029: pctxt->state = tmp;
13030:
13031: elemDecl = (xmlSchemaElementPtr) sub->children;
13032: if (elemDecl == NULL) {
13033: PERROR_INT("xmlSchemaBuildAContentModel",
13034: "<element> particle has no term");
13035: return(ret);
13036: };
13037: /*
13038: * NOTE: The {max occurs} of all the particles in the
13039: * {particles} of the group must be 0 or 1; this is
13040: * already ensured during the parse of the content of
13041: * <all>.
13042: */
13043: if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13044: int counter;
13045:
13046: /*
13047: * This is an abstract group, we need to share
13048: * the same counter for all the element transitions
13049: * derived from the group
13050: */
13051: counter = xmlAutomataNewCounter(pctxt->am,
13052: sub->minOccurs, sub->maxOccurs);
13053: xmlSchemaBuildContentModelForSubstGroup(pctxt,
13054: sub, counter, pctxt->state);
13055: } else {
13056: if ((sub->minOccurs == 1) &&
13057: (sub->maxOccurs == 1)) {
13058: xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13059: pctxt->state,
13060: elemDecl->name,
13061: elemDecl->targetNamespace,
13062: 1, 1, elemDecl);
13063: } else if ((sub->minOccurs == 0) &&
13064: (sub->maxOccurs == 1)) {
13065:
13066: xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13067: pctxt->state,
13068: elemDecl->name,
13069: elemDecl->targetNamespace,
13070: 0,
13071: 1,
13072: elemDecl);
13073: }
13074: }
13075: sub = (xmlSchemaParticlePtr) sub->next;
13076: }
13077: pctxt->state =
13078: xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13079: if (particle->minOccurs == 0) {
13080: xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13081: ret = 1;
13082: }
13083: break;
13084: }
13085: case XML_SCHEMA_TYPE_GROUP:
13086: /*
13087: * If we hit a model group definition, then this means that
13088: * it was empty, thus was not substituted for the containing
13089: * model group. Just do nothing in this case.
13090: * TODO: But the group should be substituted and not occur at
13091: * all in the content model at this point. Fix this.
13092: */
13093: ret = 1;
13094: break;
13095: default:
13096: xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13097: "xmlSchemaBuildAContentModel",
13098: "found unexpected term of type '%s' in content model",
13099: WXS_ITEM_TYPE_NAME(particle->children), NULL);
13100: return(ret);
13101: }
13102: return(ret);
13103: }
13104:
13105: /**
13106: * xmlSchemaBuildContentModel:
13107: * @ctxt: the schema parser context
13108: * @type: the complex type definition
13109: * @name: the element name
13110: *
13111: * Builds the content model of the complex type.
13112: */
13113: static void
13114: xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13115: xmlSchemaParserCtxtPtr ctxt)
13116: {
13117: if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13118: (type->contModel != NULL) ||
13119: ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13120: (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13121: return;
13122:
13123: #ifdef DEBUG_CONTENT
13124: xmlGenericError(xmlGenericErrorContext,
13125: "Building content model for %s\n", name);
13126: #endif
13127: ctxt->am = NULL;
13128: ctxt->am = xmlNewAutomata();
13129: if (ctxt->am == NULL) {
13130: xmlGenericError(xmlGenericErrorContext,
13131: "Cannot create automata for complex type %s\n", type->name);
13132: return;
13133: }
13134: ctxt->state = xmlAutomataGetInitState(ctxt->am);
13135: /*
13136: * Build the automaton.
13137: */
13138: xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13139: xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13140: type->contModel = xmlAutomataCompile(ctxt->am);
13141: if (type->contModel == NULL) {
13142: xmlSchemaPCustomErr(ctxt,
13143: XML_SCHEMAP_INTERNAL,
13144: WXS_BASIC_CAST type, type->node,
13145: "Failed to compile the content model", NULL);
13146: } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13147: xmlSchemaPCustomErr(ctxt,
13148: XML_SCHEMAP_NOT_DETERMINISTIC,
13149: /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13150: WXS_BASIC_CAST type, type->node,
13151: "The content model is not determinist", NULL);
13152: } else {
13153: #ifdef DEBUG_CONTENT_REGEXP
13154: xmlGenericError(xmlGenericErrorContext,
13155: "Content model of %s:\n", type->name);
13156: xmlRegexpPrint(stderr, type->contModel);
13157: #endif
13158: }
13159: ctxt->state = NULL;
13160: xmlFreeAutomata(ctxt->am);
13161: ctxt->am = NULL;
13162: }
13163:
13164: /**
13165: * xmlSchemaResolveElementReferences:
13166: * @elem: the schema element context
13167: * @ctxt: the schema parser context
13168: *
13169: * Resolves the references of an element declaration
13170: * or particle, which has an element declaration as it's
13171: * term.
13172: */
13173: static void
13174: xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13175: xmlSchemaParserCtxtPtr ctxt)
13176: {
13177: if ((ctxt == NULL) || (elemDecl == NULL) ||
13178: ((elemDecl != NULL) &&
13179: (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13180: return;
13181: elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13182:
13183: if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13184: xmlSchemaTypePtr type;
13185:
13186: /* (type definition) ... otherwise the type definition �resolved�
13187: * to by the �actual value� of the type [attribute] ...
13188: */
13189: type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13190: elemDecl->namedTypeNs);
13191: if (type == NULL) {
13192: xmlSchemaPResCompAttrErr(ctxt,
13193: XML_SCHEMAP_SRC_RESOLVE,
13194: WXS_BASIC_CAST elemDecl, elemDecl->node,
13195: "type", elemDecl->namedType, elemDecl->namedTypeNs,
13196: XML_SCHEMA_TYPE_BASIC, "type definition");
13197: } else
13198: elemDecl->subtypes = type;
13199: }
13200: if (elemDecl->substGroup != NULL) {
13201: xmlSchemaElementPtr substHead;
13202:
13203: /*
13204: * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13205: * substitutionGroup?
13206: */
13207: substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13208: elemDecl->substGroupNs);
13209: if (substHead == NULL) {
13210: xmlSchemaPResCompAttrErr(ctxt,
13211: XML_SCHEMAP_SRC_RESOLVE,
13212: WXS_BASIC_CAST elemDecl, NULL,
13213: "substitutionGroup", elemDecl->substGroup,
13214: elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13215: } else {
13216: xmlSchemaResolveElementReferences(substHead, ctxt);
13217: /*
13218: * Set the "substitution group affiliation".
13219: * NOTE that now we use the "refDecl" field for this.
13220: */
13221: WXS_SUBST_HEAD(elemDecl) = substHead;
13222: /*
13223: * The type definitions is set to:
13224: * SPEC "...the {type definition} of the element
13225: * declaration �resolved� to by the �actual value�
13226: * of the substitutionGroup [attribute], if present"
13227: */
13228: if (elemDecl->subtypes == NULL)
13229: elemDecl->subtypes = substHead->subtypes;
13230: }
13231: }
13232: /*
13233: * SPEC "The definition of anyType serves as the default type definition
13234: * for element declarations whose XML representation does not specify one."
13235: */
13236: if ((elemDecl->subtypes == NULL) &&
13237: (elemDecl->namedType == NULL) &&
13238: (elemDecl->substGroup == NULL))
13239: elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13240: }
13241:
13242: /**
13243: * xmlSchemaResolveUnionMemberTypes:
13244: * @ctxt: the schema parser context
13245: * @type: the schema simple type definition
13246: *
13247: * Checks and builds the "member type definitions" property of the union
13248: * simple type. This handles part (1), part (2) is done in
13249: * xmlSchemaFinishMemberTypeDefinitionsProperty()
13250: *
13251: * Returns -1 in case of an internal error, 0 otherwise.
13252: */
13253: static int
13254: xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13255: xmlSchemaTypePtr type)
13256: {
13257:
13258: xmlSchemaTypeLinkPtr link, lastLink, newLink;
13259: xmlSchemaTypePtr memberType;
13260:
13261: /*
13262: * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13263: * define the explicit members as the type definitions �resolved�
13264: * to by the items in the �actual value� of the memberTypes [attribute],
13265: * if any, followed by the type definitions corresponding to the
13266: * <simpleType>s among the [children] of <union>, if any."
13267: */
13268: /*
13269: * Resolve references.
13270: */
13271: link = type->memberTypes;
13272: lastLink = NULL;
13273: while (link != NULL) {
13274: const xmlChar *name, *nsName;
13275:
13276: name = ((xmlSchemaQNameRefPtr) link->type)->name;
13277: nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13278:
13279: memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13280: if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13281: xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13282: WXS_BASIC_CAST type, type->node, "memberTypes",
13283: name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13284: /*
13285: * Remove the member type link.
13286: */
13287: if (lastLink == NULL)
13288: type->memberTypes = link->next;
13289: else
13290: lastLink->next = link->next;
13291: newLink = link;
13292: link = link->next;
13293: xmlFree(newLink);
13294: } else {
13295: link->type = memberType;
13296: lastLink = link;
13297: link = link->next;
13298: }
13299: }
13300: /*
13301: * Add local simple types,
13302: */
13303: memberType = type->subtypes;
13304: while (memberType != NULL) {
13305: link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13306: if (link == NULL) {
13307: xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13308: return (-1);
13309: }
13310: link->type = memberType;
13311: link->next = NULL;
13312: if (lastLink == NULL)
13313: type->memberTypes = link;
13314: else
13315: lastLink->next = link;
13316: lastLink = link;
13317: memberType = memberType->next;
13318: }
13319: return (0);
13320: }
13321:
13322: /**
13323: * xmlSchemaIsDerivedFromBuiltInType:
13324: * @ctxt: the schema parser context
13325: * @type: the type definition
13326: * @valType: the value type
13327: *
13328: *
13329: * Returns 1 if the type has the given value type, or
13330: * is derived from such a type.
13331: */
13332: static int
13333: xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13334: {
13335: if (type == NULL)
13336: return (0);
13337: if (WXS_IS_COMPLEX(type))
13338: return (0);
13339: if (type->type == XML_SCHEMA_TYPE_BASIC) {
13340: if (type->builtInType == valType)
13341: return(1);
13342: if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13343: (type->builtInType == XML_SCHEMAS_ANYTYPE))
13344: return (0);
13345: return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13346: }
13347: return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13348: }
13349:
13350: #if 0
13351: /**
13352: * xmlSchemaIsDerivedFromBuiltInType:
13353: * @ctxt: the schema parser context
13354: * @type: the type definition
13355: * @valType: the value type
13356: *
13357: *
13358: * Returns 1 if the type has the given value type, or
13359: * is derived from such a type.
13360: */
13361: static int
13362: xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13363: {
13364: if (type == NULL)
13365: return (0);
13366: if (WXS_IS_COMPLEX(type))
13367: return (0);
13368: if (type->type == XML_SCHEMA_TYPE_BASIC) {
13369: if (type->builtInType == valType)
13370: return(1);
13371: return (0);
13372: } else
13373: return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13374:
13375: return (0);
13376: }
13377:
13378: static xmlSchemaTypePtr
13379: xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13380: {
13381: if (type == NULL)
13382: return (NULL);
13383: if (WXS_IS_COMPLEX(type))
13384: return (NULL);
13385: if (type->type == XML_SCHEMA_TYPE_BASIC)
13386: return(type);
13387: return(xmlSchemaQueryBuiltInType(type->subtypes));
13388: }
13389: #endif
13390:
13391: /**
13392: * xmlSchemaGetPrimitiveType:
13393: * @type: the simpleType definition
13394: *
13395: * Returns the primitive type of the given type or
13396: * NULL in case of error.
13397: */
13398: static xmlSchemaTypePtr
13399: xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13400: {
13401:
13402: while (type != NULL) {
13403: /*
13404: * Note that anySimpleType is actually not a primitive type
13405: * but we need that here.
13406: */
13407: if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13408: (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13409: return (type);
13410: type = type->baseType;
13411: }
13412:
13413: return (NULL);
13414: }
13415:
13416: #if 0
13417: /**
13418: * xmlSchemaGetBuiltInTypeAncestor:
13419: * @type: the simpleType definition
13420: *
13421: * Returns the primitive type of the given type or
13422: * NULL in case of error.
13423: */
13424: static xmlSchemaTypePtr
13425: xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13426: {
13427: if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13428: return (0);
13429: while (type != NULL) {
13430: if (type->type == XML_SCHEMA_TYPE_BASIC)
13431: return (type);
13432: type = type->baseType;
13433: }
13434:
13435: return (NULL);
13436: }
13437: #endif
13438:
13439: /**
13440: * xmlSchemaCloneWildcardNsConstraints:
13441: * @ctxt: the schema parser context
13442: * @dest: the destination wildcard
13443: * @source: the source wildcard
13444: *
13445: * Clones the namespace constraints of source
13446: * and assignes them to dest.
13447: * Returns -1 on internal error, 0 otherwise.
13448: */
13449: static int
13450: xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13451: xmlSchemaWildcardPtr dest,
13452: xmlSchemaWildcardPtr source)
13453: {
13454: xmlSchemaWildcardNsPtr cur, tmp, last;
13455:
13456: if ((source == NULL) || (dest == NULL))
13457: return(-1);
13458: dest->any = source->any;
13459: cur = source->nsSet;
13460: last = NULL;
13461: while (cur != NULL) {
13462: tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13463: if (tmp == NULL)
13464: return(-1);
13465: tmp->value = cur->value;
13466: if (last == NULL)
13467: dest->nsSet = tmp;
13468: else
13469: last->next = tmp;
13470: last = tmp;
13471: cur = cur->next;
13472: }
13473: if (dest->negNsSet != NULL)
13474: xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13475: if (source->negNsSet != NULL) {
13476: dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13477: if (dest->negNsSet == NULL)
13478: return(-1);
13479: dest->negNsSet->value = source->negNsSet->value;
13480: } else
13481: dest->negNsSet = NULL;
13482: return(0);
13483: }
13484:
13485: /**
13486: * xmlSchemaUnionWildcards:
13487: * @ctxt: the schema parser context
13488: * @completeWild: the first wildcard
13489: * @curWild: the second wildcard
13490: *
13491: * Unions the namespace constraints of the given wildcards.
13492: * @completeWild will hold the resulting union.
13493: * Returns a positive error code on failure, -1 in case of an
13494: * internal error, 0 otherwise.
13495: */
13496: static int
13497: xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13498: xmlSchemaWildcardPtr completeWild,
13499: xmlSchemaWildcardPtr curWild)
13500: {
13501: xmlSchemaWildcardNsPtr cur, curB, tmp;
13502:
13503: /*
13504: * 1 If O1 and O2 are the same value, then that value must be the
13505: * value.
13506: */
13507: if ((completeWild->any == curWild->any) &&
13508: ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13509: ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13510:
13511: if ((completeWild->negNsSet == NULL) ||
13512: (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13513:
13514: if (completeWild->nsSet != NULL) {
13515: int found = 0;
13516:
13517: /*
13518: * Check equality of sets.
13519: */
13520: cur = completeWild->nsSet;
13521: while (cur != NULL) {
13522: found = 0;
13523: curB = curWild->nsSet;
13524: while (curB != NULL) {
13525: if (cur->value == curB->value) {
13526: found = 1;
13527: break;
13528: }
13529: curB = curB->next;
13530: }
13531: if (!found)
13532: break;
13533: cur = cur->next;
13534: }
13535: if (found)
13536: return(0);
13537: } else
13538: return(0);
13539: }
13540: }
13541: /*
13542: * 2 If either O1 or O2 is any, then any must be the value
13543: */
13544: if (completeWild->any != curWild->any) {
13545: if (completeWild->any == 0) {
13546: completeWild->any = 1;
13547: if (completeWild->nsSet != NULL) {
13548: xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13549: completeWild->nsSet = NULL;
13550: }
13551: if (completeWild->negNsSet != NULL) {
13552: xmlFree(completeWild->negNsSet);
13553: completeWild->negNsSet = NULL;
13554: }
13555: }
13556: return (0);
13557: }
13558: /*
13559: * 3 If both O1 and O2 are sets of (namespace names or �absent�),
13560: * then the union of those sets must be the value.
13561: */
13562: if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13563: int found;
13564: xmlSchemaWildcardNsPtr start;
13565:
13566: cur = curWild->nsSet;
13567: start = completeWild->nsSet;
13568: while (cur != NULL) {
13569: found = 0;
13570: curB = start;
13571: while (curB != NULL) {
13572: if (cur->value == curB->value) {
13573: found = 1;
13574: break;
13575: }
13576: curB = curB->next;
13577: }
13578: if (!found) {
13579: tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13580: if (tmp == NULL)
13581: return (-1);
13582: tmp->value = cur->value;
13583: tmp->next = completeWild->nsSet;
13584: completeWild->nsSet = tmp;
13585: }
13586: cur = cur->next;
13587: }
13588:
13589: return(0);
13590: }
13591: /*
13592: * 4 If the two are negations of different values (namespace names
13593: * or �absent�), then a pair of not and �absent� must be the value.
13594: */
13595: if ((completeWild->negNsSet != NULL) &&
13596: (curWild->negNsSet != NULL) &&
13597: (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13598: completeWild->negNsSet->value = NULL;
13599:
13600: return(0);
13601: }
13602: /*
13603: * 5.
13604: */
13605: if (((completeWild->negNsSet != NULL) &&
13606: (completeWild->negNsSet->value != NULL) &&
13607: (curWild->nsSet != NULL)) ||
13608: ((curWild->negNsSet != NULL) &&
13609: (curWild->negNsSet->value != NULL) &&
13610: (completeWild->nsSet != NULL))) {
13611:
13612: int nsFound, absentFound = 0;
13613:
13614: if (completeWild->nsSet != NULL) {
13615: cur = completeWild->nsSet;
13616: curB = curWild->negNsSet;
13617: } else {
13618: cur = curWild->nsSet;
13619: curB = completeWild->negNsSet;
13620: }
13621: nsFound = 0;
13622: while (cur != NULL) {
13623: if (cur->value == NULL)
13624: absentFound = 1;
13625: else if (cur->value == curB->value)
13626: nsFound = 1;
13627: if (nsFound && absentFound)
13628: break;
13629: cur = cur->next;
13630: }
13631:
13632: if (nsFound && absentFound) {
13633: /*
13634: * 5.1 If the set S includes both the negated namespace
13635: * name and �absent�, then any must be the value.
13636: */
13637: completeWild->any = 1;
13638: if (completeWild->nsSet != NULL) {
13639: xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13640: completeWild->nsSet = NULL;
13641: }
13642: if (completeWild->negNsSet != NULL) {
13643: xmlFree(completeWild->negNsSet);
13644: completeWild->negNsSet = NULL;
13645: }
13646: } else if (nsFound && (!absentFound)) {
13647: /*
13648: * 5.2 If the set S includes the negated namespace name
13649: * but not �absent�, then a pair of not and �absent� must
13650: * be the value.
13651: */
13652: if (completeWild->nsSet != NULL) {
13653: xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13654: completeWild->nsSet = NULL;
13655: }
13656: if (completeWild->negNsSet == NULL) {
13657: completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13658: if (completeWild->negNsSet == NULL)
13659: return (-1);
13660: }
13661: completeWild->negNsSet->value = NULL;
13662: } else if ((!nsFound) && absentFound) {
13663: /*
13664: * 5.3 If the set S includes �absent� but not the negated
13665: * namespace name, then the union is not expressible.
13666: */
13667: xmlSchemaPErr(ctxt, completeWild->node,
13668: XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13669: "The union of the wilcard is not expressible.\n",
13670: NULL, NULL);
13671: return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13672: } else if ((!nsFound) && (!absentFound)) {
13673: /*
13674: * 5.4 If the set S does not include either the negated namespace
13675: * name or �absent�, then whichever of O1 or O2 is a pair of not
13676: * and a namespace name must be the value.
13677: */
13678: if (completeWild->negNsSet == NULL) {
13679: if (completeWild->nsSet != NULL) {
13680: xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13681: completeWild->nsSet = NULL;
13682: }
13683: completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13684: if (completeWild->negNsSet == NULL)
13685: return (-1);
13686: completeWild->negNsSet->value = curWild->negNsSet->value;
13687: }
13688: }
13689: return (0);
13690: }
13691: /*
13692: * 6.
13693: */
13694: if (((completeWild->negNsSet != NULL) &&
13695: (completeWild->negNsSet->value == NULL) &&
13696: (curWild->nsSet != NULL)) ||
13697: ((curWild->negNsSet != NULL) &&
13698: (curWild->negNsSet->value == NULL) &&
13699: (completeWild->nsSet != NULL))) {
13700:
13701: if (completeWild->nsSet != NULL) {
13702: cur = completeWild->nsSet;
13703: } else {
13704: cur = curWild->nsSet;
13705: }
13706: while (cur != NULL) {
13707: if (cur->value == NULL) {
13708: /*
13709: * 6.1 If the set S includes �absent�, then any must be the
13710: * value.
13711: */
13712: completeWild->any = 1;
13713: if (completeWild->nsSet != NULL) {
13714: xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13715: completeWild->nsSet = NULL;
13716: }
13717: if (completeWild->negNsSet != NULL) {
13718: xmlFree(completeWild->negNsSet);
13719: completeWild->negNsSet = NULL;
13720: }
13721: return (0);
13722: }
13723: cur = cur->next;
13724: }
13725: if (completeWild->negNsSet == NULL) {
13726: /*
13727: * 6.2 If the set S does not include �absent�, then a pair of not
13728: * and �absent� must be the value.
13729: */
13730: if (completeWild->nsSet != NULL) {
13731: xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13732: completeWild->nsSet = NULL;
13733: }
13734: completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13735: if (completeWild->negNsSet == NULL)
13736: return (-1);
13737: completeWild->negNsSet->value = NULL;
13738: }
13739: return (0);
13740: }
13741: return (0);
13742:
13743: }
13744:
13745: /**
13746: * xmlSchemaIntersectWildcards:
13747: * @ctxt: the schema parser context
13748: * @completeWild: the first wildcard
13749: * @curWild: the second wildcard
13750: *
13751: * Intersects the namespace constraints of the given wildcards.
13752: * @completeWild will hold the resulting intersection.
13753: * Returns a positive error code on failure, -1 in case of an
13754: * internal error, 0 otherwise.
13755: */
13756: static int
13757: xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13758: xmlSchemaWildcardPtr completeWild,
13759: xmlSchemaWildcardPtr curWild)
13760: {
13761: xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
13762:
13763: /*
13764: * 1 If O1 and O2 are the same value, then that value must be the
13765: * value.
13766: */
13767: if ((completeWild->any == curWild->any) &&
13768: ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13769: ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13770:
13771: if ((completeWild->negNsSet == NULL) ||
13772: (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13773:
13774: if (completeWild->nsSet != NULL) {
13775: int found = 0;
13776:
13777: /*
13778: * Check equality of sets.
13779: */
13780: cur = completeWild->nsSet;
13781: while (cur != NULL) {
13782: found = 0;
13783: curB = curWild->nsSet;
13784: while (curB != NULL) {
13785: if (cur->value == curB->value) {
13786: found = 1;
13787: break;
13788: }
13789: curB = curB->next;
13790: }
13791: if (!found)
13792: break;
13793: cur = cur->next;
13794: }
13795: if (found)
13796: return(0);
13797: } else
13798: return(0);
13799: }
13800: }
13801: /*
13802: * 2 If either O1 or O2 is any, then the other must be the value.
13803: */
13804: if ((completeWild->any != curWild->any) && (completeWild->any)) {
13805: if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13806: return(-1);
13807: return(0);
13808: }
13809: /*
13810: * 3 If either O1 or O2 is a pair of not and a value (a namespace
13811: * name or �absent�) and the other is a set of (namespace names or
13812: * �absent�), then that set, minus the negated value if it was in
13813: * the set, minus �absent� if it was in the set, must be the value.
13814: */
13815: if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13816: ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13817: const xmlChar *neg;
13818:
13819: if (completeWild->nsSet == NULL) {
13820: neg = completeWild->negNsSet->value;
13821: if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13822: return(-1);
13823: } else
13824: neg = curWild->negNsSet->value;
13825: /*
13826: * Remove absent and negated.
13827: */
13828: prev = NULL;
13829: cur = completeWild->nsSet;
13830: while (cur != NULL) {
13831: if (cur->value == NULL) {
13832: if (prev == NULL)
13833: completeWild->nsSet = cur->next;
13834: else
13835: prev->next = cur->next;
13836: xmlFree(cur);
13837: break;
13838: }
13839: prev = cur;
13840: cur = cur->next;
13841: }
13842: if (neg != NULL) {
13843: prev = NULL;
13844: cur = completeWild->nsSet;
13845: while (cur != NULL) {
13846: if (cur->value == neg) {
13847: if (prev == NULL)
13848: completeWild->nsSet = cur->next;
13849: else
13850: prev->next = cur->next;
13851: xmlFree(cur);
13852: break;
13853: }
13854: prev = cur;
13855: cur = cur->next;
13856: }
13857: }
13858:
13859: return(0);
13860: }
13861: /*
13862: * 4 If both O1 and O2 are sets of (namespace names or �absent�),
13863: * then the intersection of those sets must be the value.
13864: */
13865: if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13866: int found;
13867:
13868: cur = completeWild->nsSet;
13869: prev = NULL;
13870: while (cur != NULL) {
13871: found = 0;
13872: curB = curWild->nsSet;
13873: while (curB != NULL) {
13874: if (cur->value == curB->value) {
13875: found = 1;
13876: break;
13877: }
13878: curB = curB->next;
13879: }
13880: if (!found) {
13881: if (prev == NULL)
13882: completeWild->nsSet = cur->next;
13883: else
13884: prev->next = cur->next;
13885: tmp = cur->next;
13886: xmlFree(cur);
13887: cur = tmp;
13888: continue;
13889: }
13890: prev = cur;
13891: cur = cur->next;
13892: }
13893:
13894: return(0);
13895: }
13896: /* 5 If the two are negations of different namespace names,
13897: * then the intersection is not expressible
13898: */
13899: if ((completeWild->negNsSet != NULL) &&
13900: (curWild->negNsSet != NULL) &&
13901: (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13902: (completeWild->negNsSet->value != NULL) &&
13903: (curWild->negNsSet->value != NULL)) {
13904:
13905: xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13906: "The intersection of the wilcard is not expressible.\n",
13907: NULL, NULL);
13908: return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13909: }
13910: /*
13911: * 6 If the one is a negation of a namespace name and the other
13912: * is a negation of �absent�, then the one which is the negation
13913: * of a namespace name must be the value.
13914: */
13915: if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13916: (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13917: (completeWild->negNsSet->value == NULL)) {
13918: completeWild->negNsSet->value = curWild->negNsSet->value;
13919: }
13920: return(0);
13921: }
13922:
13923: /**
13924: * xmlSchemaIsWildcardNsConstraintSubset:
13925: * @ctxt: the schema parser context
13926: * @sub: the first wildcard
13927: * @super: the second wildcard
13928: *
13929: * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13930: *
13931: * Returns 0 if the namespace constraint of @sub is an intensional
13932: * subset of @super, 1 otherwise.
13933: */
13934: static int
13935: xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13936: xmlSchemaWildcardPtr super)
13937: {
13938: /*
13939: * 1 super must be any.
13940: */
13941: if (super->any)
13942: return (0);
13943: /*
13944: * 2.1 sub must be a pair of not and a namespace name or �absent�.
13945: * 2.2 super must be a pair of not and the same value.
13946: */
13947: if ((sub->negNsSet != NULL) &&
13948: (super->negNsSet != NULL) &&
1.1.1.2 ! misho 13949: (sub->negNsSet->value == super->negNsSet->value))
1.1 misho 13950: return (0);
13951: /*
13952: * 3.1 sub must be a set whose members are either namespace names or �absent�.
13953: */
13954: if (sub->nsSet != NULL) {
13955: /*
13956: * 3.2.1 super must be the same set or a superset thereof.
13957: */
13958: if (super->nsSet != NULL) {
13959: xmlSchemaWildcardNsPtr cur, curB;
13960: int found = 0;
13961:
13962: cur = sub->nsSet;
13963: while (cur != NULL) {
13964: found = 0;
13965: curB = super->nsSet;
13966: while (curB != NULL) {
13967: if (cur->value == curB->value) {
13968: found = 1;
13969: break;
13970: }
13971: curB = curB->next;
13972: }
13973: if (!found)
13974: return (1);
13975: cur = cur->next;
13976: }
13977: if (found)
13978: return (0);
13979: } else if (super->negNsSet != NULL) {
13980: xmlSchemaWildcardNsPtr cur;
13981: /*
13982: * 3.2.2 super must be a pair of not and a namespace name or
13983: * �absent� and that value must not be in sub's set.
13984: */
13985: cur = sub->nsSet;
13986: while (cur != NULL) {
13987: if (cur->value == super->negNsSet->value)
13988: return (1);
13989: cur = cur->next;
13990: }
13991: return (0);
13992: }
13993: }
13994: return (1);
13995: }
13996:
13997: static int
13998: xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13999: int *fixed,
14000: const xmlChar **value,
14001: xmlSchemaValPtr *val)
14002: {
14003: *fixed = 0;
14004: *value = NULL;
14005: if (val != 0)
14006: *val = NULL;
14007:
14008: if (attruse->defValue != NULL) {
14009: *value = attruse->defValue;
14010: if (val != NULL)
14011: *val = attruse->defVal;
14012: if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14013: *fixed = 1;
14014: return(1);
14015: } else if ((attruse->attrDecl != NULL) &&
14016: (attruse->attrDecl->defValue != NULL)) {
14017: *value = attruse->attrDecl->defValue;
14018: if (val != NULL)
14019: *val = attruse->attrDecl->defVal;
14020: if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14021: *fixed = 1;
14022: return(1);
14023: }
14024: return(0);
14025: }
14026: /**
14027: * xmlSchemaCheckCVCWildcardNamespace:
14028: * @wild: the wildcard
14029: * @ns: the namespace
14030: *
14031: * Validation Rule: Wildcard allows Namespace Name
14032: * (cvc-wildcard-namespace)
14033: *
14034: * Returns 0 if the given namespace matches the wildcard,
14035: * 1 otherwise and -1 on API errors.
14036: */
14037: static int
14038: xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14039: const xmlChar* ns)
14040: {
14041: if (wild == NULL)
14042: return(-1);
14043:
14044: if (wild->any)
14045: return(0);
14046: else if (wild->nsSet != NULL) {
14047: xmlSchemaWildcardNsPtr cur;
14048:
14049: cur = wild->nsSet;
14050: while (cur != NULL) {
14051: if (xmlStrEqual(cur->value, ns))
14052: return(0);
14053: cur = cur->next;
14054: }
14055: } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14056: (!xmlStrEqual(wild->negNsSet->value, ns)))
14057: return(0);
14058:
14059: return(1);
14060: }
14061:
14062: #define XML_SCHEMA_ACTION_DERIVE 0
14063: #define XML_SCHEMA_ACTION_REDEFINE 1
14064:
14065: #define WXS_ACTION_STR(a) \
14066: ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14067:
14068: /*
14069: * Schema Component Constraint:
14070: * Derivation Valid (Restriction, Complex)
14071: * derivation-ok-restriction (2) - (4)
14072: *
14073: * ATTENTION:
14074: * In XML Schema 1.1 this will be:
14075: * Validation Rule:
14076: * Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14077: *
14078: */
14079: static int
14080: xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14081: int action,
14082: xmlSchemaBasicItemPtr item,
14083: xmlSchemaBasicItemPtr baseItem,
14084: xmlSchemaItemListPtr uses,
14085: xmlSchemaItemListPtr baseUses,
14086: xmlSchemaWildcardPtr wild,
14087: xmlSchemaWildcardPtr baseWild)
14088: {
14089: xmlSchemaAttributeUsePtr cur = NULL, bcur;
14090: int i, j, found; /* err = 0; */
14091: const xmlChar *bEffValue;
14092: int effFixed;
14093:
14094: if (uses != NULL) {
14095: for (i = 0; i < uses->nbItems; i++) {
14096: cur = uses->items[i];
14097: found = 0;
14098: if (baseUses == NULL)
14099: goto not_found;
14100: for (j = 0; j < baseUses->nbItems; j++) {
14101: bcur = baseUses->items[j];
14102: if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14103: WXS_ATTRUSE_DECL_NAME(bcur)) &&
14104: (WXS_ATTRUSE_DECL_TNS(cur) ==
14105: WXS_ATTRUSE_DECL_TNS(bcur)))
14106: {
14107: /*
14108: * (2.1) "If there is an attribute use in the {attribute
14109: * uses} of the {base type definition} (call this B) whose
14110: * {attribute declaration} has the same {name} and {target
14111: * namespace}, then all of the following must be true:"
14112: */
14113: found = 1;
14114:
14115: if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14116: (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14117: {
14118: xmlChar *str = NULL;
14119: /*
14120: * (2.1.1) "one of the following must be true:"
14121: * (2.1.1.1) "B's {required} is false."
14122: * (2.1.1.2) "R's {required} is true."
14123: */
14124: xmlSchemaPAttrUseErr4(pctxt,
14125: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14126: WXS_ITEM_NODE(item), item, cur,
14127: "The 'optional' attribute use is inconsistent "
14128: "with the corresponding 'required' attribute use of "
14129: "the %s %s",
14130: WXS_ACTION_STR(action),
14131: xmlSchemaGetComponentDesignation(&str, baseItem),
14132: NULL, NULL);
14133: FREE_AND_NULL(str);
14134: /* err = pctxt->err; */
14135: } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14136: WXS_ATTRUSE_TYPEDEF(cur),
14137: WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14138: {
14139: xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14140:
14141: /*
14142: * SPEC (2.1.2) "R's {attribute declaration}'s
14143: * {type definition} must be validly derived from
14144: * B's {type definition} given the empty set as
14145: * defined in Type Derivation OK (Simple) (�3.14.6)."
14146: */
14147: xmlSchemaPAttrUseErr4(pctxt,
14148: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14149: WXS_ITEM_NODE(item), item, cur,
14150: "The attribute declaration's %s "
14151: "is not validly derived from "
14152: "the corresponding %s of the "
14153: "attribute declaration in the %s %s",
14154: xmlSchemaGetComponentDesignation(&strA,
14155: WXS_ATTRUSE_TYPEDEF(cur)),
14156: xmlSchemaGetComponentDesignation(&strB,
14157: WXS_ATTRUSE_TYPEDEF(bcur)),
14158: WXS_ACTION_STR(action),
14159: xmlSchemaGetComponentDesignation(&strC, baseItem));
14160: /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14161: FREE_AND_NULL(strA);
14162: FREE_AND_NULL(strB);
14163: FREE_AND_NULL(strC);
14164: /* err = pctxt->err; */
14165: } else {
14166: /*
14167: * 2.1.3 [Definition:] Let the effective value
14168: * constraint of an attribute use be its {value
14169: * constraint}, if present, otherwise its {attribute
14170: * declaration}'s {value constraint} .
14171: */
14172: xmlSchemaGetEffectiveValueConstraint(bcur,
14173: &effFixed, &bEffValue, NULL);
14174: /*
14175: * 2.1.3 ... one of the following must be true
14176: *
14177: * 2.1.3.1 B's �effective value constraint� is
14178: * �absent� or default.
14179: */
14180: if ((bEffValue != NULL) &&
14181: (effFixed == 1)) {
14182: const xmlChar *rEffValue = NULL;
14183:
14184: xmlSchemaGetEffectiveValueConstraint(bcur,
14185: &effFixed, &rEffValue, NULL);
14186: /*
14187: * 2.1.3.2 R's �effective value constraint� is
14188: * fixed with the same string as B's.
14189: * MAYBE TODO: Compare the computed values.
14190: * Hmm, it says "same string" so
14191: * string-equality might really be sufficient.
14192: */
14193: if ((effFixed == 0) ||
14194: (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14195: {
14196: xmlChar *str = NULL;
14197:
14198: xmlSchemaPAttrUseErr4(pctxt,
14199: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14200: WXS_ITEM_NODE(item), item, cur,
14201: "The effective value constraint of the "
14202: "attribute use is inconsistent with "
14203: "its correspondent in the %s %s",
14204: WXS_ACTION_STR(action),
14205: xmlSchemaGetComponentDesignation(&str,
14206: baseItem),
14207: NULL, NULL);
14208: FREE_AND_NULL(str);
14209: /* err = pctxt->err; */
14210: }
14211: }
14212: }
14213: break;
14214: }
14215: }
14216: not_found:
14217: if (!found) {
14218: /*
14219: * (2.2) "otherwise the {base type definition} must have an
14220: * {attribute wildcard} and the {target namespace} of the
14221: * R's {attribute declaration} must be �valid� with respect
14222: * to that wildcard, as defined in Wildcard allows Namespace
14223: * Name (�3.10.4)."
14224: */
14225: if ((baseWild == NULL) ||
14226: (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14227: (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14228: {
14229: xmlChar *str = NULL;
14230:
14231: xmlSchemaPAttrUseErr4(pctxt,
14232: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14233: WXS_ITEM_NODE(item), item, cur,
14234: "Neither a matching attribute use, "
14235: "nor a matching wildcard exists in the %s %s",
14236: WXS_ACTION_STR(action),
14237: xmlSchemaGetComponentDesignation(&str, baseItem),
14238: NULL, NULL);
14239: FREE_AND_NULL(str);
14240: /* err = pctxt->err; */
14241: }
14242: }
14243: }
14244: }
14245: /*
14246: * SPEC derivation-ok-restriction (3):
14247: * (3) "For each attribute use in the {attribute uses} of the {base type
14248: * definition} whose {required} is true, there must be an attribute
14249: * use with an {attribute declaration} with the same {name} and
14250: * {target namespace} as its {attribute declaration} in the {attribute
14251: * uses} of the complex type definition itself whose {required} is true.
14252: */
14253: if (baseUses != NULL) {
14254: for (j = 0; j < baseUses->nbItems; j++) {
14255: bcur = baseUses->items[j];
14256: if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14257: continue;
14258: found = 0;
14259: if (uses != NULL) {
14260: for (i = 0; i < uses->nbItems; i++) {
14261: cur = uses->items[i];
14262: if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14263: WXS_ATTRUSE_DECL_NAME(bcur)) &&
14264: (WXS_ATTRUSE_DECL_TNS(cur) ==
14265: WXS_ATTRUSE_DECL_TNS(bcur))) {
14266: found = 1;
14267: break;
14268: }
14269: }
14270: }
14271: if (!found) {
14272: xmlChar *strA = NULL, *strB = NULL;
14273:
14274: xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14275: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14276: NULL, item,
14277: "A matching attribute use for the "
14278: "'required' %s of the %s %s is missing",
14279: xmlSchemaGetComponentDesignation(&strA, bcur),
14280: WXS_ACTION_STR(action),
14281: xmlSchemaGetComponentDesignation(&strB, baseItem),
14282: NULL);
14283: FREE_AND_NULL(strA);
14284: FREE_AND_NULL(strB);
14285: }
14286: }
14287: }
14288: /*
14289: * derivation-ok-restriction (4)
14290: */
14291: if (wild != NULL) {
14292: /*
14293: * (4) "If there is an {attribute wildcard}, all of the
14294: * following must be true:"
14295: */
14296: if (baseWild == NULL) {
14297: xmlChar *str = NULL;
14298:
14299: /*
14300: * (4.1) "The {base type definition} must also have one."
14301: */
14302: xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14303: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14304: NULL, item,
14305: "The %s has an attribute wildcard, "
14306: "but the %s %s '%s' does not have one",
14307: WXS_ITEM_TYPE_NAME(item),
14308: WXS_ACTION_STR(action),
14309: WXS_ITEM_TYPE_NAME(baseItem),
14310: xmlSchemaGetComponentQName(&str, baseItem));
14311: FREE_AND_NULL(str);
14312: return(pctxt->err);
14313: } else if ((baseWild->any == 0) &&
14314: xmlSchemaCheckCOSNSSubset(wild, baseWild))
14315: {
14316: xmlChar *str = NULL;
14317: /*
14318: * (4.2) "The complex type definition's {attribute wildcard}'s
14319: * {namespace constraint} must be a subset of the {base type
14320: * definition}'s {attribute wildcard}'s {namespace constraint},
14321: * as defined by Wildcard Subset (�3.10.6)."
14322: */
14323: xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14324: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14325: NULL, item,
14326: "The attribute wildcard is not a valid "
14327: "subset of the wildcard in the %s %s '%s'",
14328: WXS_ACTION_STR(action),
14329: WXS_ITEM_TYPE_NAME(baseItem),
14330: xmlSchemaGetComponentQName(&str, baseItem),
14331: NULL);
14332: FREE_AND_NULL(str);
14333: return(pctxt->err);
14334: }
14335: /* 4.3 Unless the {base type definition} is the �ur-type
14336: * definition�, the complex type definition's {attribute
14337: * wildcard}'s {process contents} must be identical to or
14338: * stronger than the {base type definition}'s {attribute
14339: * wildcard}'s {process contents}, where strict is stronger
14340: * than lax is stronger than skip.
14341: */
14342: if ((! WXS_IS_ANYTYPE(baseItem)) &&
14343: (wild->processContents < baseWild->processContents)) {
14344: xmlChar *str = NULL;
14345: xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14346: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14347: NULL, baseItem,
14348: "The {process contents} of the attribute wildcard is "
14349: "weaker than the one in the %s %s '%s'",
14350: WXS_ACTION_STR(action),
14351: WXS_ITEM_TYPE_NAME(baseItem),
14352: xmlSchemaGetComponentQName(&str, baseItem),
14353: NULL);
14354: FREE_AND_NULL(str)
14355: return(pctxt->err);
14356: }
14357: }
14358: return(0);
14359: }
14360:
14361:
14362: static int
14363: xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14364: xmlSchemaBasicItemPtr item,
14365: xmlSchemaWildcardPtr *completeWild,
14366: xmlSchemaItemListPtr list,
14367: xmlSchemaItemListPtr prohibs);
14368: /**
14369: * xmlSchemaFixupTypeAttributeUses:
14370: * @ctxt: the schema parser context
14371: * @type: the complex type definition
14372: *
14373: *
14374: * Builds the wildcard and the attribute uses on the given complex type.
14375: * Returns -1 if an internal error occurs, 0 otherwise.
14376: *
14377: * ATTENTION TODO: Experimantally this uses pointer comparisons for
14378: * strings, so recheck this if we start to hardcode some schemata, since
14379: * they might not be in the same dict.
14380: * NOTE: It is allowed to "extend" the xs:anyType type.
14381: */
14382: static int
14383: xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14384: xmlSchemaTypePtr type)
14385: {
14386: xmlSchemaTypePtr baseType = NULL;
14387: xmlSchemaAttributeUsePtr use;
14388: xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14389:
14390: if (type->baseType == NULL) {
14391: PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14392: "no base type");
14393: return (-1);
14394: }
14395: baseType = type->baseType;
14396: if (WXS_IS_TYPE_NOT_FIXED(baseType))
14397: if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14398: return(-1);
14399:
14400: uses = type->attrUses;
14401: baseUses = baseType->attrUses;
14402: /*
14403: * Expand attribute group references. And build the 'complete'
14404: * wildcard, i.e. intersect multiple wildcards.
14405: * Move attribute prohibitions into a separate list.
14406: */
14407: if (uses != NULL) {
14408: if (WXS_IS_RESTRICTION(type)) {
14409: /*
14410: * This one will transfer all attr. prohibitions
14411: * into pctxt->attrProhibs.
14412: */
14413: if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14414: WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14415: pctxt->attrProhibs) == -1)
14416: {
14417: PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14418: "failed to expand attributes");
14419: }
14420: if (pctxt->attrProhibs->nbItems != 0)
14421: prohibs = pctxt->attrProhibs;
14422: } else {
14423: if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14424: WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14425: NULL) == -1)
14426: {
14427: PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14428: "failed to expand attributes");
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 containt 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: /**
14611: * xmlSchemaGetParticleTotalRangeMin:
14612: * @particle: the particle
14613: *
14614: * Schema Component Constraint: Effective Total Range
14615: * (all and sequence) + (choice)
14616: *
14617: * Returns the minimun Effective Total Range.
14618: */
14619: static int
14620: xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14621: {
14622: if ((particle->children == NULL) ||
14623: (particle->minOccurs == 0))
14624: return (0);
14625: if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14626: int min = -1, cur;
14627: xmlSchemaParticlePtr part =
14628: (xmlSchemaParticlePtr) particle->children->children;
14629:
14630: if (part == NULL)
14631: return (0);
14632: while (part != NULL) {
14633: if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14634: (part->children->type == XML_SCHEMA_TYPE_ANY))
14635: cur = part->minOccurs;
14636: else
14637: cur = xmlSchemaGetParticleTotalRangeMin(part);
14638: if (cur == 0)
14639: return (0);
14640: if ((min > cur) || (min == -1))
14641: min = cur;
14642: part = (xmlSchemaParticlePtr) part->next;
14643: }
14644: return (particle->minOccurs * min);
14645: } else {
14646: /* <all> and <sequence> */
14647: int sum = 0;
14648: xmlSchemaParticlePtr part =
14649: (xmlSchemaParticlePtr) particle->children->children;
14650:
14651: if (part == NULL)
14652: return (0);
14653: do {
14654: if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14655: (part->children->type == XML_SCHEMA_TYPE_ANY))
14656: sum += part->minOccurs;
14657: else
14658: sum += xmlSchemaGetParticleTotalRangeMin(part);
14659: part = (xmlSchemaParticlePtr) part->next;
14660: } while (part != NULL);
14661: return (particle->minOccurs * sum);
14662: }
14663: }
14664:
14665: #if 0
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: * xmlSchemaIsParticleEmptiable:
14729: * @particle: the particle
14730: *
14731: * Schema Component Constraint: Particle Emptiable
14732: * Checks whether the given particle is emptiable.
14733: *
14734: * Returns 1 if emptiable, 0 otherwise.
14735: */
14736: static int
14737: xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14738: {
14739: /*
14740: * SPEC (1) "Its {min occurs} is 0."
14741: */
14742: if ((particle == NULL) || (particle->minOccurs == 0) ||
14743: (particle->children == NULL))
14744: return (1);
14745: /*
14746: * SPEC (2) "Its {term} is a group and the minimum part of the
14747: * effective total range of that group, [...] is 0."
14748: */
14749: if (WXS_IS_MODEL_GROUP(particle->children)) {
14750: if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14751: return (1);
14752: }
14753: return (0);
14754: }
14755:
14756: /**
14757: * xmlSchemaCheckCOSSTDerivedOK:
14758: * @actxt: a context
14759: * @type: the derived simple type definition
14760: * @baseType: the base type definition
14761: * @subset: the subset of ('restriction', ect.)
14762: *
14763: * Schema Component Constraint:
14764: * Type Derivation OK (Simple) (cos-st-derived-OK)
14765: *
14766: * Checks wheter @type can be validly
14767: * derived from @baseType.
14768: *
14769: * Returns 0 on success, an positive error code otherwise.
14770: */
14771: static int
14772: xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14773: xmlSchemaTypePtr type,
14774: xmlSchemaTypePtr baseType,
14775: int subset)
14776: {
14777: /*
14778: * 1 They are the same type definition.
14779: * TODO: The identy check might have to be more complex than this.
14780: */
14781: if (type == baseType)
14782: return (0);
14783: /*
14784: * 2.1 restriction is not in the subset, or in the {final}
14785: * of its own {base type definition};
14786: *
14787: * NOTE that this will be used also via "xsi:type".
14788: *
14789: * TODO: Revise this, it looks strange. How can the "type"
14790: * not be fixed or *in* fixing?
14791: */
14792: if (WXS_IS_TYPE_NOT_FIXED(type))
14793: if (xmlSchemaTypeFixup(type, actxt) == -1)
14794: return(-1);
14795: if (WXS_IS_TYPE_NOT_FIXED(baseType))
14796: if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14797: return(-1);
14798: if ((subset & SUBSET_RESTRICTION) ||
14799: (xmlSchemaTypeFinalContains(type->baseType,
14800: XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14801: return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14802: }
14803: /* 2.2 */
14804: if (type->baseType == baseType) {
14805: /*
14806: * 2.2.1 D's �base type definition� is B.
14807: */
14808: return (0);
14809: }
14810: /*
14811: * 2.2.2 D's �base type definition� is not the �ur-type definition�
14812: * and is validly derived from B given the subset, as defined by this
14813: * constraint.
14814: */
14815: if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14816: (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14817: baseType, subset) == 0)) {
14818: return (0);
14819: }
14820: /*
14821: * 2.2.3 D's {variety} is list or union and B is the �simple ur-type
14822: * definition�.
14823: */
14824: if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14825: (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14826: return (0);
14827: }
14828: /*
14829: * 2.2.4 B's {variety} is union and D is validly derived from a type
14830: * definition in B's {member type definitions} given the subset, as
14831: * defined by this constraint.
14832: *
14833: * NOTE: This seems not to involve built-in types, since there is no
14834: * built-in Union Simple Type.
14835: */
14836: if (WXS_IS_UNION(baseType)) {
14837: xmlSchemaTypeLinkPtr cur;
14838:
14839: cur = baseType->memberTypes;
14840: while (cur != NULL) {
14841: if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14842: if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14843: return(-1);
14844: if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14845: type, cur->type, subset) == 0)
14846: {
14847: /*
14848: * It just has to be validly derived from at least one
14849: * member-type.
14850: */
14851: return (0);
14852: }
14853: cur = cur->next;
14854: }
14855: }
14856: return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14857: }
14858:
14859: /**
14860: * xmlSchemaCheckTypeDefCircularInternal:
14861: * @pctxt: the schema parser context
14862: * @ctxtType: the type definition
14863: * @ancestor: an ancestor of @ctxtType
14864: *
14865: * Checks st-props-correct (2) + ct-props-correct (3).
14866: * Circular type definitions are not allowed.
14867: *
14868: * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14869: * circular, 0 otherwise.
14870: */
14871: static int
14872: xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14873: xmlSchemaTypePtr ctxtType,
14874: xmlSchemaTypePtr ancestor)
14875: {
14876: int ret;
14877:
14878: if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14879: return (0);
14880:
14881: if (ctxtType == ancestor) {
14882: xmlSchemaPCustomErr(pctxt,
14883: XML_SCHEMAP_ST_PROPS_CORRECT_2,
14884: WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14885: "The definition is circular", NULL);
14886: return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14887: }
14888: if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14889: /*
14890: * Avoid inifinite recursion on circular types not yet checked.
14891: */
14892: return (0);
14893: }
14894: ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14895: ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14896: ancestor->baseType);
14897: ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14898: return (ret);
14899: }
14900:
14901: /**
14902: * xmlSchemaCheckTypeDefCircular:
14903: * @item: the complex/simple type definition
14904: * @ctxt: the parser context
14905: * @name: the name
14906: *
14907: * Checks for circular type definitions.
14908: */
14909: static void
14910: xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14911: xmlSchemaParserCtxtPtr ctxt)
14912: {
14913: if ((item == NULL) ||
14914: (item->type == XML_SCHEMA_TYPE_BASIC) ||
14915: (item->baseType == NULL))
14916: return;
14917: xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14918: item->baseType);
14919: }
14920:
14921: /*
14922: * Simple Type Definition Representation OK (src-simple-type) 4
14923: *
14924: * "4 Circular union type definition is disallowed. That is, if the
14925: * <union> alternative is chosen, there must not be any entries in the
14926: * memberTypes [attribute] at any depth which resolve to the component
14927: * corresponding to the <simpleType>."
14928: *
14929: * Note that this should work on the *representation* of a component,
14930: * thus assumes any union types in the member types not being yet
14931: * substituted. At this stage we need the variety of the types
14932: * to be already computed.
14933: */
14934: static int
14935: xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14936: xmlSchemaTypePtr ctxType,
14937: xmlSchemaTypeLinkPtr members)
14938: {
14939: xmlSchemaTypeLinkPtr member;
14940: xmlSchemaTypePtr memberType;
14941:
14942: member = members;
14943: while (member != NULL) {
14944: memberType = member->type;
14945: while ((memberType != NULL) &&
14946: (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14947: if (memberType == ctxType) {
14948: xmlSchemaPCustomErr(pctxt,
14949: XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14950: WXS_BASIC_CAST ctxType, NULL,
14951: "The union type definition is circular", NULL);
14952: return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14953: }
14954: if ((WXS_IS_UNION(memberType)) &&
14955: ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14956: {
14957: int res;
14958: memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14959: res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14960: ctxType,
14961: xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14962: memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14963: if (res != 0)
14964: return(res);
14965: }
14966: memberType = memberType->baseType;
14967: }
14968: member = member->next;
14969: }
14970: return(0);
14971: }
14972:
14973: static int
14974: xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14975: xmlSchemaTypePtr type)
14976: {
14977: if (! WXS_IS_UNION(type))
14978: return(0);
14979: return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14980: type->memberTypes));
14981: }
14982:
14983: /**
14984: * xmlSchemaResolveTypeReferences:
14985: * @item: the complex/simple type definition
14986: * @ctxt: the parser context
14987: * @name: the name
14988: *
14989: * Resolvese type definition references
14990: */
14991: static void
14992: xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
14993: xmlSchemaParserCtxtPtr ctxt)
14994: {
14995: if (typeDef == NULL)
14996: return;
14997:
14998: /*
14999: * Resolve the base type.
15000: */
15001: if (typeDef->baseType == NULL) {
15002: typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15003: typeDef->base, typeDef->baseNs);
15004: if (typeDef->baseType == NULL) {
15005: xmlSchemaPResCompAttrErr(ctxt,
15006: XML_SCHEMAP_SRC_RESOLVE,
15007: WXS_BASIC_CAST typeDef, typeDef->node,
15008: "base", typeDef->base, typeDef->baseNs,
15009: XML_SCHEMA_TYPE_SIMPLE, NULL);
15010: return;
15011: }
15012: }
15013: if (WXS_IS_SIMPLE(typeDef)) {
15014: if (WXS_IS_UNION(typeDef)) {
15015: /*
15016: * Resolve the memberTypes.
15017: */
15018: xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15019: return;
15020: } else if (WXS_IS_LIST(typeDef)) {
15021: /*
15022: * Resolve the itemType.
15023: */
15024: if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15025:
15026: typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15027: typeDef->base, typeDef->baseNs);
15028:
15029: if ((typeDef->subtypes == NULL) ||
15030: (! WXS_IS_SIMPLE(typeDef->subtypes)))
15031: {
15032: typeDef->subtypes = NULL;
15033: xmlSchemaPResCompAttrErr(ctxt,
15034: XML_SCHEMAP_SRC_RESOLVE,
15035: WXS_BASIC_CAST typeDef, typeDef->node,
15036: "itemType", typeDef->base, typeDef->baseNs,
15037: XML_SCHEMA_TYPE_SIMPLE, NULL);
15038: }
15039: }
15040: return;
15041: }
15042: }
15043: /*
15044: * The ball of letters below means, that if we have a particle
15045: * which has a QName-helper component as its {term}, we want
15046: * to resolve it...
15047: */
15048: else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15049: ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15050: XML_SCHEMA_TYPE_PARTICLE) &&
15051: (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15052: ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15053: XML_SCHEMA_EXTRA_QNAMEREF))
15054: {
15055: xmlSchemaQNameRefPtr ref =
15056: WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15057: xmlSchemaModelGroupDefPtr groupDef;
15058:
15059: /*
15060: * URGENT TODO: Test this.
15061: */
15062: WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15063: /*
15064: * Resolve the MG definition reference.
15065: */
15066: groupDef =
15067: WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15068: ref->itemType, ref->name, ref->targetNamespace);
15069: if (groupDef == NULL) {
15070: xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15071: NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15072: "ref", ref->name, ref->targetNamespace, ref->itemType,
15073: NULL);
15074: /* Remove the particle. */
15075: WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15076: } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15077: /* Remove the particle. */
15078: WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15079: else {
15080: /*
15081: * Assign the MG definition's {model group} to the
15082: * particle's {term}.
15083: */
15084: WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15085:
15086: if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15087: /*
15088: * SPEC cos-all-limited (1.2)
15089: * "1.2 the {term} property of a particle with
15090: * {max occurs}=1 which is part of a pair which constitutes
15091: * the {content type} of a complex type definition."
15092: */
15093: if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15094: xmlSchemaCustomErr(ACTXT_CAST ctxt,
15095: /* TODO: error code */
15096: XML_SCHEMAP_COS_ALL_LIMITED,
15097: WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15098: "The particle's {max occurs} must be 1, since the "
15099: "reference resolves to an 'all' model group",
15100: NULL, NULL);
15101: }
15102: }
15103: }
15104: }
15105: }
15106:
15107:
15108:
15109: /**
15110: * xmlSchemaCheckSTPropsCorrect:
15111: * @ctxt: the schema parser context
15112: * @type: the simple type definition
15113: *
15114: * Checks st-props-correct.
15115: *
15116: * Returns 0 if the properties are correct,
15117: * if not, a positive error code and -1 on internal
15118: * errors.
15119: */
15120: static int
15121: xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15122: xmlSchemaTypePtr type)
15123: {
15124: xmlSchemaTypePtr baseType = type->baseType;
15125: xmlChar *str = NULL;
15126:
15127: /* STATE: error funcs converted. */
15128: /*
15129: * Schema Component Constraint: Simple Type Definition Properties Correct
15130: *
15131: * NOTE: This is somehow redundant, since we actually built a simple type
15132: * to have all the needed information; this acts as an self test.
15133: */
15134: /* Base type: If the datatype has been �derived� by �restriction�
15135: * then the Simple Type Definition component from which it is �derived�,
15136: * otherwise the Simple Type Definition for anySimpleType (�4.1.6).
15137: */
15138: if (baseType == NULL) {
15139: /*
15140: * TODO: Think about: "modulo the impact of Missing
15141: * Sub-components (�5.3)."
15142: */
15143: xmlSchemaPCustomErr(ctxt,
15144: XML_SCHEMAP_ST_PROPS_CORRECT_1,
15145: WXS_BASIC_CAST type, NULL,
15146: "No base type existent", NULL);
15147: return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15148:
15149: }
15150: if (! WXS_IS_SIMPLE(baseType)) {
15151: xmlSchemaPCustomErr(ctxt,
15152: XML_SCHEMAP_ST_PROPS_CORRECT_1,
15153: WXS_BASIC_CAST type, NULL,
15154: "The base type '%s' is not a simple type",
15155: xmlSchemaGetComponentQName(&str, baseType));
15156: FREE_AND_NULL(str)
15157: return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15158: }
1.1.1.2 ! misho 15159: if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
! 15160: (WXS_IS_RESTRICTION(type) == 0) &&
! 15161: ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
! 15162: (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
1.1 misho 15163: xmlSchemaPCustomErr(ctxt,
15164: XML_SCHEMAP_ST_PROPS_CORRECT_1,
15165: WXS_BASIC_CAST type, NULL,
15166: "A type, derived by list or union, must have "
15167: "the simple ur-type definition as base type, not '%s'",
15168: xmlSchemaGetComponentQName(&str, baseType));
15169: FREE_AND_NULL(str)
15170: return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15171: }
15172: /*
15173: * Variety: One of {atomic, list, union}.
15174: */
15175: if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15176: (! WXS_IS_LIST(type))) {
15177: xmlSchemaPCustomErr(ctxt,
15178: XML_SCHEMAP_ST_PROPS_CORRECT_1,
15179: WXS_BASIC_CAST type, NULL,
15180: "The variety is absent", NULL);
15181: return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15182: }
15183: /* TODO: Finish this. Hmm, is this finished? */
15184:
15185: /*
15186: * 3 The {final} of the {base type definition} must not contain restriction.
15187: */
15188: if (xmlSchemaTypeFinalContains(baseType,
15189: XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15190: xmlSchemaPCustomErr(ctxt,
15191: XML_SCHEMAP_ST_PROPS_CORRECT_3,
15192: WXS_BASIC_CAST type, NULL,
15193: "The 'final' of its base type '%s' must not contain "
15194: "'restriction'",
15195: xmlSchemaGetComponentQName(&str, baseType));
15196: FREE_AND_NULL(str)
15197: return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15198: }
15199:
15200: /*
15201: * 2 All simple type definitions must be derived ultimately from the �simple
15202: * ur-type definition (so� circular definitions are disallowed). That is, it
15203: * must be possible to reach a built-in primitive datatype or the �simple
15204: * ur-type definition� by repeatedly following the {base type definition}.
15205: *
15206: * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15207: */
15208: return (0);
15209: }
15210:
15211: /**
15212: * xmlSchemaCheckCOSSTRestricts:
15213: * @ctxt: the schema parser context
15214: * @type: the simple type definition
15215: *
15216: * Schema Component Constraint:
15217: * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15218:
15219: * Checks if the given @type (simpleType) is derived validly by restriction.
15220: * STATUS:
15221: *
15222: * Returns -1 on internal errors, 0 if the type is validly derived,
15223: * a positive error code otherwise.
15224: */
15225: static int
15226: xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15227: xmlSchemaTypePtr type)
15228: {
15229: xmlChar *str = NULL;
15230:
15231: if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15232: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15233: "given type is not a user-derived simpleType");
15234: return (-1);
15235: }
15236:
15237: if (WXS_IS_ATOMIC(type)) {
15238: xmlSchemaTypePtr primitive;
15239: /*
15240: * 1.1 The {base type definition} must be an atomic simple
15241: * type definition or a built-in primitive datatype.
15242: */
15243: if (! WXS_IS_ATOMIC(type->baseType)) {
15244: xmlSchemaPCustomErr(pctxt,
15245: XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15246: WXS_BASIC_CAST type, NULL,
15247: "The base type '%s' is not an atomic simple type",
15248: xmlSchemaGetComponentQName(&str, type->baseType));
15249: FREE_AND_NULL(str)
15250: return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15251: }
15252: /* 1.2 The {final} of the {base type definition} must not contain
15253: * restriction.
15254: */
15255: /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15256: if (xmlSchemaTypeFinalContains(type->baseType,
15257: XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15258: xmlSchemaPCustomErr(pctxt,
15259: XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15260: WXS_BASIC_CAST type, NULL,
15261: "The final of its base type '%s' must not contain 'restriction'",
15262: xmlSchemaGetComponentQName(&str, type->baseType));
15263: FREE_AND_NULL(str)
15264: return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15265: }
15266:
15267: /*
15268: * 1.3.1 DF must be an allowed constraining facet for the {primitive
15269: * type definition}, as specified in the appropriate subsection of 3.2
15270: * Primitive datatypes.
15271: */
15272: if (type->facets != NULL) {
15273: xmlSchemaFacetPtr facet;
15274: int ok = 1;
15275:
15276: primitive = xmlSchemaGetPrimitiveType(type);
15277: if (primitive == NULL) {
15278: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15279: "failed to get primitive type");
15280: return (-1);
15281: }
15282: facet = type->facets;
15283: do {
15284: if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15285: ok = 0;
15286: xmlSchemaPIllegalFacetAtomicErr(pctxt,
15287: XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15288: type, primitive, facet);
15289: }
15290: facet = facet->next;
15291: } while (facet != NULL);
15292: if (ok == 0)
15293: return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15294: }
15295: /*
15296: * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15297: * of the {base type definition} (call this BF),then the DF's {value}
15298: * must be a valid restriction of BF's {value} as defined in
15299: * [XML Schemas: Datatypes]."
15300: *
15301: * NOTE (1.3.2) Facet derivation constraints are currently handled in
15302: * xmlSchemaDeriveAndValidateFacets()
15303: */
15304: } else if (WXS_IS_LIST(type)) {
15305: xmlSchemaTypePtr itemType = NULL;
15306:
15307: itemType = type->subtypes;
15308: if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15309: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15310: "failed to evaluate the item type");
15311: return (-1);
15312: }
15313: if (WXS_IS_TYPE_NOT_FIXED(itemType))
15314: xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15315: /*
15316: * 2.1 The {item type definition} must have a {variety} of atomic or
15317: * union (in which case all the {member type definitions}
15318: * must be atomic).
15319: */
15320: if ((! WXS_IS_ATOMIC(itemType)) &&
15321: (! WXS_IS_UNION(itemType))) {
15322: xmlSchemaPCustomErr(pctxt,
15323: XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15324: WXS_BASIC_CAST type, NULL,
15325: "The item type '%s' does not have a variety of atomic or union",
15326: xmlSchemaGetComponentQName(&str, itemType));
15327: FREE_AND_NULL(str)
15328: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15329: } else if (WXS_IS_UNION(itemType)) {
15330: xmlSchemaTypeLinkPtr member;
15331:
15332: member = itemType->memberTypes;
15333: while (member != NULL) {
15334: if (! WXS_IS_ATOMIC(member->type)) {
15335: xmlSchemaPCustomErr(pctxt,
15336: XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15337: WXS_BASIC_CAST type, NULL,
15338: "The item type is a union type, but the "
15339: "member type '%s' of this item type is not atomic",
15340: xmlSchemaGetComponentQName(&str, member->type));
15341: FREE_AND_NULL(str)
15342: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15343: }
15344: member = member->next;
15345: }
15346: }
15347:
15348: if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15349: xmlSchemaFacetPtr facet;
15350: /*
15351: * This is the case if we have: <simpleType><list ..
15352: */
15353: /*
15354: * 2.3.1
15355: * 2.3.1.1 The {final} of the {item type definition} must not
15356: * contain list.
15357: */
15358: if (xmlSchemaTypeFinalContains(itemType,
15359: XML_SCHEMAS_TYPE_FINAL_LIST)) {
15360: xmlSchemaPCustomErr(pctxt,
15361: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15362: WXS_BASIC_CAST type, NULL,
15363: "The final of its item type '%s' must not contain 'list'",
15364: xmlSchemaGetComponentQName(&str, itemType));
15365: FREE_AND_NULL(str)
15366: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15367: }
15368: /*
15369: * 2.3.1.2 The {facets} must only contain the whiteSpace
15370: * facet component.
15371: * OPTIMIZE TODO: the S4S already disallows any facet
15372: * to be specified.
15373: */
15374: if (type->facets != NULL) {
15375: facet = type->facets;
15376: do {
15377: if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15378: xmlSchemaPIllegalFacetListUnionErr(pctxt,
15379: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15380: type, facet);
15381: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15382: }
15383: facet = facet->next;
15384: } while (facet != NULL);
15385: }
15386: /*
15387: * MAYBE TODO: (Hmm, not really) Datatypes states:
15388: * A �list� datatype can be �derived� from an �atomic� datatype
15389: * whose �lexical space� allows space (such as string or anyURI)or
15390: * a �union� datatype any of whose {member type definitions}'s
15391: * �lexical space� allows space.
15392: */
15393: } else {
15394: /*
15395: * This is the case if we have: <simpleType><restriction ...
15396: * I.e. the variety of "list" is inherited.
15397: */
15398: /*
15399: * 2.3.2
15400: * 2.3.2.1 The {base type definition} must have a {variety} of list.
15401: */
15402: if (! WXS_IS_LIST(type->baseType)) {
15403: xmlSchemaPCustomErr(pctxt,
15404: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15405: WXS_BASIC_CAST type, NULL,
15406: "The base type '%s' must be a list type",
15407: xmlSchemaGetComponentQName(&str, type->baseType));
15408: FREE_AND_NULL(str)
15409: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15410: }
15411: /*
15412: * 2.3.2.2 The {final} of the {base type definition} must not
15413: * contain restriction.
15414: */
15415: if (xmlSchemaTypeFinalContains(type->baseType,
15416: XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15417: xmlSchemaPCustomErr(pctxt,
15418: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15419: WXS_BASIC_CAST type, NULL,
15420: "The 'final' of the base type '%s' must not contain 'restriction'",
15421: xmlSchemaGetComponentQName(&str, type->baseType));
15422: FREE_AND_NULL(str)
15423: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15424: }
15425: /*
15426: * 2.3.2.3 The {item type definition} must be validly derived
15427: * from the {base type definition}'s {item type definition} given
15428: * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15429: */
15430: {
15431: xmlSchemaTypePtr baseItemType;
15432:
15433: baseItemType = type->baseType->subtypes;
15434: if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15435: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15436: "failed to eval the item type of a base type");
15437: return (-1);
15438: }
15439: if ((itemType != baseItemType) &&
15440: (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15441: baseItemType, 0) != 0)) {
15442: xmlChar *strBIT = NULL, *strBT = NULL;
15443: xmlSchemaPCustomErrExt(pctxt,
15444: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15445: WXS_BASIC_CAST type, NULL,
15446: "The item type '%s' is not validly derived from "
15447: "the item type '%s' of the base type '%s'",
15448: xmlSchemaGetComponentQName(&str, itemType),
15449: xmlSchemaGetComponentQName(&strBIT, baseItemType),
15450: xmlSchemaGetComponentQName(&strBT, type->baseType));
15451:
15452: FREE_AND_NULL(str)
15453: FREE_AND_NULL(strBIT)
15454: FREE_AND_NULL(strBT)
15455: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15456: }
15457: }
15458:
15459: if (type->facets != NULL) {
15460: xmlSchemaFacetPtr facet;
15461: int ok = 1;
15462: /*
15463: * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15464: * and enumeration facet components are allowed among the {facets}.
15465: */
15466: facet = type->facets;
15467: do {
15468: switch (facet->type) {
15469: case XML_SCHEMA_FACET_LENGTH:
15470: case XML_SCHEMA_FACET_MINLENGTH:
15471: case XML_SCHEMA_FACET_MAXLENGTH:
15472: case XML_SCHEMA_FACET_WHITESPACE:
15473: /*
15474: * TODO: 2.5.1.2 List datatypes
15475: * The value of �whiteSpace� is fixed to the value collapse.
15476: */
15477: case XML_SCHEMA_FACET_PATTERN:
15478: case XML_SCHEMA_FACET_ENUMERATION:
15479: break;
15480: default: {
15481: xmlSchemaPIllegalFacetListUnionErr(pctxt,
15482: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15483: type, facet);
15484: /*
15485: * We could return, but it's nicer to report all
15486: * invalid facets.
15487: */
15488: ok = 0;
15489: }
15490: }
15491: facet = facet->next;
15492: } while (facet != NULL);
15493: if (ok == 0)
15494: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15495: /*
15496: * SPEC (2.3.2.5) (same as 1.3.2)
15497: *
15498: * NOTE (2.3.2.5) This is currently done in
15499: * xmlSchemaDeriveAndValidateFacets()
15500: */
15501: }
15502: }
15503: } else if (WXS_IS_UNION(type)) {
15504: /*
15505: * 3.1 The {member type definitions} must all have {variety} of
15506: * atomic or list.
15507: */
15508: xmlSchemaTypeLinkPtr member;
15509:
15510: member = type->memberTypes;
15511: while (member != NULL) {
15512: if (WXS_IS_TYPE_NOT_FIXED(member->type))
15513: xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15514:
15515: if ((! WXS_IS_ATOMIC(member->type)) &&
15516: (! WXS_IS_LIST(member->type))) {
15517: xmlSchemaPCustomErr(pctxt,
15518: XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15519: WXS_BASIC_CAST type, NULL,
15520: "The member type '%s' is neither an atomic, nor a list type",
15521: xmlSchemaGetComponentQName(&str, member->type));
15522: FREE_AND_NULL(str)
15523: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15524: }
15525: member = member->next;
15526: }
15527: /*
15528: * 3.3.1 If the {base type definition} is the �simple ur-type
15529: * definition�
15530: */
15531: if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15532: /*
15533: * 3.3.1.1 All of the {member type definitions} must have a
15534: * {final} which does not contain union.
15535: */
15536: member = type->memberTypes;
15537: while (member != NULL) {
15538: if (xmlSchemaTypeFinalContains(member->type,
15539: XML_SCHEMAS_TYPE_FINAL_UNION)) {
15540: xmlSchemaPCustomErr(pctxt,
15541: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15542: WXS_BASIC_CAST type, NULL,
15543: "The 'final' of member type '%s' contains 'union'",
15544: xmlSchemaGetComponentQName(&str, member->type));
15545: FREE_AND_NULL(str)
15546: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15547: }
15548: member = member->next;
15549: }
15550: /*
15551: * 3.3.1.2 The {facets} must be empty.
15552: */
15553: if (type->facetSet != NULL) {
15554: xmlSchemaPCustomErr(pctxt,
15555: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15556: WXS_BASIC_CAST type, NULL,
15557: "No facets allowed", NULL);
15558: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15559: }
15560: } else {
15561: /*
15562: * 3.3.2.1 The {base type definition} must have a {variety} of union.
15563: * I.e. the variety of "list" is inherited.
15564: */
15565: if (! WXS_IS_UNION(type->baseType)) {
15566: xmlSchemaPCustomErr(pctxt,
15567: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15568: WXS_BASIC_CAST type, NULL,
15569: "The base type '%s' is not a union type",
15570: xmlSchemaGetComponentQName(&str, type->baseType));
15571: FREE_AND_NULL(str)
15572: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15573: }
15574: /*
15575: * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15576: */
15577: if (xmlSchemaTypeFinalContains(type->baseType,
15578: XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15579: xmlSchemaPCustomErr(pctxt,
15580: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15581: WXS_BASIC_CAST type, NULL,
15582: "The 'final' of its base type '%s' must not contain 'restriction'",
15583: xmlSchemaGetComponentQName(&str, type->baseType));
15584: FREE_AND_NULL(str)
15585: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15586: }
15587: /*
15588: * 3.3.2.3 The {member type definitions}, in order, must be validly
15589: * derived from the corresponding type definitions in the {base
15590: * type definition}'s {member type definitions} given the empty set,
15591: * as defined in Type Derivation OK (Simple) (�3.14.6).
15592: */
15593: {
15594: xmlSchemaTypeLinkPtr baseMember;
15595:
15596: /*
15597: * OPTIMIZE: if the type is restricting, it has no local defined
15598: * member types and inherits the member types of the base type;
15599: * thus a check for equality can be skipped.
15600: */
15601: /*
15602: * Even worse: I cannot see a scenario where a restricting
15603: * union simple type can have other member types as the member
15604: * types of it's base type. This check seems not necessary with
15605: * respect to the derivation process in libxml2.
15606: * But necessary if constructing types with an API.
15607: */
15608: if (type->memberTypes != NULL) {
15609: member = type->memberTypes;
15610: baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15611: if ((member == NULL) && (baseMember != NULL)) {
15612: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15613: "different number of member types in base");
15614: }
15615: while (member != NULL) {
15616: if (baseMember == NULL) {
15617: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15618: "different number of member types in base");
15619: } else if ((member->type != baseMember->type) &&
15620: (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15621: member->type, baseMember->type, 0) != 0)) {
15622: xmlChar *strBMT = NULL, *strBT = NULL;
15623:
15624: xmlSchemaPCustomErrExt(pctxt,
15625: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15626: WXS_BASIC_CAST type, NULL,
15627: "The member type %s is not validly "
15628: "derived from its corresponding member "
15629: "type %s of the base type %s",
15630: xmlSchemaGetComponentQName(&str, member->type),
15631: xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15632: xmlSchemaGetComponentQName(&strBT, type->baseType));
15633: FREE_AND_NULL(str)
15634: FREE_AND_NULL(strBMT)
15635: FREE_AND_NULL(strBT)
15636: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15637: }
15638: member = member->next;
15639: if (baseMember != NULL)
15640: baseMember = baseMember->next;
15641: }
15642: }
15643: }
15644: /*
15645: * 3.3.2.4 Only pattern and enumeration facet components are
15646: * allowed among the {facets}.
15647: */
15648: if (type->facets != NULL) {
15649: xmlSchemaFacetPtr facet;
15650: int ok = 1;
15651:
15652: facet = type->facets;
15653: do {
15654: if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15655: (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15656: xmlSchemaPIllegalFacetListUnionErr(pctxt,
15657: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15658: type, facet);
15659: ok = 0;
15660: }
15661: facet = facet->next;
15662: } while (facet != NULL);
15663: if (ok == 0)
15664: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15665:
15666: }
15667: /*
15668: * SPEC (3.3.2.5) (same as 1.3.2)
15669: *
15670: * NOTE (3.3.2.5) This is currently done in
15671: * xmlSchemaDeriveAndValidateFacets()
15672: */
15673: }
15674: }
15675:
15676: return (0);
15677: }
15678:
15679: /**
15680: * xmlSchemaCheckSRCSimpleType:
15681: * @ctxt: the schema parser context
15682: * @type: the simple type definition
15683: *
15684: * Checks crc-simple-type constraints.
15685: *
15686: * Returns 0 if the constraints are satisfied,
15687: * if not a positive error code and -1 on internal
15688: * errors.
15689: */
15690: #if 0
15691: static int
15692: xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15693: xmlSchemaTypePtr type)
15694: {
15695: /*
15696: * src-simple-type.1 The corresponding simple type definition, if any,
15697: * must satisfy the conditions set out in Constraints on Simple Type
15698: * Definition Schema Components (�3.14.6).
15699: */
15700: if (WXS_IS_RESTRICTION(type)) {
15701: /*
15702: * src-simple-type.2 "If the <restriction> alternative is chosen,
15703: * either it must have a base [attribute] or a <simpleType> among its
15704: * [children], but not both."
15705: * NOTE: This is checked in the parse function of <restriction>.
15706: */
15707: /*
15708: *
15709: */
15710: } else if (WXS_IS_LIST(type)) {
15711: /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15712: * an itemType [attribute] or a <simpleType> among its [children],
15713: * but not both."
15714: *
15715: * NOTE: This is checked in the parse function of <list>.
15716: */
15717: } else if (WXS_IS_UNION(type)) {
15718: /*
15719: * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15720: */
15721: }
15722: return (0);
15723: }
15724: #endif
15725:
15726: static int
15727: xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15728: {
15729: if (ctxt->vctxt == NULL) {
15730: ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15731: if (ctxt->vctxt == NULL) {
15732: xmlSchemaPErr(ctxt, NULL,
15733: XML_SCHEMAP_INTERNAL,
15734: "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15735: "failed to create a temp. validation context.\n",
15736: NULL, NULL);
15737: return (-1);
15738: }
15739: /* TODO: Pass user data. */
15740: xmlSchemaSetValidErrors(ctxt->vctxt,
15741: ctxt->error, ctxt->warning, ctxt->errCtxt);
15742: xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15743: ctxt->serror, ctxt->errCtxt);
15744: }
15745: return (0);
15746: }
15747:
15748: static int
15749: xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15750: xmlNodePtr node,
15751: xmlSchemaTypePtr type,
15752: const xmlChar *value,
15753: xmlSchemaValPtr *retVal,
15754: int fireErrors,
15755: int normalize,
15756: int isNormalized);
15757:
15758: /**
15759: * xmlSchemaParseCheckCOSValidDefault:
15760: * @pctxt: the schema parser context
15761: * @type: the simple type definition
15762: * @value: the default value
15763: * @node: an optional node (the holder of the value)
15764: *
15765: * Schema Component Constraint: Element Default Valid (Immediate)
15766: * (cos-valid-default)
15767: * This will be used by the parser only. For the validator there's
15768: * an other version.
15769: *
15770: * Returns 0 if the constraints are satisfied,
15771: * if not, a positive error code and -1 on internal
15772: * errors.
15773: */
15774: static int
15775: xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15776: xmlNodePtr node,
15777: xmlSchemaTypePtr type,
15778: const xmlChar *value,
15779: xmlSchemaValPtr *val)
15780: {
15781: int ret = 0;
15782:
15783: /*
15784: * cos-valid-default:
15785: * Schema Component Constraint: Element Default Valid (Immediate)
15786: * For a string to be a valid default with respect to a type
15787: * definition the appropriate case among the following must be true:
15788: */
15789: if WXS_IS_COMPLEX(type) {
15790: /*
15791: * Complex type.
15792: *
15793: * SPEC (2.1) "its {content type} must be a simple type definition
15794: * or mixed."
15795: * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15796: * type}'s particle must be �emptiable� as defined by
15797: * Particle Emptiable (�3.9.6)."
15798: */
15799: if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15800: ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15801: /* NOTE that this covers (2.2.2) as well. */
15802: xmlSchemaPCustomErr(pctxt,
15803: XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15804: WXS_BASIC_CAST type, type->node,
15805: "For a string to be a valid default, the type definition "
15806: "must be a simple type or a complex type with mixed content "
15807: "and a particle emptiable", NULL);
15808: return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15809: }
15810: }
15811: /*
15812: * 1 If the type definition is a simple type definition, then the string
15813: * must be �valid� with respect to that definition as defined by String
15814: * Valid (�3.14.4).
15815: *
15816: * AND
15817: *
15818: * 2.2.1 If the {content type} is a simple type definition, then the
15819: * string must be �valid� with respect to that simple type definition
15820: * as defined by String Valid (�3.14.4).
15821: */
15822: if (WXS_IS_SIMPLE(type))
15823: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15824: type, value, val, 1, 1, 0);
15825: else if (WXS_HAS_SIMPLE_CONTENT(type))
15826: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15827: type->contentTypeDef, value, val, 1, 1, 0);
15828: else
15829: return (ret);
15830:
15831: if (ret < 0) {
15832: PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15833: "calling xmlSchemaVCheckCVCSimpleType()");
15834: }
15835:
15836: return (ret);
15837: }
15838:
15839: /**
15840: * xmlSchemaCheckCTPropsCorrect:
15841: * @ctxt: the schema parser context
15842: * @type: the complex type definition
15843: *
15844: *.(4.6) Constraints on Complex Type Definition Schema Components
15845: * Schema Component Constraint:
15846: * Complex Type Definition Properties Correct (ct-props-correct)
15847: * STATUS: (seems) complete
15848: *
15849: * Returns 0 if the constraints are satisfied, a positive
15850: * error code if not and -1 if an internal error occured.
15851: */
15852: static int
15853: xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15854: xmlSchemaTypePtr type)
15855: {
15856: /*
15857: * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15858: *
15859: * SPEC (1) "The values of the properties of a complex type definition must
15860: * be as described in the property tableau in The Complex Type Definition
15861: * Schema Component (�3.4.1), modulo the impact of Missing
15862: * Sub-components (�5.3)."
15863: */
15864: if ((type->baseType != NULL) &&
15865: (WXS_IS_SIMPLE(type->baseType)) &&
15866: (WXS_IS_EXTENSION(type) == 0)) {
15867: /*
15868: * SPEC (2) "If the {base type definition} is a simple type definition,
15869: * the {derivation method} must be extension."
15870: */
15871: xmlSchemaCustomErr(ACTXT_CAST pctxt,
15872: XML_SCHEMAP_SRC_CT_1,
15873: NULL, WXS_BASIC_CAST type,
15874: "If the base type is a simple type, the derivation method must be "
15875: "'extension'", NULL, NULL);
15876: return (XML_SCHEMAP_SRC_CT_1);
15877: }
15878: /*
15879: * SPEC (3) "Circular definitions are disallowed, except for the �ur-type
15880: * definition�. That is, it must be possible to reach the �ur-type
15881: * definition by repeatedly following the {base type definition}."
15882: *
15883: * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15884: */
15885: /*
15886: * NOTE that (4) and (5) need the following:
15887: * - attribute uses need to be already inherited (apply attr. prohibitions)
15888: * - attribute group references need to be expanded already
15889: * - simple types need to be typefixed already
15890: */
15891: if (type->attrUses &&
15892: (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15893: {
15894: xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15895: xmlSchemaAttributeUsePtr use, tmp;
15896: int i, j, hasId = 0;
15897:
15898: for (i = uses->nbItems -1; i >= 0; i--) {
15899: use = uses->items[i];
15900:
15901: /*
15902: * SPEC ct-props-correct
15903: * (4) "Two distinct attribute declarations in the
15904: * {attribute uses} must not have identical {name}s and
15905: * {target namespace}s."
15906: */
15907: if (i > 0) {
15908: for (j = i -1; j >= 0; j--) {
15909: tmp = uses->items[j];
15910: if ((WXS_ATTRUSE_DECL_NAME(use) ==
15911: WXS_ATTRUSE_DECL_NAME(tmp)) &&
15912: (WXS_ATTRUSE_DECL_TNS(use) ==
15913: WXS_ATTRUSE_DECL_TNS(tmp)))
15914: {
15915: xmlChar *str = NULL;
15916:
15917: xmlSchemaCustomErr(ACTXT_CAST pctxt,
15918: XML_SCHEMAP_AG_PROPS_CORRECT,
15919: NULL, WXS_BASIC_CAST type,
15920: "Duplicate %s",
15921: xmlSchemaGetComponentDesignation(&str, use),
15922: NULL);
15923: FREE_AND_NULL(str);
15924: /*
15925: * Remove the duplicate.
15926: */
15927: if (xmlSchemaItemListRemove(uses, i) == -1)
15928: goto exit_failure;
15929: goto next_use;
15930: }
15931: }
15932: }
15933: /*
15934: * SPEC ct-props-correct
15935: * (5) "Two distinct attribute declarations in the
15936: * {attribute uses} must not have {type definition}s which
15937: * are or are derived from ID."
15938: */
15939: if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15940: if (xmlSchemaIsDerivedFromBuiltInType(
15941: WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15942: {
15943: if (hasId) {
15944: xmlChar *str = NULL;
15945:
15946: xmlSchemaCustomErr(ACTXT_CAST pctxt,
15947: XML_SCHEMAP_AG_PROPS_CORRECT,
15948: NULL, WXS_BASIC_CAST type,
15949: "There must not exist more than one attribute "
15950: "declaration of type 'xs:ID' "
15951: "(or derived from 'xs:ID'). The %s violates this "
15952: "constraint",
15953: xmlSchemaGetComponentDesignation(&str, use),
15954: NULL);
15955: FREE_AND_NULL(str);
15956: if (xmlSchemaItemListRemove(uses, i) == -1)
15957: goto exit_failure;
15958: }
15959:
15960: hasId = 1;
15961: }
15962: }
15963: next_use: {}
15964: }
15965: }
15966: return (0);
15967: exit_failure:
15968: return(-1);
15969: }
15970:
15971: static int
15972: xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15973: xmlSchemaTypePtr typeB)
15974: {
15975: /*
15976: * TODO: This should implement component-identity
15977: * in the future.
15978: */
15979: if ((typeA == NULL) || (typeB == NULL))
15980: return (0);
15981: return (typeA == typeB);
15982: }
15983:
15984: /**
15985: * xmlSchemaCheckCOSCTDerivedOK:
15986: * @ctxt: the schema parser context
15987: * @type: the to-be derived complex type definition
15988: * @baseType: the base complex type definition
15989: * @set: the given set
15990: *
15991: * Schema Component Constraint:
15992: * Type Derivation OK (Complex) (cos-ct-derived-ok)
15993: *
15994: * STATUS: completed
15995: *
15996: * Returns 0 if the constraints are satisfied, or 1
15997: * if not.
15998: */
15999: static int
16000: xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16001: xmlSchemaTypePtr type,
16002: xmlSchemaTypePtr baseType,
16003: int set)
16004: {
16005: int equal = xmlSchemaAreEqualTypes(type, baseType);
16006: /* TODO: Error codes. */
16007: /*
16008: * SPEC "For a complex type definition (call it D, for derived)
16009: * to be validly derived from a type definition (call this
16010: * B, for base) given a subset of {extension, restriction}
16011: * all of the following must be true:"
16012: */
16013: if (! equal) {
16014: /*
16015: * SPEC (1) "If B and D are not the same type definition, then the
16016: * {derivation method} of D must not be in the subset."
16017: */
16018: if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16019: ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16020: return (1);
16021: } else {
16022: /*
16023: * SPEC (2.1) "B and D must be the same type definition."
16024: */
16025: return (0);
16026: }
16027: /*
16028: * SPEC (2.2) "B must be D's {base type definition}."
16029: */
16030: if (type->baseType == baseType)
16031: return (0);
16032: /*
16033: * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type
16034: * definition�."
16035: */
16036: if (WXS_IS_ANYTYPE(type->baseType))
16037: return (1);
16038:
16039: if (WXS_IS_COMPLEX(type->baseType)) {
16040: /*
16041: * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16042: * must be validly derived from B given the subset as defined by this
16043: * constraint."
16044: */
16045: return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16046: baseType, set));
16047: } else {
16048: /*
16049: * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16050: * must be validly derived from B given the subset as defined in Type
16051: * Derivation OK (Simple) (�3.14.6).
16052: */
16053: return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16054: baseType, set));
16055: }
16056: }
16057:
16058: /**
16059: * xmlSchemaCheckCOSDerivedOK:
16060: * @type: the derived simple type definition
16061: * @baseType: the base type definition
16062: *
16063: * Calls:
16064: * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16065: *
16066: * Checks wheter @type can be validly derived from @baseType.
16067: *
16068: * Returns 0 on success, an positive error code otherwise.
16069: */
16070: static int
16071: xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16072: xmlSchemaTypePtr type,
16073: xmlSchemaTypePtr baseType,
16074: int set)
16075: {
16076: if (WXS_IS_SIMPLE(type))
16077: return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16078: else
16079: return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16080: }
16081:
16082: /**
16083: * xmlSchemaCheckCOSCTExtends:
16084: * @ctxt: the schema parser context
16085: * @type: the complex type definition
16086: *
16087: * (3.4.6) Constraints on Complex Type Definition Schema Components
16088: * Schema Component Constraint:
16089: * Derivation Valid (Extension) (cos-ct-extends)
16090: *
16091: * STATUS:
16092: * missing:
16093: * (1.5)
16094: * (1.4.3.2.2.2) "Particle Valid (Extension)"
16095: *
16096: * Returns 0 if the constraints are satisfied, a positive
16097: * error code if not and -1 if an internal error occured.
16098: */
16099: static int
16100: xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16101: xmlSchemaTypePtr type)
16102: {
16103: xmlSchemaTypePtr base = type->baseType;
16104: /*
16105: * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16106: * temporarily only.
16107: */
16108: /*
16109: * SPEC (1) "If the {base type definition} is a complex type definition,
16110: * then all of the following must be true:"
16111: */
16112: if (WXS_IS_COMPLEX(base)) {
16113: /*
16114: * SPEC (1.1) "The {final} of the {base type definition} must not
16115: * contain extension."
16116: */
16117: if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16118: xmlSchemaPCustomErr(ctxt,
16119: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16120: WXS_BASIC_CAST type, NULL,
16121: "The 'final' of the base type definition "
16122: "contains 'extension'", NULL);
16123: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16124: }
16125:
16126: /*
16127: * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16128: * since they are automatically satisfied through the
16129: * inheriting mechanism.
16130: * Note that even if redefining components, the inheriting mechanism
16131: * is used.
16132: */
16133: #if 0
16134: /*
16135: * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16136: * uses}
16137: * of the complex type definition itself, that is, for every attribute
16138: * use in the {attribute uses} of the {base type definition}, there
16139: * must be an attribute use in the {attribute uses} of the complex
16140: * type definition itself whose {attribute declaration} has the same
16141: * {name}, {target namespace} and {type definition} as its attribute
16142: * declaration"
16143: */
16144: if (base->attrUses != NULL) {
16145: int i, j, found;
16146: xmlSchemaAttributeUsePtr use, buse;
16147:
16148: for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16149: buse = (WXS_LIST_CAST base->attrUses)->items[i];
16150: found = 0;
16151: if (type->attrUses != NULL) {
16152: use = (WXS_LIST_CAST type->attrUses)->items[j];
16153: for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16154: {
16155: if ((WXS_ATTRUSE_DECL_NAME(use) ==
16156: WXS_ATTRUSE_DECL_NAME(buse)) &&
16157: (WXS_ATTRUSE_DECL_TNS(use) ==
16158: WXS_ATTRUSE_DECL_TNS(buse)) &&
16159: (WXS_ATTRUSE_TYPEDEF(use) ==
16160: WXS_ATTRUSE_TYPEDEF(buse))
16161: {
16162: found = 1;
16163: break;
16164: }
16165: }
16166: }
16167: if (! found) {
16168: xmlChar *str = NULL;
16169:
16170: xmlSchemaCustomErr(ACTXT_CAST ctxt,
16171: XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16172: NULL, WXS_BASIC_CAST type,
16173: /*
16174: * TODO: The report does not indicate that also the
16175: * type needs to be the same.
16176: */
16177: "This type is missing a matching correspondent "
16178: "for its {base type}'s %s in its {attribute uses}",
16179: xmlSchemaGetComponentDesignation(&str,
16180: buse->children),
16181: NULL);
16182: FREE_AND_NULL(str)
16183: }
16184: }
16185: }
16186: /*
16187: * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16188: * definition must also have one, and the base type definition's
16189: * {attribute wildcard}'s {namespace constraint} must be a subset
16190: * of the complex type definition's {attribute wildcard}'s {namespace
16191: * constraint}, as defined by Wildcard Subset (�3.10.6)."
16192: */
16193:
16194: /*
16195: * MAYBE TODO: Enable if ever needed. But this will be needed only
16196: * if created the type via a schema construction API.
16197: */
16198: if (base->attributeWildcard != NULL) {
16199: if (type->attributeWilcard == NULL) {
16200: xmlChar *str = NULL;
16201:
16202: xmlSchemaCustomErr(ACTXT_CAST pctxt,
16203: XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16204: NULL, type,
16205: "The base %s has an attribute wildcard, "
16206: "but this type is missing an attribute wildcard",
16207: xmlSchemaGetComponentDesignation(&str, base));
16208: FREE_AND_NULL(str)
16209:
16210: } else if (xmlSchemaCheckCOSNSSubset(
16211: base->attributeWildcard, type->attributeWildcard))
16212: {
16213: xmlChar *str = NULL;
16214:
16215: xmlSchemaCustomErr(ACTXT_CAST pctxt,
16216: XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16217: NULL, type,
16218: "The attribute wildcard is not a valid "
16219: "superset of the one in the base %s",
16220: xmlSchemaGetComponentDesignation(&str, base));
16221: FREE_AND_NULL(str)
16222: }
16223: }
16224: #endif
16225: /*
16226: * SPEC (1.4) "One of the following must be true:"
16227: */
16228: if ((type->contentTypeDef != NULL) &&
16229: (type->contentTypeDef == base->contentTypeDef)) {
16230: /*
16231: * SPEC (1.4.1) "The {content type} of the {base type definition}
16232: * and the {content type} of the complex type definition itself
16233: * must be the same simple type definition"
16234: * PASS
16235: */
16236: } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16237: (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16238: /*
16239: * SPEC (1.4.2) "The {content type} of both the {base type
16240: * definition} and the complex type definition itself must
16241: * be empty."
16242: * PASS
16243: */
16244: } else {
16245: /*
16246: * SPEC (1.4.3) "All of the following must be true:"
16247: */
16248: if (type->subtypes == NULL) {
16249: /*
16250: * SPEC 1.4.3.1 The {content type} of the complex type
16251: * definition itself must specify a particle.
16252: */
16253: xmlSchemaPCustomErr(ctxt,
16254: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16255: WXS_BASIC_CAST type, NULL,
16256: "The content type must specify a particle", NULL);
16257: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16258: }
16259: /*
16260: * SPEC (1.4.3.2) "One of the following must be true:"
16261: */
16262: if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16263: /*
16264: * SPEC (1.4.3.2.1) "The {content type} of the {base type
16265: * definition} must be empty.
16266: * PASS
16267: */
16268: } else {
16269: /*
16270: * SPEC (1.4.3.2.2) "All of the following must be true:"
16271: */
16272: if ((type->contentType != base->contentType) ||
16273: ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16274: (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16275: /*
16276: * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16277: * or both must be element-only."
16278: */
16279: xmlSchemaPCustomErr(ctxt,
16280: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16281: WXS_BASIC_CAST type, NULL,
16282: "The content type of both, the type and its base "
16283: "type, must either 'mixed' or 'element-only'", NULL);
16284: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16285: }
16286: /*
16287: * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16288: * complex type definition must be a �valid extension�
16289: * of the {base type definition}'s particle, as defined
16290: * in Particle Valid (Extension) (�3.9.6)."
16291: *
16292: * NOTE that we won't check "Particle Valid (Extension)",
16293: * since it is ensured by the derivation process in
16294: * xmlSchemaTypeFixup(). We need to implement this when heading
16295: * for a construction API
16296: * TODO: !! This is needed to be checked if redefining a type !!
16297: */
16298: }
16299: /*
16300: * URGENT TODO (1.5)
16301: */
16302: }
16303: } else {
16304: /*
16305: * SPEC (2) "If the {base type definition} is a simple type definition,
16306: * then all of the following must be true:"
16307: */
16308: if (type->contentTypeDef != base) {
16309: /*
16310: * SPEC (2.1) "The {content type} must be the same simple type
16311: * definition."
16312: */
16313: xmlSchemaPCustomErr(ctxt,
16314: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16315: WXS_BASIC_CAST type, NULL,
16316: "The content type must be the simple base type", NULL);
16317: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16318: }
16319: if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16320: /*
16321: * SPEC (2.2) "The {final} of the {base type definition} must not
16322: * contain extension"
16323: * NOTE that this is the same as (1.1).
16324: */
16325: xmlSchemaPCustomErr(ctxt,
16326: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16327: WXS_BASIC_CAST type, NULL,
16328: "The 'final' of the base type definition "
16329: "contains 'extension'", NULL);
16330: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16331: }
16332: }
16333: return (0);
16334: }
16335:
16336: /**
16337: * xmlSchemaCheckDerivationOKRestriction:
16338: * @ctxt: the schema parser context
16339: * @type: the complex type definition
16340: *
16341: * (3.4.6) Constraints on Complex Type Definition Schema Components
16342: * Schema Component Constraint:
16343: * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16344: *
16345: * STATUS:
16346: * missing:
16347: * (5.4.2) ???
16348: *
16349: * ATTENTION:
16350: * In XML Schema 1.1 this will be:
16351: * Validation Rule: Checking complex type subsumption
16352: *
16353: * Returns 0 if the constraints are satisfied, a positive
16354: * error code if not and -1 if an internal error occured.
16355: */
16356: static int
16357: xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16358: xmlSchemaTypePtr type)
16359: {
16360: xmlSchemaTypePtr base;
16361:
16362: /*
16363: * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16364: * temporarily only.
16365: */
16366: base = type->baseType;
16367: if (! WXS_IS_COMPLEX(base)) {
16368: xmlSchemaCustomErr(ACTXT_CAST ctxt,
16369: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16370: type->node, WXS_BASIC_CAST type,
16371: "The base type must be a complex type", NULL, NULL);
16372: return(ctxt->err);
16373: }
16374: if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16375: /*
16376: * SPEC (1) "The {base type definition} must be a complex type
16377: * definition whose {final} does not contain restriction."
16378: */
16379: xmlSchemaCustomErr(ACTXT_CAST ctxt,
16380: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16381: type->node, WXS_BASIC_CAST type,
16382: "The 'final' of the base type definition "
16383: "contains 'restriction'", NULL, NULL);
16384: return (ctxt->err);
16385: }
16386: /*
16387: * SPEC (2), (3) and (4)
16388: * Those are handled in a separate function, since the
16389: * same constraints are needed for redefinition of
16390: * attribute groups as well.
16391: */
16392: if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16393: XML_SCHEMA_ACTION_DERIVE,
16394: WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16395: type->attrUses, base->attrUses,
16396: type->attributeWildcard,
16397: base->attributeWildcard) == -1)
16398: {
16399: return(-1);
16400: }
16401: /*
16402: * SPEC (5) "One of the following must be true:"
16403: */
16404: if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16405: /*
16406: * SPEC (5.1) "The {base type definition} must be the
16407: * �ur-type definition�."
16408: * PASS
16409: */
16410: } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16411: (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16412: /*
16413: * SPEC (5.2.1) "The {content type} of the complex type definition
16414: * must be a simple type definition"
16415: *
16416: * SPEC (5.2.2) "One of the following must be true:"
16417: */
16418: if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16419: (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16420: {
16421: int err;
16422: /*
16423: * SPEC (5.2.2.1) "The {content type} of the {base type
16424: * definition} must be a simple type definition from which
16425: * the {content type} is validly derived given the empty
16426: * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16427: *
16428: * ATTENTION TODO: This seems not needed if the type implicitely
16429: * derived from the base type.
16430: *
16431: */
16432: err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16433: type->contentTypeDef, base->contentTypeDef, 0);
16434: if (err != 0) {
16435: xmlChar *strA = NULL, *strB = NULL;
16436:
16437: if (err == -1)
16438: return(-1);
16439: xmlSchemaCustomErr(ACTXT_CAST ctxt,
16440: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16441: NULL, WXS_BASIC_CAST type,
16442: "The {content type} %s is not validly derived from the "
16443: "base type's {content type} %s",
16444: xmlSchemaGetComponentDesignation(&strA,
16445: type->contentTypeDef),
16446: xmlSchemaGetComponentDesignation(&strB,
16447: base->contentTypeDef));
16448: FREE_AND_NULL(strA);
16449: FREE_AND_NULL(strB);
16450: return(ctxt->err);
16451: }
16452: } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16453: (xmlSchemaIsParticleEmptiable(
16454: (xmlSchemaParticlePtr) base->subtypes))) {
16455: /*
16456: * SPEC (5.2.2.2) "The {base type definition} must be mixed
16457: * and have a particle which is �emptiable� as defined in
16458: * Particle Emptiable (�3.9.6)."
16459: * PASS
16460: */
16461: } else {
16462: xmlSchemaPCustomErr(ctxt,
16463: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16464: WXS_BASIC_CAST type, NULL,
16465: "The content type of the base type must be either "
16466: "a simple type or 'mixed' and an emptiable particle", NULL);
16467: return (ctxt->err);
16468: }
16469: } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16470: /*
16471: * SPEC (5.3.1) "The {content type} of the complex type itself must
16472: * be empty"
16473: */
16474: if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16475: /*
16476: * SPEC (5.3.2.1) "The {content type} of the {base type
16477: * definition} must also be empty."
16478: * PASS
16479: */
16480: } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16481: (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16482: xmlSchemaIsParticleEmptiable(
16483: (xmlSchemaParticlePtr) base->subtypes)) {
16484: /*
16485: * SPEC (5.3.2.2) "The {content type} of the {base type
16486: * definition} must be elementOnly or mixed and have a particle
16487: * which is �emptiable� as defined in Particle Emptiable (�3.9.6)."
16488: * PASS
16489: */
16490: } else {
16491: xmlSchemaPCustomErr(ctxt,
16492: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16493: WXS_BASIC_CAST type, NULL,
16494: "The content type of the base type must be either "
16495: "empty or 'mixed' (or 'elements-only') and an emptiable "
16496: "particle", NULL);
16497: return (ctxt->err);
16498: }
16499: } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16500: WXS_HAS_MIXED_CONTENT(type)) {
16501: /*
16502: * SPEC (5.4.1.1) "The {content type} of the complex type definition
16503: * itself must be element-only"
16504: */
16505: if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16506: /*
16507: * SPEC (5.4.1.2) "The {content type} of the complex type
16508: * definition itself and of the {base type definition} must be
16509: * mixed"
16510: */
16511: xmlSchemaPCustomErr(ctxt,
16512: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16513: WXS_BASIC_CAST type, NULL,
16514: "If the content type is 'mixed', then the content type of the "
16515: "base type must also be 'mixed'", NULL);
16516: return (ctxt->err);
16517: }
16518: /*
16519: * SPEC (5.4.2) "The particle of the complex type definition itself
16520: * must be a �valid restriction� of the particle of the {content
16521: * type} of the {base type definition} as defined in Particle Valid
16522: * (Restriction) (�3.9.6).
16523: *
16524: * URGENT TODO: (5.4.2)
16525: */
16526: } else {
16527: xmlSchemaPCustomErr(ctxt,
16528: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16529: WXS_BASIC_CAST type, NULL,
16530: "The type is not a valid restriction of its base type", NULL);
16531: return (ctxt->err);
16532: }
16533: return (0);
16534: }
16535:
16536: /**
16537: * xmlSchemaCheckCTComponent:
16538: * @ctxt: the schema parser context
16539: * @type: the complex type definition
16540: *
16541: * (3.4.6) Constraints on Complex Type Definition Schema Components
16542: *
16543: * Returns 0 if the constraints are satisfied, a positive
16544: * error code if not and -1 if an internal error occured.
16545: */
16546: static int
16547: xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16548: xmlSchemaTypePtr type)
16549: {
16550: int ret;
16551: /*
16552: * Complex Type Definition Properties Correct
16553: */
16554: ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16555: if (ret != 0)
16556: return (ret);
16557: if (WXS_IS_EXTENSION(type))
16558: ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16559: else
16560: ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16561: return (ret);
16562: }
16563:
16564: /**
16565: * xmlSchemaCheckSRCCT:
16566: * @ctxt: the schema parser context
16567: * @type: the complex type definition
16568: *
16569: * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16570: * Schema Representation Constraint:
16571: * Complex Type Definition Representation OK (src-ct)
16572: *
16573: * Returns 0 if the constraints are satisfied, a positive
16574: * error code if not and -1 if an internal error occured.
16575: */
16576: static int
16577: xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16578: xmlSchemaTypePtr type)
16579: {
16580: xmlSchemaTypePtr base;
16581: int ret = 0;
16582:
16583: /*
16584: * TODO: Adjust the error codes here, as I used
16585: * XML_SCHEMAP_SRC_CT_1 only yet.
16586: */
16587: base = type->baseType;
16588: if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16589: /*
16590: * 1 If the <complexContent> alternative is chosen, the type definition
16591: * �resolved� to by the �actual value� of the base [attribute]
16592: * must be a complex type definition;
16593: */
16594: if (! WXS_IS_COMPLEX(base)) {
16595: xmlChar *str = NULL;
16596: xmlSchemaPCustomErr(ctxt,
16597: XML_SCHEMAP_SRC_CT_1,
16598: WXS_BASIC_CAST type, type->node,
16599: "If using <complexContent>, the base type is expected to be "
16600: "a complex type. The base type '%s' is a simple type",
16601: xmlSchemaFormatQName(&str, base->targetNamespace,
16602: base->name));
16603: FREE_AND_NULL(str)
16604: return (XML_SCHEMAP_SRC_CT_1);
16605: }
16606: } else {
16607: /*
16608: * SPEC
16609: * 2 If the <simpleContent> alternative is chosen, all of the
16610: * following must be true:
16611: * 2.1 The type definition �resolved� to by the �actual value� of the
16612: * base [attribute] must be one of the following:
16613: */
16614: if (WXS_IS_SIMPLE(base)) {
16615: if (WXS_IS_EXTENSION(type) == 0) {
16616: xmlChar *str = NULL;
16617: /*
16618: * 2.1.3 only if the <extension> alternative is also
16619: * chosen, a simple type definition.
16620: */
16621: /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16622: xmlSchemaPCustomErr(ctxt,
16623: XML_SCHEMAP_SRC_CT_1,
16624: WXS_BASIC_CAST type, NULL,
16625: "If using <simpleContent> and <restriction>, the base "
16626: "type must be a complex type. The base type '%s' is "
16627: "a simple type",
16628: xmlSchemaFormatQName(&str, base->targetNamespace,
16629: base->name));
16630: FREE_AND_NULL(str)
16631: return (XML_SCHEMAP_SRC_CT_1);
16632: }
16633: } else {
16634: /* Base type is a complex type. */
16635: if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16636: (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16637: /*
16638: * 2.1.1 a complex type definition whose {content type} is a
16639: * simple type definition;
16640: * PASS
16641: */
16642: if (base->contentTypeDef == NULL) {
16643: xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16644: WXS_BASIC_CAST type, NULL,
16645: "Internal error: xmlSchemaCheckSRCCT, "
16646: "'%s', base type has no content type",
16647: type->name);
16648: return (-1);
16649: }
16650: } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16651: (WXS_IS_RESTRICTION(type))) {
16652:
16653: /*
16654: * 2.1.2 only if the <restriction> alternative is also
16655: * chosen, a complex type definition whose {content type}
16656: * is mixed and a particle emptiable.
16657: */
16658: if (! xmlSchemaIsParticleEmptiable(
16659: (xmlSchemaParticlePtr) base->subtypes)) {
16660: ret = XML_SCHEMAP_SRC_CT_1;
16661: } else
16662: /*
16663: * Attention: at this point the <simpleType> child is in
16664: * ->contentTypeDef (put there during parsing).
16665: */
16666: if (type->contentTypeDef == NULL) {
16667: xmlChar *str = NULL;
16668: /*
16669: * 2.2 If clause 2.1.2 above is satisfied, then there
16670: * must be a <simpleType> among the [children] of
16671: * <restriction>.
16672: */
16673: /* TODO: Change error code to ..._SRC_CT_2_2. */
16674: xmlSchemaPCustomErr(ctxt,
16675: XML_SCHEMAP_SRC_CT_1,
16676: WXS_BASIC_CAST type, NULL,
16677: "A <simpleType> is expected among the children "
16678: "of <restriction>, if <simpleContent> is used and "
16679: "the base type '%s' is a complex type",
16680: xmlSchemaFormatQName(&str, base->targetNamespace,
16681: base->name));
16682: FREE_AND_NULL(str)
16683: return (XML_SCHEMAP_SRC_CT_1);
16684: }
16685: } else {
16686: ret = XML_SCHEMAP_SRC_CT_1;
16687: }
16688: }
16689: if (ret > 0) {
16690: xmlChar *str = NULL;
16691: if (WXS_IS_RESTRICTION(type)) {
16692: xmlSchemaPCustomErr(ctxt,
16693: XML_SCHEMAP_SRC_CT_1,
16694: WXS_BASIC_CAST type, NULL,
16695: "If <simpleContent> and <restriction> is used, the "
16696: "base type must be a simple type or a complex type with "
16697: "mixed content and particle emptiable. The base type "
16698: "'%s' is none of those",
16699: xmlSchemaFormatQName(&str, base->targetNamespace,
16700: base->name));
16701: } else {
16702: xmlSchemaPCustomErr(ctxt,
16703: XML_SCHEMAP_SRC_CT_1,
16704: WXS_BASIC_CAST type, NULL,
16705: "If <simpleContent> and <extension> is used, the "
16706: "base type must be a simple type. The base type '%s' "
16707: "is a complex type",
16708: xmlSchemaFormatQName(&str, base->targetNamespace,
16709: base->name));
16710: }
16711: FREE_AND_NULL(str)
16712: }
16713: }
16714: /*
16715: * SPEC (3) "The corresponding complex type definition component must
16716: * satisfy the conditions set out in Constraints on Complex Type
16717: * Definition Schema Components (�3.4.6);"
16718: * NOTE (3) will be done in xmlSchemaTypeFixup().
16719: */
16720: /*
16721: * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16722: * above for {attribute wildcard} is satisfied, the intensional
16723: * intersection must be expressible, as defined in Attribute Wildcard
16724: * Intersection (�3.10.6).
16725: * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16726: */
16727: return (ret);
16728: }
16729:
16730: #ifdef ENABLE_PARTICLE_RESTRICTION
16731: /**
16732: * xmlSchemaCheckParticleRangeOK:
16733: * @ctxt: the schema parser context
16734: * @type: the complex type definition
16735: *
16736: * (3.9.6) Constraints on Particle Schema Components
16737: * Schema Component Constraint:
16738: * Occurrence Range OK (range-ok)
16739: *
16740: * STATUS: complete
16741: *
16742: * Returns 0 if the constraints are satisfied, a positive
16743: * error code if not and -1 if an internal error occured.
16744: */
16745: static int
16746: xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16747: int bmin, int bmax)
16748: {
16749: if (rmin < bmin)
16750: return (1);
16751: if ((bmax != UNBOUNDED) &&
16752: (rmax > bmax))
16753: return (1);
16754: return (0);
16755: }
16756:
16757: /**
16758: * xmlSchemaCheckRCaseNameAndTypeOK:
16759: * @ctxt: the schema parser context
16760: * @r: the restricting element declaration particle
16761: * @b: the base element declaration particle
16762: *
16763: * (3.9.6) Constraints on Particle Schema Components
16764: * Schema Component Constraint:
16765: * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16766: * (rcase-NameAndTypeOK)
16767: *
16768: * STATUS:
16769: * MISSING (3.2.3)
16770: * CLARIFY: (3.2.2)
16771: *
16772: * Returns 0 if the constraints are satisfied, a positive
16773: * error code if not and -1 if an internal error occured.
16774: */
16775: static int
16776: xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16777: xmlSchemaParticlePtr r,
16778: xmlSchemaParticlePtr b)
16779: {
16780: xmlSchemaElementPtr elemR, elemB;
16781:
16782: /* TODO: Error codes (rcase-NameAndTypeOK). */
16783: elemR = (xmlSchemaElementPtr) r->children;
16784: elemB = (xmlSchemaElementPtr) b->children;
16785: /*
16786: * SPEC (1) "The declarations' {name}s and {target namespace}s are
16787: * the same."
16788: */
16789: if ((elemR != elemB) &&
16790: ((! xmlStrEqual(elemR->name, elemB->name)) ||
16791: (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16792: return (1);
16793: /*
16794: * SPEC (2) "R's occurrence range is a valid restriction of B's
16795: * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16796: */
16797: if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16798: b->minOccurs, b->maxOccurs) != 0)
16799: return (1);
16800: /*
16801: * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16802: * {scope} are global."
16803: */
16804: if (elemR == elemB)
16805: return (0);
16806: /*
16807: * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16808: */
16809: if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16810: (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16811: return (1);
16812: /*
16813: * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16814: * or is not fixed, or R's declaration's {value constraint} is fixed
16815: * with the same value."
16816: */
16817: if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16818: ((elemR->value == NULL) ||
16819: ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16820: /* TODO: Equality of the initial value or normalized or canonical? */
16821: (! xmlStrEqual(elemR->value, elemB->value))))
16822: return (1);
16823: /*
16824: * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16825: * definitions} is a subset of B's declaration's {identity-constraint
16826: * definitions}, if any."
16827: */
16828: if (elemB->idcs != NULL) {
16829: /* TODO */
16830: }
16831: /*
16832: * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16833: * superset of B's declaration's {disallowed substitutions}."
16834: */
16835: if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16836: ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16837: ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16838: ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16839: ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16840: ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16841: return (1);
16842: /*
16843: * SPEC (3.2.5) "R's {type definition} is validly derived given
16844: * {extension, list, union} from B's {type definition}"
16845: *
16846: * BADSPEC TODO: What's the point of adding "list" and "union" to the
16847: * set, if the corresponding constraints handle "restriction" and
16848: * "extension" only?
16849: *
16850: */
16851: {
16852: int set = 0;
16853:
16854: set |= SUBSET_EXTENSION;
16855: set |= SUBSET_LIST;
16856: set |= SUBSET_UNION;
16857: if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16858: elemB->subtypes, set) != 0)
16859: return (1);
16860: }
16861: return (0);
16862: }
16863:
16864: /**
16865: * xmlSchemaCheckRCaseNSCompat:
16866: * @ctxt: the schema parser context
16867: * @r: the restricting element declaration particle
16868: * @b: the base wildcard particle
16869: *
16870: * (3.9.6) Constraints on Particle Schema Components
16871: * Schema Component Constraint:
16872: * Particle Derivation OK (Elt:Any -- NSCompat)
16873: * (rcase-NSCompat)
16874: *
16875: * STATUS: complete
16876: *
16877: * Returns 0 if the constraints are satisfied, a positive
16878: * error code if not and -1 if an internal error occured.
16879: */
16880: static int
16881: xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16882: xmlSchemaParticlePtr r,
16883: xmlSchemaParticlePtr b)
16884: {
16885: /* TODO:Error codes (rcase-NSCompat). */
16886: /*
16887: * SPEC "For an element declaration particle to be a �valid restriction�
16888: * of a wildcard particle all of the following must be true:"
16889: *
16890: * SPEC (1) "The element declaration's {target namespace} is �valid�
16891: * with respect to the wildcard's {namespace constraint} as defined by
16892: * Wildcard allows Namespace Name (�3.10.4)."
16893: */
16894: if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16895: ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16896: return (1);
16897: /*
16898: * SPEC (2) "R's occurrence range is a valid restriction of B's
16899: * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16900: */
16901: if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16902: b->minOccurs, b->maxOccurs) != 0)
16903: return (1);
16904:
16905: return (0);
16906: }
16907:
16908: /**
16909: * xmlSchemaCheckRCaseRecurseAsIfGroup:
16910: * @ctxt: the schema parser context
16911: * @r: the restricting element declaration particle
16912: * @b: the base model group particle
16913: *
16914: * (3.9.6) Constraints on Particle Schema Components
16915: * Schema Component Constraint:
16916: * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16917: * (rcase-RecurseAsIfGroup)
16918: *
16919: * STATUS: TODO
16920: *
16921: * Returns 0 if the constraints are satisfied, a positive
16922: * error code if not and -1 if an internal error occured.
16923: */
16924: static int
16925: xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16926: xmlSchemaParticlePtr r,
16927: xmlSchemaParticlePtr b)
16928: {
16929: /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16930: TODO
16931: return (0);
16932: }
16933:
16934: /**
16935: * xmlSchemaCheckRCaseNSSubset:
16936: * @ctxt: the schema parser context
16937: * @r: the restricting wildcard particle
16938: * @b: the base wildcard particle
16939: *
16940: * (3.9.6) Constraints on Particle Schema Components
16941: * Schema Component Constraint:
16942: * Particle Derivation OK (Any:Any -- NSSubset)
16943: * (rcase-NSSubset)
16944: *
16945: * STATUS: complete
16946: *
16947: * Returns 0 if the constraints are satisfied, a positive
16948: * error code if not and -1 if an internal error occured.
16949: */
16950: static int
16951: xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16952: xmlSchemaParticlePtr r,
16953: xmlSchemaParticlePtr b,
16954: int isAnyTypeBase)
16955: {
16956: /* TODO: Error codes (rcase-NSSubset). */
16957: /*
16958: * SPEC (1) "R's occurrence range is a valid restriction of B's
16959: * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16960: */
16961: if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16962: b->minOccurs, b->maxOccurs))
16963: return (1);
16964: /*
16965: * SPEC (2) "R's {namespace constraint} must be an intensional subset
16966: * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16967: */
16968: if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16969: (xmlSchemaWildcardPtr) b->children))
16970: return (1);
16971: /*
16972: * SPEC (3) "Unless B is the content model wildcard of the �ur-type
16973: * definition�, R's {process contents} must be identical to or stronger
16974: * than B's {process contents}, where strict is stronger than lax is
16975: * stronger than skip."
16976: */
16977: if (! isAnyTypeBase) {
16978: if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16979: ((xmlSchemaWildcardPtr) b->children)->processContents)
16980: return (1);
16981: }
16982:
16983: return (0);
16984: }
16985:
16986: /**
16987: * xmlSchemaCheckCOSParticleRestrict:
16988: * @ctxt: the schema parser context
16989: * @type: the complex type definition
16990: *
16991: * (3.9.6) Constraints on Particle Schema Components
16992: * Schema Component Constraint:
16993: * Particle Valid (Restriction) (cos-particle-restrict)
16994: *
16995: * STATUS: TODO
16996: *
16997: * Returns 0 if the constraints are satisfied, a positive
16998: * error code if not and -1 if an internal error occured.
16999: */
17000: static int
17001: xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17002: xmlSchemaParticlePtr r,
17003: xmlSchemaParticlePtr b)
17004: {
17005: int ret = 0;
17006:
17007: /*part = WXS_TYPE_PARTICLE(type);
17008: basePart = WXS_TYPE_PARTICLE(base);
17009: */
17010:
17011: TODO
17012:
17013: /*
17014: * SPEC (1) "They are the same particle."
17015: */
17016: if (r == b)
17017: return (0);
17018:
17019:
17020: return (0);
17021: }
17022:
17023: #if 0
17024: /**
17025: * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17026: * @ctxt: the schema parser context
17027: * @r: the model group particle
17028: * @b: the base wildcard particle
17029: *
17030: * (3.9.6) Constraints on Particle Schema Components
17031: * Schema Component Constraint:
17032: * Particle Derivation OK (All/Choice/Sequence:Any --
17033: * NSRecurseCheckCardinality)
17034: * (rcase-NSRecurseCheckCardinality)
17035: *
17036: * STATUS: TODO: subst-groups
17037: *
17038: * Returns 0 if the constraints are satisfied, a positive
17039: * error code if not and -1 if an internal error occured.
17040: */
17041: static int
17042: xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17043: xmlSchemaParticlePtr r,
17044: xmlSchemaParticlePtr b)
17045: {
17046: xmlSchemaParticlePtr part;
17047: /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17048: if ((r->children == NULL) || (r->children->children == NULL))
17049: return (-1);
17050: /*
17051: * SPEC "For a group particle to be a �valid restriction� of a
17052: * wildcard particle..."
17053: *
17054: * SPEC (1) "Every member of the {particles} of the group is a �valid
17055: * restriction� of the wildcard as defined by
17056: * Particle Valid (Restriction) (�3.9.6)."
17057: */
17058: part = (xmlSchemaParticlePtr) r->children->children;
17059: do {
17060: if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17061: return (1);
17062: part = (xmlSchemaParticlePtr) part->next;
17063: } while (part != NULL);
17064: /*
17065: * SPEC (2) "The effective total range of the group [...] is a
17066: * valid restriction of B's occurrence range as defined by
17067: * Occurrence Range OK (�3.9.6)."
17068: */
17069: if (xmlSchemaCheckParticleRangeOK(
17070: xmlSchemaGetParticleTotalRangeMin(r),
17071: xmlSchemaGetParticleTotalRangeMax(r),
17072: b->minOccurs, b->maxOccurs) != 0)
17073: return (1);
17074: return (0);
17075: }
17076: #endif
17077:
17078: /**
17079: * xmlSchemaCheckRCaseRecurse:
17080: * @ctxt: the schema parser context
17081: * @r: the <all> or <sequence> model group particle
17082: * @b: the base <all> or <sequence> model group particle
17083: *
17084: * (3.9.6) Constraints on Particle Schema Components
17085: * Schema Component Constraint:
17086: * Particle Derivation OK (All:All,Sequence:Sequence --
17087: Recurse)
17088: * (rcase-Recurse)
17089: *
17090: * STATUS: ?
17091: * TODO: subst-groups
17092: *
17093: * Returns 0 if the constraints are satisfied, a positive
17094: * error code if not and -1 if an internal error occured.
17095: */
17096: static int
17097: xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17098: xmlSchemaParticlePtr r,
17099: xmlSchemaParticlePtr b)
17100: {
17101: /* xmlSchemaParticlePtr part; */
17102: /* TODO: Error codes (rcase-Recurse). */
17103: if ((r->children == NULL) || (b->children == NULL) ||
17104: (r->children->type != b->children->type))
17105: return (-1);
17106: /*
17107: * SPEC "For an all or sequence group particle to be a �valid
17108: * restriction� of another group particle with the same {compositor}..."
17109: *
17110: * SPEC (1) "R's occurrence range is a valid restriction of B's
17111: * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17112: */
17113: if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17114: b->minOccurs, b->maxOccurs))
17115: return (1);
17116:
17117:
17118: return (0);
17119: }
17120:
17121: #endif
17122:
17123: #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17124: xmlSchemaPCustomErrExt(pctxt, \
17125: XML_SCHEMAP_INVALID_FACET_VALUE, \
17126: WXS_BASIC_CAST fac1, fac1->node, \
17127: "It is an error for both '%s' and '%s' to be specified on the "\
17128: "same type definition", \
17129: BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17130: BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17131:
17132: #define FACET_RESTR_ERR(fac1, msg) \
17133: xmlSchemaPCustomErr(pctxt, \
17134: XML_SCHEMAP_INVALID_FACET_VALUE, \
17135: WXS_BASIC_CAST fac1, fac1->node, \
17136: msg, NULL);
17137:
17138: #define FACET_RESTR_FIXED_ERR(fac) \
17139: xmlSchemaPCustomErr(pctxt, \
17140: XML_SCHEMAP_INVALID_FACET_VALUE, \
17141: WXS_BASIC_CAST fac, fac->node, \
17142: "The base type's facet is 'fixed', thus the value must not " \
17143: "differ", NULL);
17144:
17145: static void
17146: xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17147: xmlSchemaFacetPtr facet1,
17148: xmlSchemaFacetPtr facet2,
17149: int lessGreater,
17150: int orEqual,
17151: int ofBase)
17152: {
17153: xmlChar *msg = NULL;
17154:
17155: msg = xmlStrdup(BAD_CAST "'");
17156: msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17157: msg = xmlStrcat(msg, BAD_CAST "' has to be");
17158: if (lessGreater == 0)
17159: msg = xmlStrcat(msg, BAD_CAST " equal to");
17160: if (lessGreater == 1)
17161: msg = xmlStrcat(msg, BAD_CAST " greater than");
17162: else
17163: msg = xmlStrcat(msg, BAD_CAST " less than");
17164:
17165: if (orEqual)
17166: msg = xmlStrcat(msg, BAD_CAST " or equal to");
17167: msg = xmlStrcat(msg, BAD_CAST " '");
17168: msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17169: if (ofBase)
17170: msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17171: else
17172: msg = xmlStrcat(msg, BAD_CAST "'");
17173:
17174: xmlSchemaPCustomErr(pctxt,
17175: XML_SCHEMAP_INVALID_FACET_VALUE,
17176: WXS_BASIC_CAST facet1, NULL,
17177: (const char *) msg, NULL);
17178:
17179: if (msg != NULL)
17180: xmlFree(msg);
17181: }
17182:
17183: /*
17184: * xmlSchemaDeriveAndValidateFacets:
17185: *
17186: * Schema Component Constraint: Simple Type Restriction (Facets)
17187: * (st-restrict-facets)
17188: */
17189: static int
17190: xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17191: xmlSchemaTypePtr type)
17192: {
17193: xmlSchemaTypePtr base = type->baseType;
17194: xmlSchemaFacetLinkPtr link, cur, last = NULL;
17195: xmlSchemaFacetPtr facet, bfacet,
17196: flength = NULL, ftotdig = NULL, ffracdig = NULL,
17197: fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17198: fmininc = NULL, fmaxinc = NULL,
17199: fminexc = NULL, fmaxexc = NULL,
17200: bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17201: bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17202: bfmininc = NULL, bfmaxinc = NULL,
17203: bfminexc = NULL, bfmaxexc = NULL;
17204: int res; /* err = 0, fixedErr; */
17205:
17206: /*
17207: * SPEC st-restrict-facets 1:
17208: * "The {variety} of R is the same as that of B."
17209: */
17210: /*
17211: * SPEC st-restrict-facets 2:
17212: * "If {variety} is atomic, the {primitive type definition}
17213: * of R is the same as that of B."
17214: *
17215: * NOTE: we leave 1 & 2 out for now, since this will be
17216: * satisfied by the derivation process.
17217: * CONSTRUCTION TODO: Maybe needed if using a construction API.
17218: */
17219: /*
17220: * SPEC st-restrict-facets 3:
17221: * "The {facets} of R are the union of S and the {facets}
17222: * of B, eliminating duplicates. To eliminate duplicates,
17223: * when a facet of the same kind occurs in both S and the
17224: * {facets} of B, the one in the {facets} of B is not
17225: * included, with the exception of enumeration and pattern
17226: * facets, for which multiple occurrences with distinct values
17227: * are allowed."
17228: */
17229:
17230: if ((type->facetSet == NULL) && (base->facetSet == NULL))
17231: return (0);
17232:
17233: last = type->facetSet;
17234: if (last != NULL)
17235: while (last->next != NULL)
17236: last = last->next;
17237:
17238: for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17239: facet = cur->facet;
17240: switch (facet->type) {
17241: case XML_SCHEMA_FACET_LENGTH:
17242: flength = facet; break;
17243: case XML_SCHEMA_FACET_MINLENGTH:
17244: fminlen = facet; break;
17245: case XML_SCHEMA_FACET_MININCLUSIVE:
17246: fmininc = facet; break;
17247: case XML_SCHEMA_FACET_MINEXCLUSIVE:
17248: fminexc = facet; break;
17249: case XML_SCHEMA_FACET_MAXLENGTH:
17250: fmaxlen = facet; break;
17251: case XML_SCHEMA_FACET_MAXINCLUSIVE:
17252: fmaxinc = facet; break;
17253: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17254: fmaxexc = facet; break;
17255: case XML_SCHEMA_FACET_TOTALDIGITS:
17256: ftotdig = facet; break;
17257: case XML_SCHEMA_FACET_FRACTIONDIGITS:
17258: ffracdig = facet; break;
17259: default:
17260: break;
17261: }
17262: }
17263: for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17264: facet = cur->facet;
17265: switch (facet->type) {
17266: case XML_SCHEMA_FACET_LENGTH:
17267: bflength = facet; break;
17268: case XML_SCHEMA_FACET_MINLENGTH:
17269: bfminlen = facet; break;
17270: case XML_SCHEMA_FACET_MININCLUSIVE:
17271: bfmininc = facet; break;
17272: case XML_SCHEMA_FACET_MINEXCLUSIVE:
17273: bfminexc = facet; break;
17274: case XML_SCHEMA_FACET_MAXLENGTH:
17275: bfmaxlen = facet; break;
17276: case XML_SCHEMA_FACET_MAXINCLUSIVE:
17277: bfmaxinc = facet; break;
17278: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17279: bfmaxexc = facet; break;
17280: case XML_SCHEMA_FACET_TOTALDIGITS:
17281: bftotdig = facet; break;
17282: case XML_SCHEMA_FACET_FRACTIONDIGITS:
17283: bffracdig = facet; break;
17284: default:
17285: break;
17286: }
17287: }
17288: /*
17289: * length and minLength or maxLength (2.2) + (3.2)
17290: */
17291: if (flength && (fminlen || fmaxlen)) {
17292: FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17293: "either of 'minLength' or 'maxLength' to be specified on "
17294: "the same type definition")
17295: }
17296: /*
17297: * Mutual exclusions in the same derivation step.
17298: */
17299: if ((fmaxinc) && (fmaxexc)) {
17300: /*
17301: * SCC "maxInclusive and maxExclusive"
17302: */
17303: FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17304: }
17305: if ((fmininc) && (fminexc)) {
17306: /*
17307: * SCC "minInclusive and minExclusive"
17308: */
17309: FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17310: }
17311:
17312: if (flength && bflength) {
17313: /*
17314: * SCC "length valid restriction"
17315: * The values have to be equal.
17316: */
17317: res = xmlSchemaCompareValues(flength->val, bflength->val);
17318: if (res == -2)
17319: goto internal_error;
17320: if (res != 0)
17321: xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17322: if ((res != 0) && (bflength->fixed)) {
17323: FACET_RESTR_FIXED_ERR(flength)
17324: }
17325:
17326: }
17327: if (fminlen && bfminlen) {
17328: /*
17329: * SCC "minLength valid restriction"
17330: * minLength >= BASE minLength
17331: */
17332: res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17333: if (res == -2)
17334: goto internal_error;
17335: if (res == -1)
17336: xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17337: if ((res != 0) && (bfminlen->fixed)) {
17338: FACET_RESTR_FIXED_ERR(fminlen)
17339: }
17340: }
17341: if (fmaxlen && bfmaxlen) {
17342: /*
17343: * SCC "maxLength valid restriction"
17344: * maxLength <= BASE minLength
17345: */
17346: res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17347: if (res == -2)
17348: goto internal_error;
17349: if (res == 1)
17350: xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17351: if ((res != 0) && (bfmaxlen->fixed)) {
17352: FACET_RESTR_FIXED_ERR(fmaxlen)
17353: }
17354: }
17355: /*
17356: * SCC "length and minLength or maxLength"
17357: */
17358: if (! flength)
17359: flength = bflength;
17360: if (flength) {
17361: if (! fminlen)
17362: fminlen = bfminlen;
17363: if (fminlen) {
17364: /* (1.1) length >= minLength */
17365: res = xmlSchemaCompareValues(flength->val, fminlen->val);
17366: if (res == -2)
17367: goto internal_error;
17368: if (res == -1)
17369: xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17370: }
17371: if (! fmaxlen)
17372: fmaxlen = bfmaxlen;
17373: if (fmaxlen) {
17374: /* (2.1) length <= maxLength */
17375: res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17376: if (res == -2)
17377: goto internal_error;
17378: if (res == 1)
17379: xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17380: }
17381: }
17382: if (fmaxinc) {
17383: /*
17384: * "maxInclusive"
17385: */
17386: if (fmininc) {
17387: /* SCC "maxInclusive >= minInclusive" */
17388: res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17389: if (res == -2)
17390: goto internal_error;
17391: if (res == -1) {
17392: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17393: }
17394: }
17395: /*
17396: * SCC "maxInclusive valid restriction"
17397: */
17398: if (bfmaxinc) {
17399: /* maxInclusive <= BASE maxInclusive */
17400: res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17401: if (res == -2)
17402: goto internal_error;
17403: if (res == 1)
17404: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17405: if ((res != 0) && (bfmaxinc->fixed)) {
17406: FACET_RESTR_FIXED_ERR(fmaxinc)
17407: }
17408: }
17409: if (bfmaxexc) {
17410: /* maxInclusive < BASE maxExclusive */
17411: res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17412: if (res == -2)
17413: goto internal_error;
17414: if (res != -1) {
17415: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17416: }
17417: }
17418: if (bfmininc) {
17419: /* maxInclusive >= BASE minInclusive */
17420: res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17421: if (res == -2)
17422: goto internal_error;
17423: if (res == -1) {
17424: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17425: }
17426: }
17427: if (bfminexc) {
17428: /* maxInclusive > BASE minExclusive */
17429: res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17430: if (res == -2)
17431: goto internal_error;
17432: if (res != 1) {
17433: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17434: }
17435: }
17436: }
17437: if (fmaxexc) {
17438: /*
17439: * "maxExclusive >= minExclusive"
17440: */
17441: if (fminexc) {
17442: res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17443: if (res == -2)
17444: goto internal_error;
17445: if (res == -1) {
17446: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17447: }
17448: }
17449: /*
17450: * "maxExclusive valid restriction"
17451: */
17452: if (bfmaxexc) {
17453: /* maxExclusive <= BASE maxExclusive */
17454: res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17455: if (res == -2)
17456: goto internal_error;
17457: if (res == 1) {
17458: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17459: }
17460: if ((res != 0) && (bfmaxexc->fixed)) {
17461: FACET_RESTR_FIXED_ERR(fmaxexc)
17462: }
17463: }
17464: if (bfmaxinc) {
17465: /* maxExclusive <= BASE maxInclusive */
17466: res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17467: if (res == -2)
17468: goto internal_error;
17469: if (res == 1) {
17470: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17471: }
17472: }
17473: if (bfmininc) {
17474: /* maxExclusive > BASE minInclusive */
17475: res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17476: if (res == -2)
17477: goto internal_error;
17478: if (res != 1) {
17479: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17480: }
17481: }
17482: if (bfminexc) {
17483: /* maxExclusive > BASE minExclusive */
17484: res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17485: if (res == -2)
17486: goto internal_error;
17487: if (res != 1) {
17488: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17489: }
17490: }
17491: }
17492: if (fminexc) {
17493: /*
17494: * "minExclusive < maxInclusive"
17495: */
17496: if (fmaxinc) {
17497: res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17498: if (res == -2)
17499: goto internal_error;
17500: if (res != -1) {
17501: xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17502: }
17503: }
17504: /*
17505: * "minExclusive valid restriction"
17506: */
17507: if (bfminexc) {
17508: /* minExclusive >= BASE minExclusive */
17509: res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17510: if (res == -2)
17511: goto internal_error;
17512: if (res == -1) {
17513: xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17514: }
17515: if ((res != 0) && (bfminexc->fixed)) {
17516: FACET_RESTR_FIXED_ERR(fminexc)
17517: }
17518: }
17519: if (bfmaxinc) {
17520: /* minExclusive <= BASE maxInclusive */
17521: res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17522: if (res == -2)
17523: goto internal_error;
17524: if (res == 1) {
17525: xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17526: }
17527: }
17528: if (bfmininc) {
17529: /* minExclusive >= BASE minInclusive */
17530: res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17531: if (res == -2)
17532: goto internal_error;
17533: if (res == -1) {
17534: xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17535: }
17536: }
17537: if (bfmaxexc) {
17538: /* minExclusive < BASE maxExclusive */
17539: res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17540: if (res == -2)
17541: goto internal_error;
17542: if (res != -1) {
17543: xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17544: }
17545: }
17546: }
17547: if (fmininc) {
17548: /*
17549: * "minInclusive < maxExclusive"
17550: */
17551: if (fmaxexc) {
17552: res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17553: if (res == -2)
17554: goto internal_error;
17555: if (res != -1) {
17556: xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17557: }
17558: }
17559: /*
17560: * "minExclusive valid restriction"
17561: */
17562: if (bfmininc) {
17563: /* minInclusive >= BASE minInclusive */
17564: res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17565: if (res == -2)
17566: goto internal_error;
17567: if (res == -1) {
17568: xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17569: }
17570: if ((res != 0) && (bfmininc->fixed)) {
17571: FACET_RESTR_FIXED_ERR(fmininc)
17572: }
17573: }
17574: if (bfmaxinc) {
17575: /* minInclusive <= BASE maxInclusive */
17576: res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17577: if (res == -2)
17578: goto internal_error;
17579: if (res == 1) {
17580: xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17581: }
17582: }
17583: if (bfminexc) {
17584: /* minInclusive > BASE minExclusive */
17585: res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17586: if (res == -2)
17587: goto internal_error;
17588: if (res != 1)
17589: xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17590: }
17591: if (bfmaxexc) {
17592: /* minInclusive < BASE maxExclusive */
17593: res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17594: if (res == -2)
17595: goto internal_error;
17596: if (res != -1)
17597: xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17598: }
17599: }
17600: if (ftotdig && bftotdig) {
17601: /*
17602: * SCC " totalDigits valid restriction"
17603: * totalDigits <= BASE totalDigits
17604: */
17605: res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17606: if (res == -2)
17607: goto internal_error;
17608: if (res == 1)
17609: xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17610: -1, 1, 1);
17611: if ((res != 0) && (bftotdig->fixed)) {
17612: FACET_RESTR_FIXED_ERR(ftotdig)
17613: }
17614: }
17615: if (ffracdig && bffracdig) {
17616: /*
17617: * SCC "fractionDigits valid restriction"
17618: * fractionDigits <= BASE fractionDigits
17619: */
17620: res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17621: if (res == -2)
17622: goto internal_error;
17623: if (res == 1)
17624: xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17625: -1, 1, 1);
17626: if ((res != 0) && (bffracdig->fixed)) {
17627: FACET_RESTR_FIXED_ERR(ffracdig)
17628: }
17629: }
17630: /*
17631: * SCC "fractionDigits less than or equal to totalDigits"
17632: */
17633: if (! ftotdig)
17634: ftotdig = bftotdig;
17635: if (! ffracdig)
17636: ffracdig = bffracdig;
17637: if (ftotdig && ffracdig) {
17638: res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17639: if (res == -2)
17640: goto internal_error;
17641: if (res == 1)
17642: xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17643: -1, 1, 0);
17644: }
17645: /*
17646: * *Enumerations* won' be added here, since only the first set
17647: * of enumerations in the ancestor-or-self axis is used
17648: * for validation, plus we need to use the base type of those
17649: * enumerations for whitespace.
17650: *
17651: * *Patterns*: won't be add here, since they are ORed at
17652: * type level and ANDed at ancestor level. This will
17653: * happed during validation by walking the base axis
17654: * of the type.
17655: */
17656: for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17657: bfacet = cur->facet;
17658: /*
17659: * Special handling of enumerations and patterns.
17660: * TODO: hmm, they should not appear in the set, so remove this.
17661: */
17662: if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17663: (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17664: continue;
17665: /*
17666: * Search for a duplicate facet in the current type.
17667: */
17668: link = type->facetSet;
17669: /* err = 0; */
17670: /* fixedErr = 0; */
17671: while (link != NULL) {
17672: facet = link->facet;
17673: if (facet->type == bfacet->type) {
17674: switch (facet->type) {
17675: case XML_SCHEMA_FACET_WHITESPACE:
17676: /*
17677: * The whitespace must be stronger.
17678: */
17679: if (facet->whitespace < bfacet->whitespace) {
17680: FACET_RESTR_ERR(facet,
17681: "The 'whitespace' value has to be equal to "
17682: "or stronger than the 'whitespace' value of "
17683: "the base type")
17684: }
17685: if ((bfacet->fixed) &&
17686: (facet->whitespace != bfacet->whitespace)) {
17687: FACET_RESTR_FIXED_ERR(facet)
17688: }
17689: break;
17690: default:
17691: break;
17692: }
17693: /* Duplicate found. */
17694: break;
17695: }
17696: link = link->next;
17697: }
17698: /*
17699: * If no duplicate was found: add the base types's facet
17700: * to the set.
17701: */
17702: if (link == NULL) {
17703: link = (xmlSchemaFacetLinkPtr)
17704: xmlMalloc(sizeof(xmlSchemaFacetLink));
17705: if (link == NULL) {
17706: xmlSchemaPErrMemory(pctxt,
17707: "deriving facets, creating a facet link", NULL);
17708: return (-1);
17709: }
17710: link->facet = cur->facet;
17711: link->next = NULL;
17712: if (last == NULL)
17713: type->facetSet = link;
17714: else
17715: last->next = link;
17716: last = link;
17717: }
17718:
17719: }
17720:
17721: return (0);
17722: internal_error:
17723: PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17724: "an error occured");
17725: return (-1);
17726: }
17727:
17728: static int
17729: xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17730: xmlSchemaTypePtr type)
17731: {
17732: xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17733: /*
17734: * The actual value is then formed by replacing any union type
17735: * definition in the �explicit members� with the members of their
17736: * {member type definitions}, in order.
17737: *
17738: * TODO: There's a bug entry at
17739: * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17740: * which indicates that we'll keep the union types the future.
17741: */
17742: link = type->memberTypes;
17743: while (link != NULL) {
17744:
17745: if (WXS_IS_TYPE_NOT_FIXED(link->type))
17746: xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17747:
17748: if (WXS_IS_UNION(link->type)) {
17749: subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17750: if (subLink != NULL) {
17751: link->type = subLink->type;
17752: if (subLink->next != NULL) {
17753: lastLink = link->next;
17754: subLink = subLink->next;
17755: prevLink = link;
17756: while (subLink != NULL) {
17757: newLink = (xmlSchemaTypeLinkPtr)
17758: xmlMalloc(sizeof(xmlSchemaTypeLink));
17759: if (newLink == NULL) {
17760: xmlSchemaPErrMemory(pctxt, "allocating a type link",
17761: NULL);
17762: return (-1);
17763: }
17764: newLink->type = subLink->type;
17765: prevLink->next = newLink;
17766: prevLink = newLink;
17767: newLink->next = lastLink;
17768:
17769: subLink = subLink->next;
17770: }
17771: }
17772: }
17773: }
17774: link = link->next;
17775: }
17776: return (0);
17777: }
17778:
17779: static void
17780: xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17781: {
17782: int has = 0, needVal = 0, normVal = 0;
17783:
17784: has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17785: if (has) {
17786: needVal = (type->baseType->flags &
17787: XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17788: normVal = (type->baseType->flags &
17789: XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17790: }
17791: if (type->facets != NULL) {
17792: xmlSchemaFacetPtr fac;
17793:
17794: for (fac = type->facets; fac != NULL; fac = fac->next) {
17795: switch (fac->type) {
17796: case XML_SCHEMA_FACET_WHITESPACE:
17797: break;
17798: case XML_SCHEMA_FACET_PATTERN:
17799: normVal = 1;
17800: has = 1;
17801: break;
17802: case XML_SCHEMA_FACET_ENUMERATION:
17803: needVal = 1;
17804: normVal = 1;
17805: has = 1;
17806: break;
17807: default:
17808: has = 1;
17809: break;
17810: }
17811: }
17812: }
17813: if (normVal)
17814: type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17815: if (needVal)
17816: type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17817: if (has)
17818: type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17819:
17820: if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17821: xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17822: /*
17823: * OPTIMIZE VAL TODO: Some facets need a computed value.
17824: */
17825: if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17826: (prim->builtInType != XML_SCHEMAS_STRING)) {
17827: type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17828: }
17829: }
17830: }
17831:
17832: static int
17833: xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17834: {
17835:
17836:
17837: /*
17838: * Evaluate the whitespace-facet value.
17839: */
17840: if (WXS_IS_LIST(type)) {
17841: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17842: return (0);
17843: } else if (WXS_IS_UNION(type))
17844: return (0);
17845:
17846: if (type->facetSet != NULL) {
17847: xmlSchemaFacetLinkPtr lin;
17848:
17849: for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17850: if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17851: switch (lin->facet->whitespace) {
17852: case XML_SCHEMAS_FACET_PRESERVE:
17853: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17854: break;
17855: case XML_SCHEMAS_FACET_REPLACE:
17856: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17857: break;
17858: case XML_SCHEMAS_FACET_COLLAPSE:
17859: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17860: break;
17861: default:
17862: return (-1);
17863: }
17864: return (0);
17865: }
17866: }
17867: }
17868: /*
17869: * For all �atomic� datatypes other than string (and types �derived�
17870: * by �restriction� from it) the value of whiteSpace is fixed to
17871: * collapse
17872: */
17873: {
17874: xmlSchemaTypePtr anc;
17875:
17876: for (anc = type->baseType; anc != NULL &&
17877: anc->builtInType != XML_SCHEMAS_ANYTYPE;
17878: anc = anc->baseType) {
17879:
17880: if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17881: if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17882: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17883:
17884: } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17885: (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17886: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17887:
17888: } else
17889: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17890: break;
17891: }
17892: }
17893: }
17894: return (0);
17895: }
17896:
17897: static int
17898: xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17899: xmlSchemaTypePtr type)
17900: {
17901: if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17902: return(0);
17903: if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17904: return(0);
17905: type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17906:
17907: if (WXS_IS_LIST(type)) {
17908: /*
17909: * Corresponds to <simpleType><list>...
17910: */
17911: if (type->subtypes == NULL) {
17912: /*
17913: * This one is really needed, so get out.
17914: */
17915: PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17916: "list type has no item-type assigned");
17917: return(-1);
17918: }
17919: } else if (WXS_IS_UNION(type)) {
17920: /*
17921: * Corresponds to <simpleType><union>...
17922: */
17923: if (type->memberTypes == NULL) {
17924: /*
17925: * This one is really needed, so get out.
17926: */
17927: PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17928: "union type has no member-types assigned");
17929: return(-1);
17930: }
17931: } else {
17932: /*
17933: * Corresponds to <simpleType><restriction>...
17934: */
17935: if (type->baseType == NULL) {
17936: PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17937: "type has no base-type assigned");
17938: return(-1);
17939: }
17940: if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17941: if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17942: return(-1);
17943: /*
17944: * Variety
17945: * If the <restriction> alternative is chosen, then the
17946: * {variety} of the {base type definition}.
17947: */
17948: if (WXS_IS_ATOMIC(type->baseType))
17949: type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17950: else if (WXS_IS_LIST(type->baseType)) {
17951: type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17952: /*
17953: * Inherit the itemType.
17954: */
17955: type->subtypes = type->baseType->subtypes;
17956: } else if (WXS_IS_UNION(type->baseType)) {
17957: type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17958: /*
17959: * NOTE that we won't assign the memberTypes of the base,
17960: * since this will make trouble when freeing them; we will
17961: * use a lookup function to access them instead.
17962: */
17963: }
17964: }
17965: return(0);
17966: }
17967:
17968: #ifdef DEBUG_TYPE
17969: static void
17970: xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17971: xmlSchemaTypePtr type)
17972: {
17973: if (type->node != NULL) {
17974: xmlGenericError(xmlGenericErrorContext,
17975: "Type of %s : %s:%d :", name,
17976: type->node->doc->URL,
17977: xmlGetLineNo(type->node));
17978: } else {
17979: xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
17980: }
17981: if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
17982: switch (type->contentType) {
17983: case XML_SCHEMA_CONTENT_SIMPLE:
17984: xmlGenericError(xmlGenericErrorContext, "simple\n");
17985: break;
17986: case XML_SCHEMA_CONTENT_ELEMENTS:
17987: xmlGenericError(xmlGenericErrorContext, "elements\n");
17988: break;
17989: case XML_SCHEMA_CONTENT_UNKNOWN:
17990: xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17991: break;
17992: case XML_SCHEMA_CONTENT_EMPTY:
17993: xmlGenericError(xmlGenericErrorContext, "empty\n");
17994: break;
17995: case XML_SCHEMA_CONTENT_MIXED:
17996: if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
17997: type->subtypes))
17998: xmlGenericError(xmlGenericErrorContext,
17999: "mixed as emptiable particle\n");
18000: else
18001: xmlGenericError(xmlGenericErrorContext, "mixed\n");
18002: break;
18003: /* Removed, since not used. */
18004: /*
18005: case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18006: xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18007: break;
18008: */
18009: case XML_SCHEMA_CONTENT_BASIC:
18010: xmlGenericError(xmlGenericErrorContext, "basic\n");
18011: break;
18012: default:
18013: xmlGenericError(xmlGenericErrorContext,
18014: "not registered !!!\n");
18015: break;
18016: }
18017: }
18018: }
18019: #endif
18020:
18021: /*
18022: * 3.14.6 Constraints on Simple Type Definition Schema Components
18023: */
18024: static int
18025: xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18026: xmlSchemaTypePtr type)
18027: {
18028: int res, olderrs = pctxt->nberrors;
18029:
18030: if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18031: return(-1);
18032:
18033: if (! WXS_IS_TYPE_NOT_FIXED(type))
18034: return(0);
18035:
18036: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18037: type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18038:
18039: if (type->baseType == NULL) {
18040: PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18041: "missing baseType");
18042: goto exit_failure;
18043: }
18044: if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18045: xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18046: /*
18047: * If a member type of a union is a union itself, we need to substitute
18048: * that member type for its member types.
18049: * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18050: * types in WXS 1.1.
18051: */
18052: if ((type->memberTypes != NULL) &&
18053: (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18054: return(-1);
18055: /*
18056: * SPEC src-simple-type 1
18057: * "The corresponding simple type definition, if any, must satisfy
18058: * the conditions set out in Constraints on Simple Type Definition
18059: * Schema Components (�3.14.6)."
18060: */
18061: /*
18062: * Schema Component Constraint: Simple Type Definition Properties Correct
18063: * (st-props-correct)
18064: */
18065: res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18066: HFAILURE HERROR
18067: /*
18068: * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18069: * (cos-st-restricts)
18070: */
18071: res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18072: HFAILURE HERROR
18073: /*
18074: * TODO: Removed the error report, since it got annoying to get an
18075: * extra error report, if anything failed until now.
18076: * Enable this if needed.
18077: *
18078: * xmlSchemaPErr(ctxt, type->node,
18079: * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18080: * "Simple type '%s' does not satisfy the constraints "
18081: * "on simple type definitions.\n",
18082: * type->name, NULL);
18083: */
18084: /*
18085: * Schema Component Constraint: Simple Type Restriction (Facets)
18086: * (st-restrict-facets)
18087: */
18088: res = xmlSchemaCheckFacetValues(type, pctxt);
18089: HFAILURE HERROR
18090: if ((type->facetSet != NULL) ||
18091: (type->baseType->facetSet != NULL)) {
18092: res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18093: HFAILURE HERROR
18094: }
18095: /*
18096: * Whitespace value.
18097: */
18098: res = xmlSchemaTypeFixupWhitespace(type);
18099: HFAILURE HERROR
18100: xmlSchemaTypeFixupOptimFacets(type);
18101:
18102: exit_error:
18103: #ifdef DEBUG_TYPE
18104: xmlSchemaDebugFixedType(pctxt, type);
18105: #endif
18106: if (olderrs != pctxt->nberrors)
18107: return(pctxt->err);
18108: return(0);
18109:
18110: exit_failure:
18111: #ifdef DEBUG_TYPE
18112: xmlSchemaDebugFixedType(pctxt, type);
18113: #endif
18114: return(-1);
18115: }
18116:
18117: static int
18118: xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18119: xmlSchemaTypePtr type)
18120: {
18121: int res = 0, olderrs = pctxt->nberrors;
18122: xmlSchemaTypePtr baseType = type->baseType;
18123:
18124: if (! WXS_IS_TYPE_NOT_FIXED(type))
18125: return(0);
18126: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18127: if (baseType == NULL) {
18128: PERROR_INT("xmlSchemaFixupComplexType",
18129: "missing baseType");
18130: goto exit_failure;
18131: }
18132: /*
18133: * Fixup the base type.
18134: */
18135: if (WXS_IS_TYPE_NOT_FIXED(baseType))
18136: xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18137: if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18138: /*
18139: * Skip fixup if the base type is invalid.
18140: * TODO: Generate a warning!
18141: */
18142: return(0);
18143: }
18144: /*
18145: * This basically checks if the base type can be derived.
18146: */
18147: res = xmlSchemaCheckSRCCT(pctxt, type);
18148: HFAILURE HERROR
18149: /*
18150: * Fixup the content type.
18151: */
18152: if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18153: /*
18154: * Corresponds to <complexType><simpleContent>...
18155: */
18156: if ((WXS_IS_COMPLEX(baseType)) &&
18157: (baseType->contentTypeDef != NULL) &&
18158: (WXS_IS_RESTRICTION(type))) {
18159: xmlSchemaTypePtr contentBase, content;
18160: #ifdef ENABLE_NAMED_LOCALS
18161: char buf[30];
18162: const xmlChar *tmpname;
18163: #endif
18164: /*
18165: * SPEC (1) If <restriction> + base type is <complexType>,
18166: * "whose own {content type} is a simple type..."
18167: */
18168: if (type->contentTypeDef != NULL) {
18169: /*
18170: * SPEC (1.1) "the simple type definition corresponding to the
18171: * <simpleType> among the [children] of <restriction> if there
18172: * is one;"
18173: * Note that this "<simpleType> among the [children]" was put
18174: * into ->contentTypeDef during parsing.
18175: */
18176: contentBase = type->contentTypeDef;
18177: type->contentTypeDef = NULL;
18178: } else {
18179: /*
18180: * (1.2) "...otherwise (<restriction> has no <simpleType>
18181: * among its [children]), the simple type definition which
18182: * is the {content type} of the ... base type."
18183: */
18184: contentBase = baseType->contentTypeDef;
18185: }
18186: /*
18187: * SPEC
18188: * "... a simple type definition which restricts the simple
18189: * type definition identified in clause 1.1 or clause 1.2
18190: * with a set of facet components"
18191: *
18192: * Create the anonymous simple type, which will be the content
18193: * type of the complex type.
18194: */
18195: #ifdef ENABLE_NAMED_LOCALS
18196: snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18197: tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18198: content = xmlSchemaAddType(pctxt, pctxt->schema,
18199: XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18200: type->node, 0);
18201: #else
18202: content = xmlSchemaAddType(pctxt, pctxt->schema,
18203: XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18204: type->node, 0);
18205: #endif
18206: if (content == NULL)
18207: goto exit_failure;
18208: /*
18209: * We will use the same node as for the <complexType>
18210: * to have it somehow anchored in the schema doc.
18211: */
18212: content->type = XML_SCHEMA_TYPE_SIMPLE;
18213: content->baseType = contentBase;
18214: /*
18215: * Move the facets, previously anchored on the
18216: * complexType during parsing.
18217: */
18218: content->facets = type->facets;
18219: type->facets = NULL;
18220: content->facetSet = type->facetSet;
18221: type->facetSet = NULL;
18222:
18223: type->contentTypeDef = content;
18224: if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18225: xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18226: /*
18227: * Fixup the newly created type. We don't need to check
18228: * for circularity here.
18229: */
18230: res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18231: HFAILURE HERROR
18232: res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18233: HFAILURE HERROR
18234:
18235: } else if ((WXS_IS_COMPLEX(baseType)) &&
18236: (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18237: (WXS_IS_RESTRICTION(type))) {
18238: /*
18239: * SPEC (2) If <restriction> + base is a mixed <complexType> with
18240: * an emptiable particle, then a simple type definition which
18241: * restricts the <restriction>'s <simpleType> child.
18242: */
18243: if ((type->contentTypeDef == NULL) ||
18244: (type->contentTypeDef->baseType == NULL)) {
18245: /*
18246: * TODO: Check if this ever happens.
18247: */
18248: xmlSchemaPCustomErr(pctxt,
18249: XML_SCHEMAP_INTERNAL,
18250: WXS_BASIC_CAST type, NULL,
18251: "Internal error: xmlSchemaTypeFixup, "
18252: "complex type '%s': the <simpleContent><restriction> "
18253: "is missing a <simpleType> child, but was not catched "
18254: "by xmlSchemaCheckSRCCT()", type->name);
18255: goto exit_failure;
18256: }
18257: } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18258: /*
18259: * SPEC (3) If <extension> + base is <complexType> with
18260: * <simpleType> content, "...then the {content type} of that
18261: * complex type definition"
18262: */
18263: if (baseType->contentTypeDef == NULL) {
18264: /*
18265: * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18266: * should have catched this already.
18267: */
18268: xmlSchemaPCustomErr(pctxt,
18269: XML_SCHEMAP_INTERNAL,
18270: WXS_BASIC_CAST type, NULL,
18271: "Internal error: xmlSchemaTypeFixup, "
18272: "complex type '%s': the <extension>ed base type is "
18273: "a complex type with no simple content type",
18274: type->name);
18275: goto exit_failure;
18276: }
18277: type->contentTypeDef = baseType->contentTypeDef;
18278: } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18279: /*
18280: * SPEC (4) <extension> + base is <simpleType>
18281: * "... then that simple type definition"
18282: */
18283: type->contentTypeDef = baseType;
18284: } else {
18285: /*
18286: * TODO: Check if this ever happens.
18287: */
18288: xmlSchemaPCustomErr(pctxt,
18289: XML_SCHEMAP_INTERNAL,
18290: WXS_BASIC_CAST type, NULL,
18291: "Internal error: xmlSchemaTypeFixup, "
18292: "complex type '%s' with <simpleContent>: unhandled "
18293: "derivation case", type->name);
18294: goto exit_failure;
18295: }
18296: } else {
18297: int dummySequence = 0;
18298: xmlSchemaParticlePtr particle =
18299: (xmlSchemaParticlePtr) type->subtypes;
18300: /*
18301: * Corresponds to <complexType><complexContent>...
18302: *
18303: * NOTE that the effective mixed was already set during parsing of
18304: * <complexType> and <complexContent>; its flag value is
18305: * XML_SCHEMAS_TYPE_MIXED.
18306: *
18307: * Compute the "effective content":
18308: * (2.1.1) + (2.1.2) + (2.1.3)
18309: */
18310: if ((particle == NULL) ||
18311: ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18312: ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18313: (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18314: ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18315: (particle->minOccurs == 0))) &&
18316: ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18317: if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18318: /*
18319: * SPEC (2.1.4) "If the �effective mixed� is true, then
18320: * a particle whose properties are as follows:..."
18321: *
18322: * Empty sequence model group with
18323: * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18324: * NOTE that we sill assign it the <complexType> node to
18325: * somehow anchor it in the doc.
18326: */
18327: if ((particle == NULL) ||
18328: (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18329: /*
18330: * Create the particle.
18331: */
18332: particle = xmlSchemaAddParticle(pctxt,
18333: type->node, 1, 1);
18334: if (particle == NULL)
18335: goto exit_failure;
18336: /*
18337: * Create the model group.
18338: */ /* URGENT TODO: avoid adding to pending items. */
18339: particle->children = (xmlSchemaTreeItemPtr)
18340: xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18341: XML_SCHEMA_TYPE_SEQUENCE, type->node);
18342: if (particle->children == NULL)
18343: goto exit_failure;
18344:
18345: type->subtypes = (xmlSchemaTypePtr) particle;
18346: }
18347: dummySequence = 1;
18348: type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18349: } else {
18350: /*
18351: * SPEC (2.1.5) "otherwise empty"
18352: */
18353: type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18354: }
18355: } else {
18356: /*
18357: * SPEC (2.2) "otherwise the particle corresponding to the
18358: * <all>, <choice>, <group> or <sequence> among the
18359: * [children]."
18360: */
18361: type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18362: }
18363: /*
18364: * Compute the "content type".
18365: */
18366: if (WXS_IS_RESTRICTION(type)) {
18367: /*
18368: * SPEC (3.1) "If <restriction>..."
18369: * (3.1.1) + (3.1.2) */
18370: if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18371: if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18372: type->contentType = XML_SCHEMA_CONTENT_MIXED;
18373: }
18374: } else {
18375: /*
18376: * SPEC (3.2) "If <extension>..."
18377: */
18378: if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18379: /*
18380: * SPEC (3.2.1)
18381: * "If the �effective content� is empty, then the
18382: * {content type} of the [...] base ..."
18383: */
18384: type->contentType = baseType->contentType;
18385: type->subtypes = baseType->subtypes;
18386: /*
18387: * Fixes bug #347316:
18388: * This is the case when the base type has a simple
18389: * type definition as content.
18390: */
18391: type->contentTypeDef = baseType->contentTypeDef;
18392: /*
18393: * NOTE that the effective mixed is ignored here.
18394: */
18395: } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18396: /*
18397: * SPEC (3.2.2)
18398: */
18399: if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18400: type->contentType = XML_SCHEMA_CONTENT_MIXED;
18401: } else {
18402: /*
18403: * SPEC (3.2.3)
18404: */
18405: if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18406: type->contentType = XML_SCHEMA_CONTENT_MIXED;
18407: /*
18408: * "A model group whose {compositor} is sequence and whose
18409: * {particles} are..."
18410: */
18411: if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18412: (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18413: ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18414: XML_SCHEMA_TYPE_ALL))
18415: {
18416: /*
18417: * SPEC cos-all-limited (1)
18418: */
18419: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18420: /* TODO: error code */
18421: XML_SCHEMAP_COS_ALL_LIMITED,
18422: WXS_ITEM_NODE(type), NULL,
18423: "The type has an 'all' model group in its "
18424: "{content type} and thus cannot be derived from "
18425: "a non-empty type, since this would produce a "
18426: "'sequence' model group containing the 'all' "
18427: "model group; 'all' model groups are not "
18428: "allowed to appear inside other model groups",
18429: NULL, NULL);
18430:
18431: } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18432: (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18433: ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18434: XML_SCHEMA_TYPE_ALL))
18435: {
18436: /*
18437: * SPEC cos-all-limited (1)
18438: */
18439: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18440: /* TODO: error code */
18441: XML_SCHEMAP_COS_ALL_LIMITED,
18442: WXS_ITEM_NODE(type), NULL,
18443: "A type cannot be derived by extension from a type "
18444: "which has an 'all' model group in its "
18445: "{content type}, since this would produce a "
18446: "'sequence' model group containing the 'all' "
18447: "model group; 'all' model groups are not "
18448: "allowed to appear inside other model groups",
18449: NULL, NULL);
18450:
18451: } else if (! dummySequence) {
18452: xmlSchemaTreeItemPtr effectiveContent =
18453: (xmlSchemaTreeItemPtr) type->subtypes;
18454: /*
18455: * Create the particle.
18456: */
18457: particle = xmlSchemaAddParticle(pctxt,
18458: type->node, 1, 1);
18459: if (particle == NULL)
18460: goto exit_failure;
18461: /*
18462: * Create the "sequence" model group.
18463: */
18464: particle->children = (xmlSchemaTreeItemPtr)
18465: xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18466: XML_SCHEMA_TYPE_SEQUENCE, type->node);
18467: if (particle->children == NULL)
18468: goto exit_failure;
18469: WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18470: /*
18471: * SPEC "the particle of the {content type} of
18472: * the ... base ..."
18473: * Create a duplicate of the base type's particle
18474: * and assign its "term" to it.
18475: */
18476: particle->children->children =
18477: (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18478: type->node,
1.1.1.2 ! misho 18479: ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
! 18480: ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
1.1 misho 18481: if (particle->children->children == NULL)
18482: goto exit_failure;
18483: particle = (xmlSchemaParticlePtr)
18484: particle->children->children;
18485: particle->children =
18486: ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18487: /*
18488: * SPEC "followed by the �effective content�."
18489: */
18490: particle->next = effectiveContent;
18491: /*
18492: * This all will result in:
18493: * new-particle
18494: * --> new-sequence(
18495: * new-particle
18496: * --> base-model,
18497: * this-particle
18498: * --> this-model
18499: * )
18500: */
18501: } else {
18502: /*
18503: * This is the case when there is already an empty
18504: * <sequence> with minOccurs==maxOccurs==1.
18505: * Just add the base types's content type.
18506: * NOTE that, although we miss to add an intermediate
18507: * <sequence>, this should produce no difference to
18508: * neither the regex compilation of the content model,
18509: * nor to the complex type contraints.
18510: */
18511: particle->children->children =
18512: (xmlSchemaTreeItemPtr) baseType->subtypes;
18513: }
18514: }
18515: }
18516: }
18517: /*
18518: * Now fixup attribute uses:
18519: * - expand attr. group references
18520: * - intersect attribute wildcards
18521: * - inherit attribute uses of the base type
18522: * - inherit or union attr. wildcards if extending
18523: * - apply attr. use prohibitions if restricting
18524: */
18525: res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18526: HFAILURE HERROR
18527: /*
18528: * Apply the complex type component constraints; this will not
18529: * check attributes, since this is done in
18530: * xmlSchemaFixupTypeAttributeUses().
18531: */
18532: res = xmlSchemaCheckCTComponent(pctxt, type);
18533: HFAILURE HERROR
18534:
18535: #ifdef DEBUG_TYPE
18536: xmlSchemaDebugFixedType(pctxt, type);
18537: #endif
18538: if (olderrs != pctxt->nberrors)
18539: return(pctxt->err);
18540: else
18541: return(0);
18542:
18543: exit_error:
18544: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18545: #ifdef DEBUG_TYPE
18546: xmlSchemaDebugFixedType(pctxt, type);
18547: #endif
18548: return(pctxt->err);
18549:
18550: exit_failure:
18551: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18552: #ifdef DEBUG_TYPE
18553: xmlSchemaDebugFixedType(pctxt, type);
18554: #endif
18555: return(-1);
18556: }
18557:
18558:
18559: /**
18560: * xmlSchemaTypeFixup:
18561: * @typeDecl: the schema type definition
18562: * @ctxt: the schema parser context
18563: *
18564: * Fixes the content model of the type.
18565: * URGENT TODO: We need an int result!
18566: */
18567: static int
18568: xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18569: xmlSchemaAbstractCtxtPtr actxt)
18570: {
18571: if (type == NULL)
18572: return(0);
18573: if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18574: AERROR_INT("xmlSchemaTypeFixup",
18575: "this function needs a parser context");
18576: return(-1);
18577: }
18578: if (! WXS_IS_TYPE_NOT_FIXED(type))
18579: return(0);
18580: if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18581: return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18582: else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18583: return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18584: return(0);
18585: }
18586:
18587: /**
18588: * xmlSchemaCheckFacet:
18589: * @facet: the facet
18590: * @typeDecl: the schema type definition
18591: * @pctxt: the schema parser context or NULL
18592: * @name: the optional name of the type
18593: *
18594: * Checks and computes the values of facets.
18595: *
18596: * Returns 0 if valid, a positive error code if not valid and
18597: * -1 in case of an internal or API error.
18598: */
18599: int
18600: xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18601: xmlSchemaTypePtr typeDecl,
18602: xmlSchemaParserCtxtPtr pctxt,
18603: const xmlChar * name ATTRIBUTE_UNUSED)
18604: {
18605: int ret = 0, ctxtGiven;
18606:
18607: if ((facet == NULL) || (typeDecl == NULL))
18608: return(-1);
18609: /*
18610: * TODO: will the parser context be given if used from
18611: * the relaxNG module?
18612: */
18613: if (pctxt == NULL)
18614: ctxtGiven = 0;
18615: else
18616: ctxtGiven = 1;
18617:
18618: switch (facet->type) {
18619: case XML_SCHEMA_FACET_MININCLUSIVE:
18620: case XML_SCHEMA_FACET_MINEXCLUSIVE:
18621: case XML_SCHEMA_FACET_MAXINCLUSIVE:
18622: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18623: case XML_SCHEMA_FACET_ENUMERATION: {
18624: /*
18625: * Okay we need to validate the value
18626: * at that point.
18627: */
18628: xmlSchemaTypePtr base;
18629:
18630: /* 4.3.5.5 Constraints on enumeration Schema Components
18631: * Schema Component Constraint: enumeration valid restriction
18632: * It is an �error� if any member of {value} is not in the
18633: * �value space� of {base type definition}.
18634: *
18635: * minInclusive, maxInclusive, minExclusive, maxExclusive:
18636: * The value �must� be in the
18637: * �value space� of the �base type�.
18638: */
18639: /*
18640: * This function is intended to deliver a compiled value
18641: * on the facet. In this implementation of XML Schemata the
18642: * type holding a facet, won't be a built-in type.
18643: * Thus to ensure that other API
18644: * calls (relaxng) do work, if the given type is a built-in
18645: * type, we will assume that the given built-in type *is
18646: * already* the base type.
18647: */
18648: if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18649: base = typeDecl->baseType;
18650: if (base == NULL) {
18651: PERROR_INT("xmlSchemaCheckFacet",
18652: "a type user derived type has no base type");
18653: return (-1);
18654: }
18655: } else
18656: base = typeDecl;
18657:
18658: if (! ctxtGiven) {
18659: /*
18660: * A context is needed if called from RelaxNG.
18661: */
18662: pctxt = xmlSchemaNewParserCtxt("*");
18663: if (pctxt == NULL)
18664: return (-1);
18665: }
18666: /*
18667: * NOTE: This call does not check the content nodes,
18668: * since they are not available:
18669: * facet->node is just the node holding the facet
18670: * definition, *not* the attribute holding the *value*
18671: * of the facet.
18672: */
18673: ret = xmlSchemaVCheckCVCSimpleType(
18674: ACTXT_CAST pctxt, facet->node, base,
18675: facet->value, &(facet->val), 1, 1, 0);
18676: if (ret != 0) {
18677: if (ret < 0) {
18678: /* No error message for RelaxNG. */
18679: if (ctxtGiven) {
18680: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18681: XML_SCHEMAP_INTERNAL, facet->node, NULL,
18682: "Internal error: xmlSchemaCheckFacet, "
18683: "failed to validate the value '%s' of the "
18684: "facet '%s' against the base type",
18685: facet->value, xmlSchemaFacetTypeToString(facet->type));
18686: }
18687: goto internal_error;
18688: }
18689: ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18690: /* No error message for RelaxNG. */
18691: if (ctxtGiven) {
18692: xmlChar *str = NULL;
18693:
18694: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18695: ret, facet->node, WXS_BASIC_CAST facet,
18696: "The value '%s' of the facet does not validate "
18697: "against the base type '%s'",
18698: facet->value,
18699: xmlSchemaFormatQName(&str,
18700: base->targetNamespace, base->name));
18701: FREE_AND_NULL(str);
18702: }
18703: goto exit;
18704: } else if (facet->val == NULL) {
18705: if (ctxtGiven) {
18706: PERROR_INT("xmlSchemaCheckFacet",
18707: "value was not computed");
18708: }
18709: TODO
18710: }
18711: break;
18712: }
18713: case XML_SCHEMA_FACET_PATTERN:
18714: facet->regexp = xmlRegexpCompile(facet->value);
18715: if (facet->regexp == NULL) {
18716: ret = XML_SCHEMAP_REGEXP_INVALID;
18717: /* No error message for RelaxNG. */
18718: if (ctxtGiven) {
18719: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18720: ret, facet->node, WXS_BASIC_CAST typeDecl,
18721: "The value '%s' of the facet 'pattern' is not a "
18722: "valid regular expression",
18723: facet->value, NULL);
18724: }
18725: }
18726: break;
18727: case XML_SCHEMA_FACET_TOTALDIGITS:
18728: case XML_SCHEMA_FACET_FRACTIONDIGITS:
18729: case XML_SCHEMA_FACET_LENGTH:
18730: case XML_SCHEMA_FACET_MAXLENGTH:
18731: case XML_SCHEMA_FACET_MINLENGTH:
18732:
18733: if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18734: ret = xmlSchemaValidatePredefinedType(
18735: xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18736: facet->value, &(facet->val));
18737: } else {
18738: ret = xmlSchemaValidatePredefinedType(
18739: xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18740: facet->value, &(facet->val));
18741: }
18742: if (ret != 0) {
18743: if (ret < 0) {
18744: /* No error message for RelaxNG. */
18745: if (ctxtGiven) {
18746: PERROR_INT("xmlSchemaCheckFacet",
18747: "validating facet value");
18748: }
18749: goto internal_error;
18750: }
18751: ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18752: /* No error message for RelaxNG. */
18753: if (ctxtGiven) {
18754: /* error code */
18755: xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18756: ret, facet->node, WXS_BASIC_CAST typeDecl,
18757: "The value '%s' of the facet '%s' is not a valid '%s'",
18758: facet->value,
18759: xmlSchemaFacetTypeToString(facet->type),
18760: (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18761: BAD_CAST "nonNegativeInteger" :
18762: BAD_CAST "positiveInteger",
18763: NULL);
18764: }
18765: }
18766: break;
18767:
18768: case XML_SCHEMA_FACET_WHITESPACE:{
18769: if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18770: facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18771: } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18772: facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18773: } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18774: facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18775: } else {
18776: ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18777: /* No error message for RelaxNG. */
18778: if (ctxtGiven) {
18779: /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18780: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18781: ret, facet->node, WXS_BASIC_CAST typeDecl,
18782: "The value '%s' of the facet 'whitespace' is not "
18783: "valid", facet->value, NULL);
18784: }
18785: }
18786: }
18787: default:
18788: break;
18789: }
18790: exit:
18791: if ((! ctxtGiven) && (pctxt != NULL))
18792: xmlSchemaFreeParserCtxt(pctxt);
18793: return (ret);
18794: internal_error:
18795: if ((! ctxtGiven) && (pctxt != NULL))
18796: xmlSchemaFreeParserCtxt(pctxt);
18797: return (-1);
18798: }
18799:
18800: /**
18801: * xmlSchemaCheckFacetValues:
18802: * @typeDecl: the schema type definition
18803: * @ctxt: the schema parser context
18804: *
18805: * Checks the default values types, especially for facets
18806: */
18807: static int
18808: xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18809: xmlSchemaParserCtxtPtr pctxt)
18810: {
18811: int res, olderrs = pctxt->nberrors;
18812: const xmlChar *name = typeDecl->name;
18813: /*
18814: * NOTE: It is intended to use the facets list, instead
18815: * of facetSet.
18816: */
18817: if (typeDecl->facets != NULL) {
18818: xmlSchemaFacetPtr facet = typeDecl->facets;
18819:
18820: /*
18821: * Temporarily assign the "schema" to the validation context
18822: * of the parser context. This is needed for NOTATION validation.
18823: */
18824: if (pctxt->vctxt == NULL) {
18825: if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18826: return(-1);
18827: }
18828: pctxt->vctxt->schema = pctxt->schema;
18829: while (facet != NULL) {
18830: res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18831: HFAILURE
18832: facet = facet->next;
18833: }
18834: pctxt->vctxt->schema = NULL;
18835: }
18836: if (olderrs != pctxt->nberrors)
18837: return(pctxt->err);
18838: return(0);
18839: exit_failure:
18840: return(-1);
18841: }
18842:
18843: /**
18844: * xmlSchemaGetCircModelGrDefRef:
18845: * @ctxtMGroup: the searched model group
18846: * @selfMGroup: the second searched model group
18847: * @particle: the first particle
18848: *
18849: * This one is intended to be used by
18850: * xmlSchemaCheckGroupDefCircular only.
18851: *
18852: * Returns the particle with the circular model group definition reference,
18853: * otherwise NULL.
18854: */
18855: static xmlSchemaTreeItemPtr
18856: xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18857: xmlSchemaTreeItemPtr particle)
18858: {
18859: xmlSchemaTreeItemPtr circ = NULL;
18860: xmlSchemaTreeItemPtr term;
18861: xmlSchemaModelGroupDefPtr gdef;
18862:
18863: for (; particle != NULL; particle = particle->next) {
18864: term = particle->children;
18865: if (term == NULL)
18866: continue;
18867: switch (term->type) {
18868: case XML_SCHEMA_TYPE_GROUP:
18869: gdef = (xmlSchemaModelGroupDefPtr) term;
18870: if (gdef == groupDef)
18871: return (particle);
18872: /*
18873: * Mark this model group definition to avoid infinite
18874: * recursion on circular references not yet examined.
18875: */
18876: if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18877: continue;
18878: if (gdef->children != NULL) {
18879: gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18880: circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18881: gdef->children->children);
18882: gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18883: if (circ != NULL)
18884: return (circ);
18885: }
18886: break;
18887: case XML_SCHEMA_TYPE_SEQUENCE:
18888: case XML_SCHEMA_TYPE_CHOICE:
18889: case XML_SCHEMA_TYPE_ALL:
18890: circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18891: if (circ != NULL)
18892: return (circ);
18893: break;
18894: default:
18895: break;
18896: }
18897: }
18898: return (NULL);
18899: }
18900:
18901: /**
18902: * xmlSchemaCheckGroupDefCircular:
18903: * @item: the model group definition
18904: * @ctxt: the parser context
18905: * @name: the name
18906: *
18907: * Checks for circular references to model group definitions.
18908: */
18909: static void
18910: xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18911: xmlSchemaParserCtxtPtr ctxt)
18912: {
18913: /*
18914: * Schema Component Constraint: Model Group Correct
18915: * 2 Circular groups are disallowed. That is, within the {particles}
18916: * of a group there must not be at any depth a particle whose {term}
18917: * is the group itself.
18918: */
18919: if ((item == NULL) ||
18920: (item->type != XML_SCHEMA_TYPE_GROUP) ||
18921: (item->children == NULL))
18922: return;
18923: {
18924: xmlSchemaTreeItemPtr circ;
18925:
18926: circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18927: if (circ != NULL) {
18928: xmlChar *str = NULL;
18929: /*
18930: * TODO: The error report is not adequate: this constraint
18931: * is defined for model groups but not definitions, but since
18932: * there cannot be any circular model groups without a model group
18933: * definition (if not using a construction API), we check those
18934: * defintions only.
18935: */
18936: xmlSchemaPCustomErr(ctxt,
18937: XML_SCHEMAP_MG_PROPS_CORRECT_2,
18938: NULL, WXS_ITEM_NODE(circ),
18939: "Circular reference to the model group definition '%s' "
18940: "defined", xmlSchemaFormatQName(&str,
18941: item->targetNamespace, item->name));
18942: FREE_AND_NULL(str)
18943: /*
18944: * NOTE: We will cut the reference to avoid further
18945: * confusion of the processor. This is a fatal error.
18946: */
18947: circ->children = NULL;
18948: }
18949: }
18950: }
18951:
18952: /**
18953: * xmlSchemaModelGroupToModelGroupDefFixup:
18954: * @ctxt: the parser context
18955: * @mg: the model group
18956: *
18957: * Assigns the model group of model group definitions to the "term"
18958: * of the referencing particle.
18959: * In xmlSchemaResolveModelGroupParticleReferences the model group
18960: * definitions were assigned to the "term", since needed for the
18961: * circularity check.
18962: *
18963: * Schema Component Constraint:
18964: * All Group Limited (cos-all-limited) (1.2)
18965: */
18966: static void
18967: xmlSchemaModelGroupToModelGroupDefFixup(
18968: xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18969: xmlSchemaModelGroupPtr mg)
18970: {
18971: xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18972:
18973: while (particle != NULL) {
18974: if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18975: ((WXS_PARTICLE_TERM(particle))->type !=
18976: XML_SCHEMA_TYPE_GROUP))
18977: {
18978: particle = WXS_PTC_CAST particle->next;
18979: continue;
18980: }
18981: if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18982: /*
18983: * TODO: Remove the particle.
18984: */
18985: WXS_PARTICLE_TERM(particle) = NULL;
18986: particle = WXS_PTC_CAST particle->next;
18987: continue;
18988: }
18989: /*
18990: * Assign the model group to the {term} of the particle.
18991: */
18992: WXS_PARTICLE_TERM(particle) =
18993: WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18994:
18995: particle = WXS_PTC_CAST particle->next;
18996: }
18997: }
18998:
18999: /**
19000: * xmlSchemaCheckAttrGroupCircularRecur:
19001: * @ctxtGr: the searched attribute group
19002: * @attr: the current attribute list to be processed
19003: *
19004: * This one is intended to be used by
19005: * xmlSchemaCheckAttrGroupCircular only.
19006: *
19007: * Returns the circular attribute grou reference, otherwise NULL.
19008: */
19009: static xmlSchemaQNameRefPtr
19010: xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19011: xmlSchemaItemListPtr list)
19012: {
19013: xmlSchemaAttributeGroupPtr gr;
19014: xmlSchemaQNameRefPtr ref, circ;
19015: int i;
19016: /*
19017: * We will search for an attribute group reference which
19018: * references the context attribute group.
19019: */
19020: for (i = 0; i < list->nbItems; i++) {
19021: ref = list->items[i];
19022: if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19023: (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19024: (ref->item != NULL))
19025: {
19026: gr = WXS_ATTR_GROUP_CAST ref->item;
19027: if (gr == ctxtGr)
19028: return(ref);
19029: if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19030: continue;
19031: /*
19032: * Mark as visited to avoid infinite recursion on
19033: * circular references not yet examined.
19034: */
19035: if ((gr->attrUses) &&
19036: (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19037: {
19038: gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19039: circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19040: (xmlSchemaItemListPtr) gr->attrUses);
19041: gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19042: if (circ != NULL)
19043: return (circ);
19044: }
19045:
19046: }
19047: }
19048: return (NULL);
19049: }
19050:
19051: /**
19052: * xmlSchemaCheckAttrGroupCircular:
19053: * attrGr: the attribute group definition
19054: * @ctxt: the parser context
19055: * @name: the name
19056: *
19057: * Checks for circular references of attribute groups.
19058: */
19059: static int
19060: xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19061: xmlSchemaParserCtxtPtr ctxt)
19062: {
19063: /*
19064: * Schema Representation Constraint:
19065: * Attribute Group Definition Representation OK
19066: * 3 Circular group reference is disallowed outside <redefine>.
19067: * That is, unless this element information item's parent is
19068: * <redefine>, then among the [children], if any, there must
19069: * not be an <attributeGroup> with ref [attribute] which resolves
19070: * to the component corresponding to this <attributeGroup>. Indirect
19071: * circularity is also ruled out. That is, when QName resolution
19072: * (Schema Document) (�3.15.3) is applied to a �QName� arising from
19073: * any <attributeGroup>s with a ref [attribute] among the [children],
19074: * it must not be the case that a �QName� is encountered at any depth
19075: * which resolves to the component corresponding to this <attributeGroup>.
19076: */
19077: if (attrGr->attrUses == NULL)
19078: return(0);
19079: else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19080: return(0);
19081: else {
19082: xmlSchemaQNameRefPtr circ;
19083:
19084: circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19085: (xmlSchemaItemListPtr) attrGr->attrUses);
19086: if (circ != NULL) {
19087: xmlChar *str = NULL;
19088: /*
19089: * TODO: Report the referenced attr group as QName.
19090: */
19091: xmlSchemaPCustomErr(ctxt,
19092: XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19093: NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19094: "Circular reference to the attribute group '%s' "
19095: "defined", xmlSchemaGetComponentQName(&str, attrGr));
19096: FREE_AND_NULL(str);
19097: /*
19098: * NOTE: We will cut the reference to avoid further
19099: * confusion of the processor.
19100: * BADSPEC TODO: The spec should define how to process in this case.
19101: */
19102: circ->item = NULL;
19103: return(ctxt->err);
19104: }
19105: }
19106: return(0);
19107: }
19108:
19109: static int
19110: xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19111: xmlSchemaAttributeGroupPtr attrGr);
19112:
19113: /**
19114: * xmlSchemaExpandAttributeGroupRefs:
19115: * @pctxt: the parser context
19116: * @node: the node of the component holding the attribute uses
19117: * @completeWild: the intersected wildcard to be returned
19118: * @list: the attribute uses
19119: *
19120: * Substitutes contained attribute group references
19121: * for their attribute uses. Wilcards are intersected.
19122: * Attribute use prohibitions are removed from the list
19123: * and returned via the @prohibs list.
19124: * Pointlessness of attr. prohibs, if a matching attr. decl
19125: * is existent a well, are checked.
19126: */
19127: static int
19128: xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19129: xmlSchemaBasicItemPtr item,
19130: xmlSchemaWildcardPtr *completeWild,
19131: xmlSchemaItemListPtr list,
19132: xmlSchemaItemListPtr prohibs)
19133: {
19134: xmlSchemaAttributeGroupPtr gr;
19135: xmlSchemaAttributeUsePtr use;
19136: xmlSchemaItemListPtr sublist;
19137: int i, j;
19138: int created = (*completeWild == NULL) ? 0 : 1;
19139:
19140: if (prohibs)
19141: prohibs->nbItems = 0;
19142:
19143: for (i = 0; i < list->nbItems; i++) {
19144: use = list->items[i];
19145:
19146: if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19147: if (prohibs == NULL) {
19148: PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19149: "unexpected attr prohibition found");
19150: return(-1);
19151: }
19152: /*
19153: * Remove from attribute uses.
19154: */
19155: if (xmlSchemaItemListRemove(list, i) == -1)
19156: return(-1);
19157: i--;
19158: /*
19159: * Note that duplicate prohibitions were already
19160: * handled at parsing time.
19161: */
19162: /*
19163: * Add to list of prohibitions.
19164: */
19165: xmlSchemaItemListAddSize(prohibs, 2, use);
19166: continue;
19167: }
19168: if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19169: ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19170: {
19171: if ((WXS_QNAME_CAST use)->item == NULL)
19172: return(-1);
19173: gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19174: /*
19175: * Expand the referenced attr. group.
19176: * TODO: remove this, this is done in a previous step, so
19177: * already done here.
19178: */
19179: if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19180: if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19181: return(-1);
19182: }
19183: /*
19184: * Build the 'complete' wildcard; i.e. intersect multiple
19185: * wildcards.
19186: */
19187: if (gr->attributeWildcard != NULL) {
19188: if (*completeWild == NULL) {
19189: *completeWild = gr->attributeWildcard;
19190: } else {
19191: if (! created) {
19192: xmlSchemaWildcardPtr tmpWild;
19193:
19194: /*
19195: * Copy the first encountered wildcard as context,
19196: * except for the annotation.
19197: *
19198: * Although the complete wildcard might not correspond
19199: * to any node in the schema, we will anchor it on
19200: * the node of the owner component.
19201: */
19202: tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19203: XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19204: WXS_ITEM_NODE(item));
19205: if (tmpWild == NULL)
19206: return(-1);
19207: if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19208: tmpWild, *completeWild) == -1)
19209: return (-1);
19210: tmpWild->processContents = (*completeWild)->processContents;
19211: *completeWild = tmpWild;
19212: created = 1;
19213: }
19214:
19215: if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19216: gr->attributeWildcard) == -1)
19217: return(-1);
19218: }
19219: }
19220: /*
19221: * Just remove the reference if the referenced group does not
19222: * contain any attribute uses.
19223: */
19224: sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19225: if ((sublist == NULL) || sublist->nbItems == 0) {
19226: if (xmlSchemaItemListRemove(list, i) == -1)
19227: return(-1);
19228: i--;
19229: continue;
19230: }
19231: /*
19232: * Add the attribute uses.
19233: */
19234: list->items[i] = sublist->items[0];
19235: if (sublist->nbItems != 1) {
19236: for (j = 1; j < sublist->nbItems; j++) {
19237: i++;
19238: if (xmlSchemaItemListInsert(list,
19239: sublist->items[j], i) == -1)
19240: return(-1);
19241: }
19242: }
19243: }
19244:
19245: }
19246: /*
19247: * Handle pointless prohibitions of declared attributes.
19248: */
19249: if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19250: xmlSchemaAttributeUseProhibPtr prohib;
19251:
19252: for (i = prohibs->nbItems -1; i >= 0; i--) {
19253: prohib = prohibs->items[i];
19254: for (j = 0; j < list->nbItems; j++) {
19255: use = list->items[j];
19256:
19257: if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19258: (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19259: {
19260: xmlChar *str = NULL;
19261:
19262: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19263: XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19264: prohib->node, NULL,
19265: "Skipping pointless attribute use prohibition "
19266: "'%s', since a corresponding attribute use "
19267: "exists already in the type definition",
19268: xmlSchemaFormatQName(&str,
19269: prohib->targetNamespace, prohib->name),
19270: NULL, NULL);
19271: FREE_AND_NULL(str);
19272: /*
19273: * Remove the prohibition.
19274: */
19275: if (xmlSchemaItemListRemove(prohibs, i) == -1)
19276: return(-1);
19277: break;
19278: }
19279: }
19280: }
19281: }
19282: return(0);
19283: }
19284:
19285: /**
19286: * xmlSchemaAttributeGroupExpandRefs:
19287: * @pctxt: the parser context
19288: * @attrGr: the attribute group definition
19289: *
19290: * Computation of:
19291: * {attribute uses} property
19292: * {attribute wildcard} property
19293: *
19294: * Substitutes contained attribute group references
19295: * for their attribute uses. Wilcards are intersected.
19296: */
19297: static int
19298: xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19299: xmlSchemaAttributeGroupPtr attrGr)
19300: {
19301: if ((attrGr->attrUses == NULL) ||
19302: (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19303: return(0);
19304:
19305: attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19306: if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19307: &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19308: return(-1);
19309: return(0);
19310: }
19311:
19312: /**
19313: * xmlSchemaAttributeGroupExpandRefs:
19314: * @pctxt: the parser context
19315: * @attrGr: the attribute group definition
19316: *
19317: * Substitutes contained attribute group references
19318: * for their attribute uses. Wilcards are intersected.
19319: *
19320: * Schema Component Constraint:
19321: * Attribute Group Definition Properties Correct (ag-props-correct)
19322: */
19323: static int
19324: xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19325: xmlSchemaAttributeGroupPtr attrGr)
19326: {
19327: /*
19328: * SPEC ag-props-correct
19329: * (1) "The values of the properties of an attribute group definition
19330: * must be as described in the property tableau in The Attribute
19331: * Group Definition Schema Component (�3.6.1), modulo the impact of
19332: * Missing Sub-components (�5.3);"
19333: */
19334:
19335: if ((attrGr->attrUses != NULL) &&
19336: (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19337: {
19338: xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19339: xmlSchemaAttributeUsePtr use, tmp;
19340: int i, j, hasId = 0;
19341:
19342: for (i = uses->nbItems -1; i >= 0; i--) {
19343: use = uses->items[i];
19344: /*
19345: * SPEC ag-props-correct
19346: * (2) "Two distinct members of the {attribute uses} must not have
19347: * {attribute declaration}s both of whose {name}s match and whose
19348: * {target namespace}s are identical."
19349: */
19350: if (i > 0) {
19351: for (j = i -1; j >= 0; j--) {
19352: tmp = uses->items[j];
19353: if ((WXS_ATTRUSE_DECL_NAME(use) ==
19354: WXS_ATTRUSE_DECL_NAME(tmp)) &&
19355: (WXS_ATTRUSE_DECL_TNS(use) ==
19356: WXS_ATTRUSE_DECL_TNS(tmp)))
19357: {
19358: xmlChar *str = NULL;
19359:
19360: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19361: XML_SCHEMAP_AG_PROPS_CORRECT,
19362: attrGr->node, WXS_BASIC_CAST attrGr,
19363: "Duplicate %s",
19364: xmlSchemaGetComponentDesignation(&str, use),
19365: NULL);
19366: FREE_AND_NULL(str);
19367: /*
19368: * Remove the duplicate.
19369: */
19370: if (xmlSchemaItemListRemove(uses, i) == -1)
19371: return(-1);
19372: goto next_use;
19373: }
19374: }
19375: }
19376: /*
19377: * SPEC ag-props-correct
19378: * (3) "Two distinct members of the {attribute uses} must not have
19379: * {attribute declaration}s both of whose {type definition}s are or
19380: * are derived from ID."
19381: * TODO: Does 'derived' include member-types of unions?
19382: */
19383: if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19384: if (xmlSchemaIsDerivedFromBuiltInType(
19385: WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19386: {
19387: if (hasId) {
19388: xmlChar *str = NULL;
19389:
19390: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19391: XML_SCHEMAP_AG_PROPS_CORRECT,
19392: attrGr->node, WXS_BASIC_CAST attrGr,
19393: "There must not exist more than one attribute "
19394: "declaration of type 'xs:ID' "
19395: "(or derived from 'xs:ID'). The %s violates this "
19396: "constraint",
19397: xmlSchemaGetComponentDesignation(&str, use),
19398: NULL);
19399: FREE_AND_NULL(str);
19400: if (xmlSchemaItemListRemove(uses, i) == -1)
19401: return(-1);
19402: }
19403: hasId = 1;
19404: }
19405: }
19406: next_use: {}
19407: }
19408: }
19409: return(0);
19410: }
19411:
19412: /**
19413: * xmlSchemaResolveAttrGroupReferences:
19414: * @attrgrpDecl: the schema attribute definition
19415: * @ctxt: the schema parser context
19416: * @name: the attribute name
19417: *
19418: * Resolves references to attribute group definitions.
19419: */
19420: static int
19421: xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19422: xmlSchemaParserCtxtPtr ctxt)
19423: {
19424: xmlSchemaAttributeGroupPtr group;
19425:
19426: if (ref->item != NULL)
19427: return(0);
19428: group = xmlSchemaGetAttributeGroup(ctxt->schema,
19429: ref->name,
19430: ref->targetNamespace);
19431: if (group == NULL) {
19432: xmlSchemaPResCompAttrErr(ctxt,
19433: XML_SCHEMAP_SRC_RESOLVE,
19434: NULL, ref->node,
19435: "ref", ref->name, ref->targetNamespace,
19436: ref->itemType, NULL);
19437: return(ctxt->err);
19438: }
19439: ref->item = WXS_BASIC_CAST group;
19440: return(0);
19441: }
19442:
19443: /**
19444: * xmlSchemaCheckAttrPropsCorrect:
19445: * @item: an schema attribute declaration/use
19446: * @ctxt: a schema parser context
19447: * @name: the name of the attribute
19448: *
19449: *
19450: * Schema Component Constraint:
19451: * Attribute Declaration Properties Correct (a-props-correct)
19452: *
19453: * Validates the value constraints of an attribute declaration/use.
19454: * NOTE that this needs the simle type definitions to be already
19455: * builded and checked.
19456: */
19457: static int
19458: xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19459: xmlSchemaAttributePtr attr)
19460: {
19461:
19462: /*
19463: * SPEC a-props-correct (1)
19464: * "The values of the properties of an attribute declaration must
19465: * be as described in the property tableau in The Attribute
19466: * Declaration Schema Component (�3.2.1), modulo the impact of
19467: * Missing Sub-components (�5.3)."
19468: */
19469:
19470: if (WXS_ATTR_TYPEDEF(attr) == NULL)
19471: return(0);
19472:
19473: if (attr->defValue != NULL) {
19474: int ret;
19475:
19476: /*
19477: * SPEC a-props-correct (3)
19478: * "If the {type definition} is or is derived from ID then there
19479: * must not be a {value constraint}."
19480: */
19481: if (xmlSchemaIsDerivedFromBuiltInType(
19482: WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19483: {
19484: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19485: XML_SCHEMAP_A_PROPS_CORRECT_3,
19486: NULL, WXS_BASIC_CAST attr,
19487: "Value constraints are not allowed if the type definition "
19488: "is or is derived from xs:ID",
19489: NULL, NULL);
19490: return(pctxt->err);
19491: }
19492: /*
19493: * SPEC a-props-correct (2)
19494: * "if there is a {value constraint}, the canonical lexical
19495: * representation of its value must be �valid� with respect
19496: * to the {type definition} as defined in String Valid (�3.14.4)."
19497: * TODO: Don't care about the *cononical* stuff here, this requirement
19498: * will be removed in WXS 1.1 anyway.
19499: */
19500: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19501: attr->node, WXS_ATTR_TYPEDEF(attr),
19502: attr->defValue, &(attr->defVal),
19503: 1, 1, 0);
19504: if (ret != 0) {
19505: if (ret < 0) {
19506: PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19507: "calling xmlSchemaVCheckCVCSimpleType()");
19508: return(-1);
19509: }
19510: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19511: XML_SCHEMAP_A_PROPS_CORRECT_2,
19512: NULL, WXS_BASIC_CAST attr,
19513: "The value of the value constraint is not valid",
19514: NULL, NULL);
19515: return(pctxt->err);
19516: }
19517: }
19518:
19519: return(0);
19520: }
19521:
19522: static xmlSchemaElementPtr
19523: xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19524: xmlSchemaElementPtr ancestor)
19525: {
19526: xmlSchemaElementPtr ret;
19527:
19528: if (WXS_SUBST_HEAD(ancestor) == NULL)
19529: return (NULL);
19530: if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19531: return (ancestor);
19532:
19533: if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19534: return (NULL);
19535: WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19536: ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19537: WXS_SUBST_HEAD(ancestor));
19538: WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19539:
19540: return (ret);
19541: }
19542:
19543: /**
19544: * xmlSchemaCheckElemPropsCorrect:
19545: * @ctxt: a schema parser context
19546: * @decl: the element declaration
19547: * @name: the name of the attribute
19548: *
19549: * Schema Component Constraint:
19550: * Element Declaration Properties Correct (e-props-correct)
19551: *
19552: * STATUS:
19553: * missing: (6)
19554: */
19555: static int
19556: xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19557: xmlSchemaElementPtr elemDecl)
19558: {
19559: int ret = 0;
19560: xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19561: /*
19562: * SPEC (1) "The values of the properties of an element declaration
19563: * must be as described in the property tableau in The Element
19564: * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19565: * Sub-components (�5.3)."
19566: */
19567: if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19568: xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19569:
19570: xmlSchemaCheckElementDeclComponent(head, pctxt);
19571: /*
19572: * SPEC (3) "If there is a non-�absent� {substitution group
19573: * affiliation}, then {scope} must be global."
19574: */
19575: if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19576: xmlSchemaPCustomErr(pctxt,
19577: XML_SCHEMAP_E_PROPS_CORRECT_3,
19578: WXS_BASIC_CAST elemDecl, NULL,
19579: "Only global element declarations can have a "
19580: "substitution group affiliation", NULL);
19581: ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19582: }
19583: /*
19584: * TODO: SPEC (6) "Circular substitution groups are disallowed.
19585: * That is, it must not be possible to return to an element declaration
19586: * by repeatedly following the {substitution group affiliation}
19587: * property."
19588: */
19589: if (head == elemDecl)
19590: circ = head;
19591: else if (WXS_SUBST_HEAD(head) != NULL)
19592: circ = xmlSchemaCheckSubstGroupCircular(head, head);
19593: else
19594: circ = NULL;
19595: if (circ != NULL) {
19596: xmlChar *strA = NULL, *strB = NULL;
19597:
19598: xmlSchemaPCustomErrExt(pctxt,
19599: XML_SCHEMAP_E_PROPS_CORRECT_6,
19600: WXS_BASIC_CAST circ, NULL,
19601: "The element declaration '%s' defines a circular "
19602: "substitution group to element declaration '%s'",
19603: xmlSchemaGetComponentQName(&strA, circ),
19604: xmlSchemaGetComponentQName(&strB, head),
19605: NULL);
19606: FREE_AND_NULL(strA)
19607: FREE_AND_NULL(strB)
19608: ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19609: }
19610: /*
19611: * SPEC (4) "If there is a {substitution group affiliation},
19612: * the {type definition}
19613: * of the element declaration must be validly derived from the {type
19614: * definition} of the {substitution group affiliation}, given the value
19615: * of the {substitution group exclusions} of the {substitution group
19616: * affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19617: * (if the {type definition} is complex) or as defined in
19618: * Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19619: * simple)."
19620: *
19621: * NOTE: {substitution group exclusions} means the values of the
19622: * attribute "final".
19623: */
19624:
19625: if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19626: int set = 0;
19627:
19628: if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19629: set |= SUBSET_EXTENSION;
19630: if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19631: set |= SUBSET_RESTRICTION;
19632:
19633: if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19634: WXS_ELEM_TYPEDEF(head), set) != 0) {
19635: xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19636:
19637: ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19638: xmlSchemaPCustomErrExt(pctxt,
19639: XML_SCHEMAP_E_PROPS_CORRECT_4,
19640: WXS_BASIC_CAST elemDecl, NULL,
19641: "The type definition '%s' was "
19642: "either rejected by the substitution group "
19643: "affiliation '%s', or not validly derived from its type "
19644: "definition '%s'",
19645: xmlSchemaGetComponentQName(&strA, typeDef),
19646: xmlSchemaGetComponentQName(&strB, head),
19647: xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19648: FREE_AND_NULL(strA)
19649: FREE_AND_NULL(strB)
19650: FREE_AND_NULL(strC)
19651: }
19652: }
19653: }
19654: /*
19655: * SPEC (5) "If the {type definition} or {type definition}'s
19656: * {content type}
19657: * is or is derived from ID then there must not be a {value constraint}.
19658: * Note: The use of ID as a type definition for elements goes beyond
19659: * XML 1.0, and should be avoided if backwards compatibility is desired"
19660: */
19661: if ((elemDecl->value != NULL) &&
19662: ((WXS_IS_SIMPLE(typeDef) &&
19663: xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19664: (WXS_IS_COMPLEX(typeDef) &&
19665: WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19666: xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19667: XML_SCHEMAS_ID)))) {
19668:
19669: ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19670: xmlSchemaPCustomErr(pctxt,
19671: XML_SCHEMAP_E_PROPS_CORRECT_5,
19672: WXS_BASIC_CAST elemDecl, NULL,
19673: "The type definition (or type definition's content type) is or "
19674: "is derived from ID; value constraints are not allowed in "
19675: "conjunction with such a type definition", NULL);
19676: } else if (elemDecl->value != NULL) {
19677: int vcret;
19678: xmlNodePtr node = NULL;
19679:
19680: /*
19681: * SPEC (2) "If there is a {value constraint}, the canonical lexical
19682: * representation of its value must be �valid� with respect to the
19683: * {type definition} as defined in Element Default Valid (Immediate)
19684: * (�3.3.6)."
19685: */
19686: if (typeDef == NULL) {
19687: xmlSchemaPErr(pctxt, elemDecl->node,
19688: XML_SCHEMAP_INTERNAL,
19689: "Internal error: xmlSchemaCheckElemPropsCorrect, "
19690: "type is missing... skipping validation of "
19691: "the value constraint", NULL, NULL);
19692: return (-1);
19693: }
19694: if (elemDecl->node != NULL) {
19695: if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19696: node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19697: BAD_CAST "fixed");
19698: else
19699: node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19700: BAD_CAST "default");
19701: }
19702: vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19703: typeDef, elemDecl->value, &(elemDecl->defVal));
19704: if (vcret != 0) {
19705: if (vcret < 0) {
19706: PERROR_INT("xmlSchemaElemCheckValConstr",
19707: "failed to validate the value constraint of an "
19708: "element declaration");
19709: return (-1);
19710: }
19711: return (vcret);
19712: }
19713: }
19714:
19715: return (ret);
19716: }
19717:
19718: /**
19719: * xmlSchemaCheckElemSubstGroup:
19720: * @ctxt: a schema parser context
19721: * @decl: the element declaration
19722: * @name: the name of the attribute
19723: *
19724: * Schema Component Constraint:
19725: * Substitution Group (cos-equiv-class)
19726: *
19727: * In Libxml2 the subst. groups will be precomputed, in terms of that
19728: * a list will be built for each subst. group head, holding all direct
19729: * referents to this head.
19730: * NOTE that this function needs:
19731: * 1. circular subst. groups to be checked beforehand
19732: * 2. the declaration's type to be derived from the head's type
19733: *
19734: * STATUS:
19735: *
19736: */
19737: static void
19738: xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19739: xmlSchemaElementPtr elemDecl)
19740: {
19741: if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19742: /* SPEC (1) "Its {abstract} is false." */
19743: (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19744: return;
19745: {
19746: xmlSchemaElementPtr head;
19747: xmlSchemaTypePtr headType, type;
19748: int set, methSet;
19749: /*
19750: * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19751: * {disallowed substitutions} as the blocking constraint, as defined in
19752: * Substitution Group OK (Transitive) (�3.3.6)."
19753: */
19754: for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19755: head = WXS_SUBST_HEAD(head)) {
19756: set = 0;
19757: methSet = 0;
19758: /*
19759: * The blocking constraints.
19760: */
19761: if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19762: continue;
19763: headType = head->subtypes;
19764: type = elemDecl->subtypes;
19765: if (headType == type)
19766: goto add_member;
19767: if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19768: set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19769: if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19770: set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19771: /*
19772: * SPEC: Substitution Group OK (Transitive) (2.3)
19773: * "The set of all {derivation method}s involved in the
19774: * derivation of D's {type definition} from C's {type definition}
19775: * does not intersect with the union of the blocking constraint,
19776: * C's {prohibited substitutions} (if C is complex, otherwise the
19777: * empty set) and the {prohibited substitutions} (respectively the
19778: * empty set) of any intermediate {type definition}s in the
19779: * derivation of D's {type definition} from C's {type definition}."
19780: */
19781: /*
19782: * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19783: * subst.head axis, the methSet does not need to be computed for
19784: * the full depth over and over.
19785: */
19786: /*
19787: * The set of all {derivation method}s involved in the derivation
19788: */
19789: while ((type != NULL) && (type != headType)) {
19790: if ((WXS_IS_EXTENSION(type)) &&
19791: ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19792: methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19793:
19794: if (WXS_IS_RESTRICTION(type) &&
19795: ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19796: methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19797:
19798: type = type->baseType;
19799: }
19800: /*
19801: * The {prohibited substitutions} of all intermediate types +
19802: * the head's type.
19803: */
19804: type = elemDecl->subtypes->baseType;
19805: while (type != NULL) {
19806: if (WXS_IS_COMPLEX(type)) {
19807: if ((type->flags &
19808: XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19809: ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19810: set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19811: if ((type->flags &
19812: XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19813: ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19814: set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19815: } else
19816: break;
19817: if (type == headType)
19818: break;
19819: type = type->baseType;
19820: }
19821: if ((set != 0) &&
19822: (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19823: (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19824: ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19825: (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19826: continue;
19827: }
19828: add_member:
19829: xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19830: if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19831: head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19832: }
19833: }
19834: }
19835:
19836: #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19837: /**
19838: * xmlSchemaCheckElementDeclComponent
19839: * @pctxt: the schema parser context
19840: * @ctxtComponent: the context component (an element declaration)
19841: * @ctxtParticle: the first particle of the context component
19842: * @searchParticle: the element declaration particle to be analysed
19843: *
19844: * Schema Component Constraint: Element Declarations Consistent
19845: */
19846: static int
19847: xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19848: xmlSchemaBasicItemPtr ctxtComponent,
19849: xmlSchemaParticlePtr ctxtParticle,
19850: xmlSchemaParticlePtr searchParticle,
19851: xmlSchemaParticlePtr curParticle,
19852: int search)
19853: {
19854: return(0);
19855:
19856: int ret = 0;
19857: xmlSchemaParticlePtr cur = curParticle;
19858: if (curParticle == NULL) {
19859: return(0);
19860: }
19861: if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19862: /*
19863: * Just return in this case. A missing "term" of the particle
19864: * might arise due to an invalid "term" component.
19865: */
19866: return(0);
19867: }
19868: while (cur != NULL) {
19869: switch (WXS_PARTICLE_TERM(cur)->type) {
19870: case XML_SCHEMA_TYPE_ANY:
19871: break;
19872: case XML_SCHEMA_TYPE_ELEMENT:
19873: if (search == 0) {
19874: ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19875: ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19876: if (ret != 0)
19877: return(ret);
19878: } else {
19879: xmlSchemaElementPtr elem =
19880: WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19881: /*
19882: * SPEC Element Declarations Consistent:
19883: * "If the {particles} contains, either directly,
19884: * indirectly (that is, within the {particles} of a
19885: * contained model group, recursively) or �implicitly�
19886: * two or more element declaration particles with
19887: * the same {name} and {target namespace}, then
19888: * all their type definitions must be the same
19889: * top-level definition [...]"
19890: */
19891: if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19892: WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19893: xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19894: WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19895: {
19896: xmlChar *strA = NULL, *strB = NULL;
19897:
19898: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19899: /* TODO: error code */
19900: XML_SCHEMAP_COS_NONAMBIG,
19901: WXS_ITEM_NODE(cur), NULL,
19902: "In the content model of %s, there are multiple "
19903: "element declarations for '%s' with different "
19904: "type definitions",
19905: xmlSchemaGetComponentDesignation(&strA,
19906: ctxtComponent),
19907: xmlSchemaFormatQName(&strB,
19908: WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19909: WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19910: FREE_AND_NULL(strA);
19911: FREE_AND_NULL(strB);
19912: return(XML_SCHEMAP_COS_NONAMBIG);
19913: }
19914: }
19915: break;
19916: case XML_SCHEMA_TYPE_SEQUENCE: {
19917: break;
19918: }
19919: case XML_SCHEMA_TYPE_CHOICE:{
19920: /*
19921: xmlSchemaTreeItemPtr sub;
19922:
19923: sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
19924: while (sub != NULL) {
19925: ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19926: ctxtParticle, ctxtElem);
19927: if (ret != 0)
19928: return(ret);
19929: sub = sub->next;
19930: }
19931: */
19932: break;
19933: }
19934: case XML_SCHEMA_TYPE_ALL:
19935: break;
19936: case XML_SCHEMA_TYPE_GROUP:
19937: break;
19938: default:
19939: xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19940: "xmlSchemaCheckElementDeclConsistent",
19941: "found unexpected term of type '%s' in content model",
19942: WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19943: return(-1);
19944: }
19945: cur = (xmlSchemaParticlePtr) cur->next;
19946: }
19947:
19948: exit:
19949: return(ret);
19950: }
19951: #endif
19952:
19953: /**
19954: * xmlSchemaCheckElementDeclComponent
19955: * @item: an schema element declaration/particle
19956: * @ctxt: a schema parser context
19957: * @name: the name of the attribute
19958: *
19959: * Validates the value constraints of an element declaration.
19960: * Adds substitution group members.
19961: */
19962: static void
19963: xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19964: xmlSchemaParserCtxtPtr ctxt)
19965: {
19966: if (elemDecl == NULL)
19967: return;
19968: if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19969: return;
19970: elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19971: if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19972: /*
19973: * Adds substitution group members.
19974: */
19975: xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19976: }
19977: }
19978:
19979: /**
19980: * xmlSchemaResolveModelGroupParticleReferences:
19981: * @particle: a particle component
19982: * @ctxt: a parser context
19983: *
19984: * Resolves references of a model group's {particles} to
19985: * model group definitions and to element declarations.
19986: */
19987: static void
19988: xmlSchemaResolveModelGroupParticleReferences(
19989: xmlSchemaParserCtxtPtr ctxt,
19990: xmlSchemaModelGroupPtr mg)
19991: {
19992: xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19993: xmlSchemaQNameRefPtr ref;
19994: xmlSchemaBasicItemPtr refItem;
19995:
19996: /*
19997: * URGENT TODO: Test this.
19998: */
19999: while (particle != NULL) {
20000: if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20001: ((WXS_PARTICLE_TERM(particle))->type !=
20002: XML_SCHEMA_EXTRA_QNAMEREF))
20003: {
20004: goto next_particle;
20005: }
20006: ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20007: /*
20008: * Resolve the reference.
20009: * NULL the {term} by default.
20010: */
20011: particle->children = NULL;
20012:
20013: refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20014: ref->itemType, ref->name, ref->targetNamespace);
20015: if (refItem == NULL) {
20016: xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20017: NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20018: ref->targetNamespace, ref->itemType, NULL);
20019: /* TODO: remove the particle. */
20020: goto next_particle;
20021: }
20022: if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20023: if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20024: /* TODO: remove the particle. */
20025: goto next_particle;
20026: /*
20027: * NOTE that we will assign the model group definition
20028: * itself to the "term" of the particle. This will ease
20029: * the check for circular model group definitions. After
20030: * that the "term" will be assigned the model group of the
20031: * model group definition.
20032: */
20033: if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20034: XML_SCHEMA_TYPE_ALL) {
20035: /*
20036: * SPEC cos-all-limited (1)
20037: * SPEC cos-all-limited (1.2)
20038: * "It appears only as the value of one or both of the
20039: * following properties:"
20040: * (1.1) "the {model group} property of a model group
20041: * definition."
20042: * (1.2) "the {term} property of a particle [... of] the "
20043: * {content type} of a complex type definition."
20044: */
20045: xmlSchemaCustomErr(ACTXT_CAST ctxt,
20046: /* TODO: error code */
20047: XML_SCHEMAP_COS_ALL_LIMITED,
20048: WXS_ITEM_NODE(particle), NULL,
20049: "A model group definition is referenced, but "
20050: "it contains an 'all' model group, which "
20051: "cannot be contained by model groups",
20052: NULL, NULL);
20053: /* TODO: remove the particle. */
20054: goto next_particle;
20055: }
20056: particle->children = (xmlSchemaTreeItemPtr) refItem;
20057: } else {
20058: /*
20059: * TODO: Are referenced element declarations the only
20060: * other components we expect here?
20061: */
20062: particle->children = (xmlSchemaTreeItemPtr) refItem;
20063: }
20064: next_particle:
20065: particle = WXS_PTC_CAST particle->next;
20066: }
20067: }
20068:
20069: static int
20070: xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20071: xmlSchemaValPtr y)
20072: {
20073: xmlSchemaTypePtr tx, ty, ptx, pty;
20074: int ret;
20075:
20076: while (x != NULL) {
20077: /* Same types. */
20078: tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20079: ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20080: ptx = xmlSchemaGetPrimitiveType(tx);
20081: pty = xmlSchemaGetPrimitiveType(ty);
20082: /*
20083: * (1) if a datatype T' is �derived� by �restriction� from an
20084: * atomic datatype T then the �value space� of T' is a subset of
20085: * the �value space� of T. */
20086: /*
20087: * (2) if datatypes T' and T'' are �derived� by �restriction�
20088: * from a common atomic ancestor T then the �value space�s of T'
20089: * and T'' may overlap.
20090: */
20091: if (ptx != pty)
20092: return(0);
20093: /*
20094: * We assume computed values to be normalized, so do a fast
20095: * string comparison for string based types.
20096: */
20097: if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20098: WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20099: if (! xmlStrEqual(
20100: xmlSchemaValueGetAsString(x),
20101: xmlSchemaValueGetAsString(y)))
20102: return (0);
20103: } else {
20104: ret = xmlSchemaCompareValuesWhtsp(
20105: x, XML_SCHEMA_WHITESPACE_PRESERVE,
20106: y, XML_SCHEMA_WHITESPACE_PRESERVE);
20107: if (ret == -2)
20108: return(-1);
20109: if (ret != 0)
20110: return(0);
20111: }
20112: /*
20113: * Lists.
20114: */
20115: x = xmlSchemaValueGetNext(x);
20116: if (x != NULL) {
20117: y = xmlSchemaValueGetNext(y);
20118: if (y == NULL)
20119: return (0);
20120: } else if (xmlSchemaValueGetNext(y) != NULL)
20121: return (0);
20122: else
20123: return (1);
20124: }
20125: return (0);
20126: }
20127:
20128: /**
20129: * xmlSchemaResolveAttrUseReferences:
20130: * @item: an attribute use
20131: * @ctxt: a parser context
20132: *
20133: * Resolves the referenced attribute declaration.
20134: */
20135: static int
20136: xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20137: xmlSchemaParserCtxtPtr ctxt)
20138: {
20139: if ((ctxt == NULL) || (ause == NULL))
20140: return(-1);
20141: if ((ause->attrDecl == NULL) ||
20142: (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20143: return(0);
20144:
20145: {
20146: xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20147:
20148: /*
20149: * TODO: Evaluate, what errors could occur if the declaration is not
20150: * found.
20151: */
20152: ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20153: ref->name, ref->targetNamespace);
20154: if (ause->attrDecl == NULL) {
20155: xmlSchemaPResCompAttrErr(ctxt,
20156: XML_SCHEMAP_SRC_RESOLVE,
20157: WXS_BASIC_CAST ause, ause->node,
20158: "ref", ref->name, ref->targetNamespace,
20159: XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20160: return(ctxt->err);;
20161: }
20162: }
20163: return(0);
20164: }
20165:
20166: /**
20167: * xmlSchemaCheckAttrUsePropsCorrect:
20168: * @ctxt: a parser context
20169: * @use: an attribute use
20170: *
20171: * Schema Component Constraint:
20172: * Attribute Use Correct (au-props-correct)
20173: *
20174: */
20175: static int
20176: xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20177: xmlSchemaAttributeUsePtr use)
20178: {
20179: if ((ctxt == NULL) || (use == NULL))
20180: return(-1);
20181: if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20182: ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20183: return(0);
20184:
20185: /*
20186: * SPEC au-props-correct (1)
20187: * "The values of the properties of an attribute use must be as
20188: * described in the property tableau in The Attribute Use Schema
20189: * Component (�3.5.1), modulo the impact of Missing
20190: * Sub-components (�5.3)."
20191: */
20192:
20193: if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20194: ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20195: ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20196: {
20197: xmlSchemaPCustomErr(ctxt,
20198: XML_SCHEMAP_AU_PROPS_CORRECT_2,
20199: WXS_BASIC_CAST use, NULL,
20200: "The attribute declaration has a 'fixed' value constraint "
20201: ", thus the attribute use must also have a 'fixed' value "
20202: "constraint",
20203: NULL);
20204: return(ctxt->err);
20205: }
20206: /*
20207: * Compute and check the value constraint's value.
20208: */
20209: if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20210: int ret;
20211: /*
20212: * TODO: The spec seems to be missing a check of the
20213: * value constraint of the attribute use. We will do it here.
20214: */
20215: /*
20216: * SPEC a-props-correct (3)
20217: */
20218: if (xmlSchemaIsDerivedFromBuiltInType(
20219: WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20220: {
20221: xmlSchemaCustomErr(ACTXT_CAST ctxt,
20222: XML_SCHEMAP_AU_PROPS_CORRECT,
20223: NULL, WXS_BASIC_CAST use,
20224: "Value constraints are not allowed if the type definition "
20225: "is or is derived from xs:ID",
20226: NULL, NULL);
20227: return(ctxt->err);
20228: }
20229:
20230: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20231: use->node, WXS_ATTRUSE_TYPEDEF(use),
20232: use->defValue, &(use->defVal),
20233: 1, 1, 0);
20234: if (ret != 0) {
20235: if (ret < 0) {
20236: PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20237: "calling xmlSchemaVCheckCVCSimpleType()");
20238: return(-1);
20239: }
20240: xmlSchemaCustomErr(ACTXT_CAST ctxt,
20241: XML_SCHEMAP_AU_PROPS_CORRECT,
20242: NULL, WXS_BASIC_CAST use,
20243: "The value of the value constraint is not valid",
20244: NULL, NULL);
20245: return(ctxt->err);
20246: }
20247: }
20248: /*
20249: * SPEC au-props-correct (2)
20250: * "If the {attribute declaration} has a fixed
20251: * {value constraint}, then if the attribute use itself has a
20252: * {value constraint}, it must also be fixed and its value must match
20253: * that of the {attribute declaration}'s {value constraint}."
20254: */
20255: if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20256: (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20257: {
20258: if (! xmlSchemaAreValuesEqual(use->defVal,
20259: (WXS_ATTRUSE_DECL(use))->defVal))
20260: {
20261: xmlSchemaPCustomErr(ctxt,
20262: XML_SCHEMAP_AU_PROPS_CORRECT_2,
20263: WXS_BASIC_CAST use, NULL,
20264: "The 'fixed' value constraint of the attribute use "
20265: "must match the attribute declaration's value "
20266: "constraint '%s'",
20267: (WXS_ATTRUSE_DECL(use))->defValue);
20268: }
20269: return(ctxt->err);
20270: }
20271: return(0);
20272: }
20273:
20274:
20275:
20276:
20277: /**
20278: * xmlSchemaResolveAttrTypeReferences:
20279: * @item: an attribute declaration
20280: * @ctxt: a parser context
20281: *
20282: * Resolves the referenced type definition component.
20283: */
20284: static int
20285: xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20286: xmlSchemaParserCtxtPtr ctxt)
20287: {
20288: /*
20289: * The simple type definition corresponding to the <simpleType> element
20290: * information item in the [children], if present, otherwise the simple
20291: * type definition �resolved� to by the �actual value� of the type
20292: * [attribute], if present, otherwise the �simple ur-type definition�.
20293: */
20294: if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20295: return(0);
20296: item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20297: if (item->subtypes != NULL)
20298: return(0);
20299: if (item->typeName != NULL) {
20300: xmlSchemaTypePtr type;
20301:
20302: type = xmlSchemaGetType(ctxt->schema, item->typeName,
20303: item->typeNs);
20304: if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20305: xmlSchemaPResCompAttrErr(ctxt,
20306: XML_SCHEMAP_SRC_RESOLVE,
20307: WXS_BASIC_CAST item, item->node,
20308: "type", item->typeName, item->typeNs,
20309: XML_SCHEMA_TYPE_SIMPLE, NULL);
20310: return(ctxt->err);
20311: } else
20312: item->subtypes = type;
20313:
20314: } else {
20315: /*
20316: * The type defaults to the xs:anySimpleType.
20317: */
20318: item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20319: }
20320: return(0);
20321: }
20322:
20323: /**
20324: * xmlSchemaResolveIDCKeyReferences:
20325: * @idc: the identity-constraint definition
20326: * @ctxt: the schema parser context
20327: * @name: the attribute name
20328: *
20329: * Resolve keyRef references to key/unique IDCs.
20330: * Schema Component Constraint:
20331: * Identity-constraint Definition Properties Correct (c-props-correct)
20332: */
20333: static int
20334: xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20335: xmlSchemaParserCtxtPtr pctxt)
20336: {
20337: if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20338: return(0);
20339: if (idc->ref->name != NULL) {
20340: idc->ref->item = (xmlSchemaBasicItemPtr)
20341: xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20342: idc->ref->targetNamespace);
20343: if (idc->ref->item == NULL) {
20344: /*
20345: * TODO: It is actually not an error to fail to resolve
20346: * at this stage. BUT we need to be that strict!
20347: */
20348: xmlSchemaPResCompAttrErr(pctxt,
20349: XML_SCHEMAP_SRC_RESOLVE,
20350: WXS_BASIC_CAST idc, idc->node,
20351: "refer", idc->ref->name,
20352: idc->ref->targetNamespace,
20353: XML_SCHEMA_TYPE_IDC_KEY, NULL);
20354: return(pctxt->err);
20355: } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20356: /*
20357: * SPEC c-props-correct (1)
20358: */
20359: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20360: XML_SCHEMAP_C_PROPS_CORRECT,
20361: NULL, WXS_BASIC_CAST idc,
20362: "The keyref references a keyref",
20363: NULL, NULL);
20364: idc->ref->item = NULL;
20365: return(pctxt->err);
20366: } else {
20367: if (idc->nbFields !=
20368: ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20369: xmlChar *str = NULL;
20370: xmlSchemaIDCPtr refer;
20371:
20372: refer = (xmlSchemaIDCPtr) idc->ref->item;
20373: /*
20374: * SPEC c-props-correct(2)
20375: * "If the {identity-constraint category} is keyref,
20376: * the cardinality of the {fields} must equal that of
20377: * the {fields} of the {referenced key}.
20378: */
20379: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20380: XML_SCHEMAP_C_PROPS_CORRECT,
20381: NULL, WXS_BASIC_CAST idc,
20382: "The cardinality of the keyref differs from the "
20383: "cardinality of the referenced key/unique '%s'",
20384: xmlSchemaFormatQName(&str, refer->targetNamespace,
20385: refer->name),
20386: NULL);
20387: FREE_AND_NULL(str)
20388: return(pctxt->err);
20389: }
20390: }
20391: }
20392: return(0);
20393: }
20394:
20395: static int
20396: xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20397: xmlSchemaParserCtxtPtr pctxt)
20398: {
20399: if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20400: prohib->targetNamespace) == NULL) {
20401:
20402: xmlSchemaPResCompAttrErr(pctxt,
20403: XML_SCHEMAP_SRC_RESOLVE,
20404: NULL, prohib->node,
20405: "ref", prohib->name, prohib->targetNamespace,
20406: XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20407: return(XML_SCHEMAP_SRC_RESOLVE);
20408: }
20409: return(0);
20410: }
20411:
20412: #define WXS_REDEFINED_TYPE(c) \
20413: (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20414:
20415: #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20416: (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20417:
20418: #define WXS_REDEFINED_ATTR_GROUP(c) \
20419: (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20420:
20421: static int
20422: xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20423: {
20424: int err = 0;
20425: xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20426: xmlSchemaBasicItemPtr prev, item;
20427: int wasRedefined;
20428:
20429: if (redef == NULL)
20430: return(0);
20431:
20432: do {
20433: item = redef->item;
20434: /*
20435: * First try to locate the redefined component in the
20436: * schema graph starting with the redefined schema.
20437: * NOTE: According to this schema bug entry:
20438: * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20439: * it's not clear if the referenced component needs to originate
20440: * from the <redefine>d schema _document_ or the schema; the latter
20441: * would include all imported and included sub-schemas of the
20442: * <redefine>d schema. Currenlty we latter approach is used.
20443: * SUPPLEMENT: It seems that the WG moves towards the latter
20444: * approach, so we are doing it right.
20445: *
20446: */
20447: prev = xmlSchemaFindRedefCompInGraph(
20448: redef->targetBucket, item->type,
20449: redef->refName, redef->refTargetNs);
20450: if (prev == NULL) {
20451: xmlChar *str = NULL;
20452: xmlNodePtr node;
20453:
20454: /*
20455: * SPEC src-redefine:
20456: * (6.2.1) "The �actual value� of its own name attribute plus
20457: * target namespace must successfully �resolve� to a model
20458: * group definition in I."
20459: * (7.2.1) "The �actual value� of its own name attribute plus
20460: * target namespace must successfully �resolve� to an attribute
20461: * group definition in I."
20462:
20463: *
20464: * Note that, if we are redefining with the use of references
20465: * to components, the spec assumes the src-resolve to be used;
20466: * but this won't assure that we search only *inside* the
20467: * redefined schema.
20468: */
20469: if (redef->reference)
20470: node = WXS_ITEM_NODE(redef->reference);
20471: else
20472: node = WXS_ITEM_NODE(item);
20473: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20474: /*
20475: * TODO: error code.
20476: * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20477: * reference kind.
20478: */
20479: XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20480: "The %s '%s' to be redefined could not be found in "
20481: "the redefined schema",
20482: WXS_ITEM_TYPE_NAME(item),
20483: xmlSchemaFormatQName(&str, redef->refTargetNs,
20484: redef->refName));
20485: FREE_AND_NULL(str);
20486: err = pctxt->err;
20487: redef = redef->next;
20488: continue;
20489: }
20490: /*
20491: * TODO: Obtaining and setting the redefinition state is really
20492: * clumsy.
20493: */
20494: wasRedefined = 0;
20495: switch (item->type) {
20496: case XML_SCHEMA_TYPE_COMPLEX:
20497: case XML_SCHEMA_TYPE_SIMPLE:
20498: if ((WXS_TYPE_CAST prev)->flags &
20499: XML_SCHEMAS_TYPE_REDEFINED)
20500: {
20501: wasRedefined = 1;
20502: break;
20503: }
20504: /* Mark it as redefined. */
20505: (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20506: /*
20507: * Assign the redefined type to the
20508: * base type of the redefining type.
20509: * TODO: How
20510: */
20511: ((xmlSchemaTypePtr) item)->baseType =
20512: (xmlSchemaTypePtr) prev;
20513: break;
20514: case XML_SCHEMA_TYPE_GROUP:
20515: if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20516: XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20517: {
20518: wasRedefined = 1;
20519: break;
20520: }
20521: /* Mark it as redefined. */
20522: (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20523: XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20524: if (redef->reference != NULL) {
20525: /*
20526: * Overwrite the QName-reference with the
20527: * referenced model group def.
20528: */
20529: (WXS_PTC_CAST redef->reference)->children =
20530: WXS_TREE_CAST prev;
20531: }
20532: redef->target = prev;
20533: break;
20534: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20535: if ((WXS_ATTR_GROUP_CAST prev)->flags &
20536: XML_SCHEMAS_ATTRGROUP_REDEFINED)
20537: {
20538: wasRedefined = 1;
20539: break;
20540: }
20541: (WXS_ATTR_GROUP_CAST prev)->flags |=
20542: XML_SCHEMAS_ATTRGROUP_REDEFINED;
20543: if (redef->reference != NULL) {
20544: /*
20545: * Assign the redefined attribute group to the
20546: * QName-reference component.
20547: * This is the easy case, since we will just
20548: * expand the redefined group.
20549: */
20550: (WXS_QNAME_CAST redef->reference)->item = prev;
20551: redef->target = NULL;
20552: } else {
20553: /*
20554: * This is the complicated case: we need
20555: * to apply src-redefine (7.2.2) at a later
20556: * stage, i.e. when attribute group references
20557: * have beed expanded and simple types have
20558: * beed fixed.
20559: */
20560: redef->target = prev;
20561: }
20562: break;
20563: default:
20564: PERROR_INT("xmlSchemaResolveRedefReferences",
20565: "Unexpected redefined component type");
20566: return(-1);
20567: }
20568: if (wasRedefined) {
20569: xmlChar *str = NULL;
20570: xmlNodePtr node;
20571:
20572: if (redef->reference)
20573: node = WXS_ITEM_NODE(redef->reference);
20574: else
20575: node = WXS_ITEM_NODE(redef->item);
20576:
20577: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20578: /* TODO: error code. */
20579: XML_SCHEMAP_SRC_REDEFINE,
20580: node, NULL,
20581: "The referenced %s was already redefined. Multiple "
20582: "redefinition of the same component is not supported",
20583: xmlSchemaGetComponentDesignation(&str, prev),
20584: NULL);
20585: FREE_AND_NULL(str)
20586: err = pctxt->err;
20587: redef = redef->next;
20588: continue;
20589: }
20590: redef = redef->next;
20591: } while (redef != NULL);
20592:
20593: return(err);
20594: }
20595:
20596: static int
20597: xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20598: {
20599: int err = 0;
20600: xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20601: xmlSchemaBasicItemPtr item;
20602:
20603: if (redef == NULL)
20604: return(0);
20605:
20606: do {
20607: if (redef->target == NULL) {
20608: redef = redef->next;
20609: continue;
20610: }
20611: item = redef->item;
20612:
20613: switch (item->type) {
20614: case XML_SCHEMA_TYPE_SIMPLE:
20615: case XML_SCHEMA_TYPE_COMPLEX:
20616: /*
20617: * Since the spec wants the {name} of the redefined
20618: * type to be 'absent', we'll NULL it.
20619: */
20620: (WXS_TYPE_CAST redef->target)->name = NULL;
20621:
20622: /*
20623: * TODO: Seems like there's nothing more to do. The normal
20624: * inheritance mechanism is used. But not 100% sure.
20625: */
20626: break;
20627: case XML_SCHEMA_TYPE_GROUP:
20628: /*
20629: * URGENT TODO:
20630: * SPEC src-redefine:
20631: * (6.2.2) "The {model group} of the model group definition
20632: * which corresponds to it per XML Representation of Model
20633: * Group Definition Schema Components (�3.7.2) must be a
20634: * �valid restriction� of the {model group} of that model
20635: * group definition in I, as defined in Particle Valid
20636: * (Restriction) (�3.9.6)."
20637: */
20638: break;
20639: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20640: /*
20641: * SPEC src-redefine:
20642: * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20643: * the attribute group definition which corresponds to it
20644: * per XML Representation of Attribute Group Definition Schema
20645: * Components (�3.6.2) must be �valid restrictions� of the
20646: * {attribute uses} and {attribute wildcard} of that attribute
20647: * group definition in I, as defined in clause 2, clause 3 and
20648: * clause 4 of Derivation Valid (Restriction, Complex)
20649: * (�3.4.6) (where references to the base type definition are
20650: * understood as references to the attribute group definition
20651: * in I)."
20652: */
20653: err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20654: XML_SCHEMA_ACTION_REDEFINE,
20655: item, redef->target,
20656: (WXS_ATTR_GROUP_CAST item)->attrUses,
20657: (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20658: (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20659: (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20660: if (err == -1)
20661: return(-1);
20662: break;
20663: default:
20664: break;
20665: }
20666: redef = redef->next;
20667: } while (redef != NULL);
20668: return(0);
20669: }
20670:
20671:
20672: static int
20673: xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20674: xmlSchemaBucketPtr bucket)
20675: {
20676: xmlSchemaBasicItemPtr item;
20677: int err;
20678: xmlHashTablePtr *table;
20679: const xmlChar *name;
20680: int i;
20681:
20682: #define WXS_GET_GLOBAL_HASH(c, slot) { \
20683: if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20684: table = &(WXS_IMPBUCKET((c))->schema->slot); \
20685: else \
20686: table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20687:
20688: /*
20689: * Add global components to the schema's hash tables.
20690: * This is the place where duplicate components will be
20691: * detected.
20692: * TODO: I think normally we should support imports of the
20693: * same namespace from multiple locations. We don't do currently,
20694: * but if we do then according to:
20695: * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20696: * we would need, if imported directly, to import redefined
20697: * components as well to be able to catch clashing components.
20698: * (I hope I'll still know what this means after some months :-()
20699: */
20700: if (bucket == NULL)
20701: return(-1);
20702: if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20703: return(0);
20704: bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20705:
20706: for (i = 0; i < bucket->globals->nbItems; i++) {
20707: item = bucket->globals->items[i];
20708: table = NULL;
20709: switch (item->type) {
20710: case XML_SCHEMA_TYPE_COMPLEX:
20711: case XML_SCHEMA_TYPE_SIMPLE:
20712: if (WXS_REDEFINED_TYPE(item))
20713: continue;
20714: name = (WXS_TYPE_CAST item)->name;
20715: WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20716: break;
20717: case XML_SCHEMA_TYPE_ELEMENT:
20718: name = (WXS_ELEM_CAST item)->name;
20719: WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20720: break;
20721: case XML_SCHEMA_TYPE_ATTRIBUTE:
20722: name = (WXS_ATTR_CAST item)->name;
20723: WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20724: break;
20725: case XML_SCHEMA_TYPE_GROUP:
20726: if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20727: continue;
20728: name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20729: WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20730: break;
20731: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20732: if (WXS_REDEFINED_ATTR_GROUP(item))
20733: continue;
20734: name = (WXS_ATTR_GROUP_CAST item)->name;
20735: WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20736: break;
20737: case XML_SCHEMA_TYPE_IDC_KEY:
20738: case XML_SCHEMA_TYPE_IDC_UNIQUE:
20739: case XML_SCHEMA_TYPE_IDC_KEYREF:
20740: name = (WXS_IDC_CAST item)->name;
20741: WXS_GET_GLOBAL_HASH(bucket, idcDef)
20742: break;
20743: case XML_SCHEMA_TYPE_NOTATION:
20744: name = ((xmlSchemaNotationPtr) item)->name;
20745: WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20746: break;
20747: default:
20748: PERROR_INT("xmlSchemaAddComponents",
20749: "Unexpected global component type");
20750: continue;
20751: }
20752: if (*table == NULL) {
20753: *table = xmlHashCreateDict(10, pctxt->dict);
20754: if (*table == NULL) {
20755: PERROR_INT("xmlSchemaAddComponents",
20756: "failed to create a component hash table");
20757: return(-1);
20758: }
20759: }
20760: err = xmlHashAddEntry(*table, name, item);
20761: if (err != 0) {
20762: xmlChar *str = NULL;
20763:
20764: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20765: XML_SCHEMAP_REDEFINED_TYPE,
20766: WXS_ITEM_NODE(item),
20767: WXS_BASIC_CAST item,
20768: "A global %s '%s' does already exist",
20769: WXS_ITEM_TYPE_NAME(item),
20770: xmlSchemaGetComponentQName(&str, item));
20771: FREE_AND_NULL(str);
20772: }
20773: }
20774: /*
20775: * Process imported/included schemas.
20776: */
20777: if (bucket->relations != NULL) {
20778: xmlSchemaSchemaRelationPtr rel = bucket->relations;
20779: do {
20780: if ((rel->bucket != NULL) &&
20781: ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20782: if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20783: return(-1);
20784: }
20785: rel = rel->next;
20786: } while (rel != NULL);
20787: }
20788: return(0);
20789: }
20790:
20791: static int
20792: xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20793: xmlSchemaBucketPtr rootBucket)
20794: {
20795: xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20796: xmlSchemaTreeItemPtr item, *items;
20797: int nbItems, i, ret = 0;
20798: xmlSchemaBucketPtr oldbucket = con->bucket;
20799: xmlSchemaElementPtr elemDecl;
20800:
20801: #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20802:
20803: if ((con->pending == NULL) ||
20804: (con->pending->nbItems == 0))
20805: return(0);
20806:
20807: /*
20808: * Since xmlSchemaFixupComplexType() will create new particles
20809: * (local components), and those particle components need a bucket
20810: * on the constructor, we'll assure here that the constructor has
20811: * a bucket.
20812: * TODO: Think about storing locals _only_ on the main bucket.
20813: */
20814: if (con->bucket == NULL)
20815: con->bucket = rootBucket;
20816:
20817: /* TODO:
20818: * SPEC (src-redefine):
20819: * (6.2) "If it has no such self-reference, then all of the
20820: * following must be true:"
20821:
20822: * (6.2.2) The {model group} of the model group definition which
20823: * corresponds to it per XML Representation of Model Group
20824: * Definition Schema Components (�3.7.2) must be a �valid
20825: * restriction� of the {model group} of that model group definition
20826: * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20827: */
20828: xmlSchemaCheckSRCRedefineFirst(pctxt);
20829:
20830: /*
20831: * Add global components to the schemata's hash tables.
20832: */
20833: xmlSchemaAddComponents(pctxt, rootBucket);
20834:
20835: pctxt->ctxtType = NULL;
20836: items = (xmlSchemaTreeItemPtr *) con->pending->items;
20837: nbItems = con->pending->nbItems;
20838: /*
20839: * Now that we have parsed *all* the schema document(s) and converted
20840: * them to schema components, we can resolve references, apply component
20841: * constraints, create the FSA from the content model, etc.
20842: */
20843: /*
20844: * Resolve references of..
20845: *
20846: * 1. element declarations:
20847: * - the type definition
20848: * - the substitution group affiliation
20849: * 2. simple/complex types:
20850: * - the base type definition
20851: * - the memberTypes of union types
20852: * - the itemType of list types
20853: * 3. attributes declarations and attribute uses:
20854: * - the type definition
20855: * - if an attribute use, then the attribute declaration
20856: * 4. attribute group references:
20857: * - the attribute group definition
20858: * 5. particles:
20859: * - the term of the particle (e.g. a model group)
20860: * 6. IDC key-references:
20861: * - the referenced IDC 'key' or 'unique' definition
20862: * 7. Attribute prohibitions which had a "ref" attribute.
20863: */
20864: for (i = 0; i < nbItems; i++) {
20865: item = items[i];
20866: switch (item->type) {
20867: case XML_SCHEMA_TYPE_ELEMENT:
20868: xmlSchemaResolveElementReferences(
20869: (xmlSchemaElementPtr) item, pctxt);
20870: FIXHFAILURE;
20871: break;
20872: case XML_SCHEMA_TYPE_COMPLEX:
20873: case XML_SCHEMA_TYPE_SIMPLE:
20874: xmlSchemaResolveTypeReferences(
20875: (xmlSchemaTypePtr) item, pctxt);
20876: FIXHFAILURE;
20877: break;
20878: case XML_SCHEMA_TYPE_ATTRIBUTE:
20879: xmlSchemaResolveAttrTypeReferences(
20880: (xmlSchemaAttributePtr) item, pctxt);
20881: FIXHFAILURE;
20882: break;
20883: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20884: xmlSchemaResolveAttrUseReferences(
20885: (xmlSchemaAttributeUsePtr) item, pctxt);
20886: FIXHFAILURE;
20887: break;
20888: case XML_SCHEMA_EXTRA_QNAMEREF:
20889: if ((WXS_QNAME_CAST item)->itemType ==
20890: XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20891: {
20892: xmlSchemaResolveAttrGroupReferences(
20893: WXS_QNAME_CAST item, pctxt);
20894: }
20895: FIXHFAILURE;
20896: break;
20897: case XML_SCHEMA_TYPE_SEQUENCE:
20898: case XML_SCHEMA_TYPE_CHOICE:
20899: case XML_SCHEMA_TYPE_ALL:
20900: xmlSchemaResolveModelGroupParticleReferences(pctxt,
20901: WXS_MODEL_GROUP_CAST item);
20902: FIXHFAILURE;
20903: break;
20904: case XML_SCHEMA_TYPE_IDC_KEY:
20905: case XML_SCHEMA_TYPE_IDC_UNIQUE:
20906: case XML_SCHEMA_TYPE_IDC_KEYREF:
20907: xmlSchemaResolveIDCKeyReferences(
20908: (xmlSchemaIDCPtr) item, pctxt);
20909: FIXHFAILURE;
20910: break;
20911: case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20912: /*
20913: * Handle attribue prohibition which had a
20914: * "ref" attribute.
20915: */
20916: xmlSchemaResolveAttrUseProhibReferences(
20917: WXS_ATTR_PROHIB_CAST item, pctxt);
20918: FIXHFAILURE;
20919: break;
20920: default:
20921: break;
20922: }
20923: }
20924: if (pctxt->nberrors != 0)
20925: goto exit_error;
20926:
20927: /*
20928: * Now that all references are resolved we
20929: * can check for circularity of...
20930: * 1. the base axis of type definitions
20931: * 2. nested model group definitions
20932: * 3. nested attribute group definitions
20933: * TODO: check for circual substitution groups.
20934: */
20935: for (i = 0; i < nbItems; i++) {
20936: item = items[i];
20937: /*
20938: * Let's better stop on the first error here.
20939: */
20940: switch (item->type) {
20941: case XML_SCHEMA_TYPE_COMPLEX:
20942: case XML_SCHEMA_TYPE_SIMPLE:
20943: xmlSchemaCheckTypeDefCircular(
20944: (xmlSchemaTypePtr) item, pctxt);
20945: FIXHFAILURE;
20946: if (pctxt->nberrors != 0)
20947: goto exit_error;
20948: break;
20949: case XML_SCHEMA_TYPE_GROUP:
20950: xmlSchemaCheckGroupDefCircular(
20951: (xmlSchemaModelGroupDefPtr) item, pctxt);
20952: FIXHFAILURE;
20953: if (pctxt->nberrors != 0)
20954: goto exit_error;
20955: break;
20956: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20957: xmlSchemaCheckAttrGroupCircular(
20958: (xmlSchemaAttributeGroupPtr) item, pctxt);
20959: FIXHFAILURE;
20960: if (pctxt->nberrors != 0)
20961: goto exit_error;
20962: break;
20963: default:
20964: break;
20965: }
20966: }
20967: if (pctxt->nberrors != 0)
20968: goto exit_error;
20969: /*
20970: * Model group definition references:
20971: * Such a reference is reflected by a particle at the component
20972: * level. Until now the 'term' of such particles pointed
20973: * to the model group definition; this was done, in order to
20974: * ease circularity checks. Now we need to set the 'term' of
20975: * such particles to the model group of the model group definition.
20976: */
20977: for (i = 0; i < nbItems; i++) {
20978: item = items[i];
20979: switch (item->type) {
20980: case XML_SCHEMA_TYPE_SEQUENCE:
20981: case XML_SCHEMA_TYPE_CHOICE:
20982: xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20983: WXS_MODEL_GROUP_CAST item);
20984: break;
20985: default:
20986: break;
20987: }
20988: }
20989: if (pctxt->nberrors != 0)
20990: goto exit_error;
20991: /*
20992: * Expand attribute group references of attribute group definitions.
20993: */
20994: for (i = 0; i < nbItems; i++) {
20995: item = items[i];
20996: switch (item->type) {
20997: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20998: if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20999: WXS_ATTR_GROUP_HAS_REFS(item))
21000: {
21001: xmlSchemaAttributeGroupExpandRefs(pctxt,
21002: WXS_ATTR_GROUP_CAST item);
21003: FIXHFAILURE;
21004: }
21005: break;
21006: default:
21007: break;
21008: }
21009: }
21010: if (pctxt->nberrors != 0)
21011: goto exit_error;
21012: /*
21013: * First compute the variety of simple types. This is needed as
21014: * a seperate step, since otherwise we won't be able to detect
21015: * circular union types in all cases.
21016: */
21017: for (i = 0; i < nbItems; i++) {
21018: item = items[i];
21019: switch (item->type) {
21020: case XML_SCHEMA_TYPE_SIMPLE:
21021: if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21022: xmlSchemaFixupSimpleTypeStageOne(pctxt,
21023: (xmlSchemaTypePtr) item);
21024: FIXHFAILURE;
21025: }
21026: break;
21027: default:
21028: break;
21029: }
21030: }
21031: if (pctxt->nberrors != 0)
21032: goto exit_error;
21033: /*
21034: * Detect circular union types. Note that this needs the variety to
21035: * be already computed.
21036: */
21037: for (i = 0; i < nbItems; i++) {
21038: item = items[i];
21039: switch (item->type) {
21040: case XML_SCHEMA_TYPE_SIMPLE:
21041: if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21042: xmlSchemaCheckUnionTypeDefCircular(pctxt,
21043: (xmlSchemaTypePtr) item);
21044: FIXHFAILURE;
21045: }
21046: break;
21047: default:
21048: break;
21049: }
21050: }
21051: if (pctxt->nberrors != 0)
21052: goto exit_error;
21053:
21054: /*
21055: * Do the complete type fixup for simple types.
21056: */
21057: for (i = 0; i < nbItems; i++) {
21058: item = items[i];
21059: switch (item->type) {
21060: case XML_SCHEMA_TYPE_SIMPLE:
21061: if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21062: xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21063: FIXHFAILURE;
21064: }
21065: break;
21066: default:
21067: break;
21068: }
21069: }
21070: if (pctxt->nberrors != 0)
21071: goto exit_error;
21072: /*
21073: * At this point we need build and check all simple types.
21074: */
21075: /*
21076: * Apply contraints for attribute declarations.
21077: */
21078: for (i = 0; i < nbItems; i++) {
21079: item = items[i];
21080: switch (item->type) {
21081: case XML_SCHEMA_TYPE_ATTRIBUTE:
21082: xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21083: FIXHFAILURE;
21084: break;
21085: default:
21086: break;
21087: }
21088: }
21089: if (pctxt->nberrors != 0)
21090: goto exit_error;
21091: /*
21092: * Apply constraints for attribute uses.
21093: */
21094: for (i = 0; i < nbItems; i++) {
21095: item = items[i];
21096: switch (item->type) {
21097: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21098: if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21099: xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21100: WXS_ATTR_USE_CAST item);
21101: FIXHFAILURE;
21102: }
21103: break;
21104: default:
21105: break;
21106: }
21107: }
21108: if (pctxt->nberrors != 0)
21109: goto exit_error;
21110:
21111: /*
21112: * Apply constraints for attribute group definitions.
21113: */
21114: for (i = 0; i < nbItems; i++) {
21115: item = items[i];
21116: switch (item->type) {
21117: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21118: if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21119: ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21120: {
21121: xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_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: * Apply constraints for redefinitions.
21134: */
21135: if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21136: xmlSchemaCheckSRCRedefineSecond(pctxt);
21137: if (pctxt->nberrors != 0)
21138: goto exit_error;
21139:
21140: /*
21141: * Complex types are builded and checked.
21142: */
21143: for (i = 0; i < nbItems; i++) {
21144: item = con->pending->items[i];
21145: switch (item->type) {
21146: case XML_SCHEMA_TYPE_COMPLEX:
21147: if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21148: xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21149: FIXHFAILURE;
21150: }
21151: break;
21152: default:
21153: break;
21154: }
21155: }
21156: if (pctxt->nberrors != 0)
21157: goto exit_error;
21158:
21159: /*
21160: * The list could have changed, since xmlSchemaFixupComplexType()
21161: * will create particles and model groups in some cases.
21162: */
21163: items = (xmlSchemaTreeItemPtr *) con->pending->items;
21164: nbItems = con->pending->nbItems;
21165:
21166: /*
21167: * Apply some constraints for element declarations.
21168: */
21169: for (i = 0; i < nbItems; i++) {
21170: item = items[i];
21171: switch (item->type) {
21172: case XML_SCHEMA_TYPE_ELEMENT:
21173: elemDecl = (xmlSchemaElementPtr) item;
21174:
21175: if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21176: {
21177: xmlSchemaCheckElementDeclComponent(
21178: (xmlSchemaElementPtr) elemDecl, pctxt);
21179: FIXHFAILURE;
21180: }
21181:
21182: #ifdef WXS_ELEM_DECL_CONS_ENABLED
21183: /*
21184: * Schema Component Constraint: Element Declarations Consistent
21185: * Apply this constraint to local types of element declarations.
21186: */
21187: if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21188: (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21189: (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21190: {
21191: xmlSchemaCheckElementDeclConsistent(pctxt,
21192: WXS_BASIC_CAST elemDecl,
21193: WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21194: NULL, NULL, 0);
21195: }
21196: #endif
21197: break;
21198: default:
21199: break;
21200: }
21201: }
21202: if (pctxt->nberrors != 0)
21203: goto exit_error;
21204:
21205: /*
21206: * Finally we can build the automaton from the content model of
21207: * complex types.
21208: */
21209:
21210: for (i = 0; i < nbItems; i++) {
21211: item = items[i];
21212: switch (item->type) {
21213: case XML_SCHEMA_TYPE_COMPLEX:
21214: xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21215: /* FIXHFAILURE; */
21216: break;
21217: default:
21218: break;
21219: }
21220: }
21221: if (pctxt->nberrors != 0)
21222: goto exit_error;
21223: /*
21224: * URGENT TODO: cos-element-consistent
21225: */
21226: goto exit;
21227:
21228: exit_error:
21229: ret = pctxt->err;
21230: goto exit;
21231:
21232: exit_failure:
21233: ret = -1;
21234:
21235: exit:
21236: /*
21237: * Reset the constructor. This is needed for XSI acquisition, since
21238: * those items will be processed over and over again for every XSI
21239: * if not cleared here.
21240: */
21241: con->bucket = oldbucket;
21242: con->pending->nbItems = 0;
21243: if (con->substGroups != NULL) {
21244: xmlHashFree(con->substGroups,
21245: (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21246: con->substGroups = NULL;
21247: }
21248: if (con->redefs != NULL) {
21249: xmlSchemaRedefListFree(con->redefs);
21250: con->redefs = NULL;
21251: }
21252: return(ret);
21253: }
21254: /**
21255: * xmlSchemaParse:
21256: * @ctxt: a schema validation context
21257: *
21258: * parse a schema definition resource and build an internal
21259: * XML Shema struture which can be used to validate instances.
21260: *
21261: * Returns the internal XML Schema structure built from the resource or
21262: * NULL in case of error
21263: */
21264: xmlSchemaPtr
21265: xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21266: {
21267: xmlSchemaPtr mainSchema = NULL;
21268: xmlSchemaBucketPtr bucket = NULL;
21269: int res;
21270:
21271: /*
21272: * This one is used if the schema to be parsed was specified via
21273: * the API; i.e. not automatically by the validated instance document.
21274: */
21275:
21276: xmlSchemaInitTypes();
21277:
21278: if (ctxt == NULL)
21279: return (NULL);
21280:
21281: /* TODO: Init the context. Is this all we need?*/
21282: ctxt->nberrors = 0;
21283: ctxt->err = 0;
21284: ctxt->counter = 0;
21285:
21286: /* Create the *main* schema. */
21287: mainSchema = xmlSchemaNewSchema(ctxt);
21288: if (mainSchema == NULL)
21289: goto exit_failure;
21290: /*
21291: * Create the schema constructor.
21292: */
21293: if (ctxt->constructor == NULL) {
21294: ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21295: if (ctxt->constructor == NULL)
21296: return(NULL);
21297: /* Take ownership of the constructor to be able to free it. */
21298: ctxt->ownsConstructor = 1;
21299: }
21300: ctxt->constructor->mainSchema = mainSchema;
21301: /*
21302: * Locate and add the schema document.
21303: */
21304: res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21305: ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21306: NULL, NULL, &bucket);
21307: if (res == -1)
21308: goto exit_failure;
21309: if (res != 0)
21310: goto exit;
21311:
21312: if (bucket == NULL) {
21313: /* TODO: Error code, actually we failed to *locate* the schema. */
21314: if (ctxt->URL)
21315: xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21316: NULL, NULL,
21317: "Failed to locate the main schema resource at '%s'",
21318: ctxt->URL, NULL);
21319: else
21320: xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21321: NULL, NULL,
21322: "Failed to locate the main schema resource",
21323: NULL, NULL);
21324: goto exit;
21325: }
21326: /* Then do the parsing for good. */
21327: if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21328: goto exit_failure;
21329: if (ctxt->nberrors != 0)
21330: goto exit;
21331:
21332: mainSchema->doc = bucket->doc;
21333: mainSchema->preserve = ctxt->preserve;
21334:
21335: ctxt->schema = mainSchema;
21336:
21337: if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21338: goto exit_failure;
21339:
21340: /*
21341: * TODO: This is not nice, since we cannot distinguish from the
21342: * result if there was an internal error or not.
21343: */
21344: exit:
21345: if (ctxt->nberrors != 0) {
21346: if (mainSchema) {
21347: xmlSchemaFree(mainSchema);
21348: mainSchema = NULL;
21349: }
21350: if (ctxt->constructor) {
21351: xmlSchemaConstructionCtxtFree(ctxt->constructor);
21352: ctxt->constructor = NULL;
21353: ctxt->ownsConstructor = 0;
21354: }
21355: }
21356: ctxt->schema = NULL;
21357: return(mainSchema);
21358: exit_failure:
21359: /*
21360: * Quite verbose, but should catch internal errors, which were
21361: * not communitated.
21362: */
21363: if (mainSchema) {
21364: xmlSchemaFree(mainSchema);
21365: mainSchema = NULL;
21366: }
21367: if (ctxt->constructor) {
21368: xmlSchemaConstructionCtxtFree(ctxt->constructor);
21369: ctxt->constructor = NULL;
21370: ctxt->ownsConstructor = 0;
21371: }
21372: PERROR_INT2("xmlSchemaParse",
21373: "An internal error occured");
21374: ctxt->schema = NULL;
21375: return(NULL);
21376: }
21377:
21378: /**
21379: * xmlSchemaSetParserErrors:
21380: * @ctxt: a schema validation context
21381: * @err: the error callback
21382: * @warn: the warning callback
21383: * @ctx: contextual data for the callbacks
21384: *
21385: * Set the callback functions used to handle errors for a validation context
21386: */
21387: void
21388: xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21389: xmlSchemaValidityErrorFunc err,
21390: xmlSchemaValidityWarningFunc warn, void *ctx)
21391: {
21392: if (ctxt == NULL)
21393: return;
21394: ctxt->error = err;
21395: ctxt->warning = warn;
21396: ctxt->errCtxt = ctx;
21397: if (ctxt->vctxt != NULL)
21398: xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21399: }
21400:
21401: /**
21402: * xmlSchemaSetParserStructuredErrors:
21403: * @ctxt: a schema parser context
21404: * @serror: the structured error function
21405: * @ctx: the functions context
21406: *
21407: * Set the structured error callback
21408: */
21409: void
21410: xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21411: xmlStructuredErrorFunc serror,
21412: void *ctx)
21413: {
21414: if (ctxt == NULL)
21415: return;
21416: ctxt->serror = serror;
21417: ctxt->errCtxt = ctx;
21418: if (ctxt->vctxt != NULL)
21419: xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21420: }
21421:
21422: /**
21423: * xmlSchemaGetParserErrors:
21424: * @ctxt: a XMl-Schema parser context
21425: * @err: the error callback result
21426: * @warn: the warning callback result
21427: * @ctx: contextual data for the callbacks result
21428: *
21429: * Get the callback information used to handle errors for a parser context
21430: *
21431: * Returns -1 in case of failure, 0 otherwise
21432: */
21433: int
21434: xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21435: xmlSchemaValidityErrorFunc * err,
21436: xmlSchemaValidityWarningFunc * warn, void **ctx)
21437: {
21438: if (ctxt == NULL)
21439: return(-1);
21440: if (err != NULL)
21441: *err = ctxt->error;
21442: if (warn != NULL)
21443: *warn = ctxt->warning;
21444: if (ctx != NULL)
21445: *ctx = ctxt->errCtxt;
21446: return(0);
21447: }
21448:
21449: /**
21450: * xmlSchemaFacetTypeToString:
21451: * @type: the facet type
21452: *
21453: * Convert the xmlSchemaTypeType to a char string.
21454: *
21455: * Returns the char string representation of the facet type if the
21456: * type is a facet and an "Internal Error" string otherwise.
21457: */
21458: static const xmlChar *
21459: xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21460: {
21461: switch (type) {
21462: case XML_SCHEMA_FACET_PATTERN:
21463: return (BAD_CAST "pattern");
21464: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21465: return (BAD_CAST "maxExclusive");
21466: case XML_SCHEMA_FACET_MAXINCLUSIVE:
21467: return (BAD_CAST "maxInclusive");
21468: case XML_SCHEMA_FACET_MINEXCLUSIVE:
21469: return (BAD_CAST "minExclusive");
21470: case XML_SCHEMA_FACET_MININCLUSIVE:
21471: return (BAD_CAST "minInclusive");
21472: case XML_SCHEMA_FACET_WHITESPACE:
21473: return (BAD_CAST "whiteSpace");
21474: case XML_SCHEMA_FACET_ENUMERATION:
21475: return (BAD_CAST "enumeration");
21476: case XML_SCHEMA_FACET_LENGTH:
21477: return (BAD_CAST "length");
21478: case XML_SCHEMA_FACET_MAXLENGTH:
21479: return (BAD_CAST "maxLength");
21480: case XML_SCHEMA_FACET_MINLENGTH:
21481: return (BAD_CAST "minLength");
21482: case XML_SCHEMA_FACET_TOTALDIGITS:
21483: return (BAD_CAST "totalDigits");
21484: case XML_SCHEMA_FACET_FRACTIONDIGITS:
21485: return (BAD_CAST "fractionDigits");
21486: default:
21487: break;
21488: }
21489: return (BAD_CAST "Internal Error");
21490: }
21491:
21492: static xmlSchemaWhitespaceValueType
21493: xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21494: {
21495: /*
21496: * The normalization type can be changed only for types which are derived
21497: * from xsd:string.
21498: */
21499: if (type->type == XML_SCHEMA_TYPE_BASIC) {
21500: /*
21501: * Note that we assume a whitespace of preserve for anySimpleType.
21502: */
21503: if ((type->builtInType == XML_SCHEMAS_STRING) ||
21504: (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21505: return(XML_SCHEMA_WHITESPACE_PRESERVE);
21506: else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21507: return(XML_SCHEMA_WHITESPACE_REPLACE);
21508: else {
21509: /*
21510: * For all �atomic� datatypes other than string (and types �derived�
21511: * by �restriction� from it) the value of whiteSpace is fixed to
21512: * collapse
21513: * Note that this includes built-in list datatypes.
21514: */
21515: return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21516: }
21517: } else if (WXS_IS_LIST(type)) {
21518: /*
21519: * For list types the facet "whiteSpace" is fixed to "collapse".
21520: */
21521: return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21522: } else if (WXS_IS_UNION(type)) {
21523: return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21524: } else if (WXS_IS_ATOMIC(type)) {
21525: if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21526: return (XML_SCHEMA_WHITESPACE_PRESERVE);
21527: else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21528: return (XML_SCHEMA_WHITESPACE_REPLACE);
21529: else
21530: return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21531: }
21532: return (-1);
21533: }
21534:
21535: /************************************************************************
21536: * *
21537: * Simple type validation *
21538: * *
21539: ************************************************************************/
21540:
21541:
21542: /************************************************************************
21543: * *
21544: * DOM Validation code *
21545: * *
21546: ************************************************************************/
21547:
21548: /**
21549: * xmlSchemaAssembleByLocation:
21550: * @pctxt: a schema parser context
21551: * @vctxt: a schema validation context
21552: * @schema: the existing schema
21553: * @node: the node that fired the assembling
21554: * @nsName: the namespace name of the new schema
21555: * @location: the location of the schema
21556: *
21557: * Expands an existing schema by an additional schema.
21558: *
21559: * Returns 0 if the new schema is correct, a positive error code
21560: * number otherwise and -1 in case of an internal or API error.
21561: */
21562: static int
21563: xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21564: xmlSchemaPtr schema,
21565: xmlNodePtr node,
21566: const xmlChar *nsName,
21567: const xmlChar *location)
21568: {
21569: int ret = 0;
21570: xmlSchemaParserCtxtPtr pctxt;
21571: xmlSchemaBucketPtr bucket = NULL;
21572:
21573: if ((vctxt == NULL) || (schema == NULL))
21574: return (-1);
21575:
21576: if (vctxt->pctxt == NULL) {
21577: VERROR_INT("xmlSchemaAssembleByLocation",
21578: "no parser context available");
21579: return(-1);
21580: }
21581: pctxt = vctxt->pctxt;
21582: if (pctxt->constructor == NULL) {
21583: PERROR_INT("xmlSchemaAssembleByLocation",
21584: "no constructor");
21585: return(-1);
21586: }
21587: /*
21588: * Acquire the schema document.
21589: */
21590: location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21591: location, node);
21592: /*
21593: * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21594: * the process will automatically change this to
21595: * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21596: */
21597: ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21598: location, NULL, NULL, 0, node, NULL, nsName,
21599: &bucket);
21600: if (ret != 0)
21601: return(ret);
21602: if (bucket == NULL) {
21603: /*
21604: * Generate a warning that the document could not be located.
21605: */
21606: xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21607: node, NULL,
21608: "The document at location '%s' could not be acquired",
21609: location, NULL, NULL);
21610: return(ret);
21611: }
21612: /*
21613: * The first located schema will be handled as if all other
21614: * schemas imported by XSI were imported by this first schema.
21615: */
21616: if ((bucket != NULL) &&
21617: (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21618: WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21619: /*
21620: * TODO: Is this handled like an import? I.e. is it not an error
21621: * if the schema cannot be located?
21622: */
21623: if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21624: return(0);
21625: /*
21626: * We will reuse the parser context for every schema imported
21627: * directly via XSI. So reset the context.
21628: */
21629: pctxt->nberrors = 0;
21630: pctxt->err = 0;
21631: pctxt->doc = bucket->doc;
21632:
21633: ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21634: if (ret == -1) {
21635: pctxt->doc = NULL;
21636: goto exit_failure;
21637: }
21638: /* Paranoid error channelling. */
21639: if ((ret == 0) && (pctxt->nberrors != 0))
21640: ret = pctxt->err;
21641: if (pctxt->nberrors == 0) {
21642: /*
21643: * Only bother to fixup pending components, if there was
21644: * no error yet.
21645: * For every XSI acquired schema (and its sub-schemata) we will
21646: * fixup the components.
21647: */
21648: xmlSchemaFixupComponents(pctxt, bucket);
21649: ret = pctxt->err;
21650: /*
21651: * Not nice, but we need somehow to channel the schema parser
21652: * error to the validation context.
21653: */
21654: if ((ret != 0) && (vctxt->err == 0))
21655: vctxt->err = ret;
21656: vctxt->nberrors += pctxt->nberrors;
21657: } else {
21658: /* Add to validation error sum. */
21659: vctxt->nberrors += pctxt->nberrors;
21660: }
21661: pctxt->doc = NULL;
21662: return(ret);
21663: exit_failure:
21664: pctxt->doc = NULL;
21665: return (-1);
21666: }
21667:
21668: static xmlSchemaAttrInfoPtr
21669: xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21670: int metaType)
21671: {
21672: if (vctxt->nbAttrInfos == 0)
21673: return (NULL);
21674: {
21675: int i;
21676: xmlSchemaAttrInfoPtr iattr;
21677:
21678: for (i = 0; i < vctxt->nbAttrInfos; i++) {
21679: iattr = vctxt->attrInfos[i];
21680: if (iattr->metaType == metaType)
21681: return (iattr);
21682: }
21683:
21684: }
21685: return (NULL);
21686: }
21687:
21688: /**
21689: * xmlSchemaAssembleByXSI:
21690: * @vctxt: a schema validation context
21691: *
21692: * Expands an existing schema by an additional schema using
21693: * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21694: * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21695: * must be set to 1.
21696: *
21697: * Returns 0 if the new schema is correct, a positive error code
21698: * number otherwise and -1 in case of an internal or API error.
21699: */
21700: static int
21701: xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21702: {
21703: const xmlChar *cur, *end;
21704: const xmlChar *nsname = NULL, *location;
21705: int count = 0;
21706: int ret = 0;
21707: xmlSchemaAttrInfoPtr iattr;
21708:
21709: /*
21710: * Parse the value; we will assume an even number of values
21711: * to be given (this is how Xerces and XSV work).
21712: *
21713: * URGENT TODO: !! This needs to work for both
21714: * @noNamespaceSchemaLocation AND @schemaLocation on the same
21715: * element !!
21716: */
21717: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21718: XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21719: if (iattr == NULL)
21720: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21721: XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21722: if (iattr == NULL)
21723: return (0);
21724: cur = iattr->value;
21725: do {
21726: /*
21727: * TODO: Move the string parsing mechanism away from here.
21728: */
21729: if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21730: /*
21731: * Get the namespace name.
21732: */
21733: while (IS_BLANK_CH(*cur))
21734: cur++;
21735: end = cur;
21736: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21737: end++;
21738: if (end == cur)
21739: break;
21740: count++; /* TODO: Don't use the schema's dict. */
21741: nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21742: cur = end;
21743: }
21744: /*
21745: * Get the URI.
21746: */
21747: while (IS_BLANK_CH(*cur))
21748: cur++;
21749: end = cur;
21750: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21751: end++;
21752: if (end == cur) {
21753: if (iattr->metaType ==
21754: XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21755: {
21756: /*
21757: * If using @schemaLocation then tuples are expected.
21758: * I.e. the namespace name *and* the document's URI.
21759: */
21760: xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21761: iattr->node, NULL,
21762: "The value must consist of tuples: the target namespace "
21763: "name and the document's URI", NULL, NULL, NULL);
21764: }
21765: break;
21766: }
21767: count++; /* TODO: Don't use the schema's dict. */
21768: location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21769: cur = end;
21770: ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21771: iattr->node, nsname, location);
21772: if (ret == -1) {
21773: VERROR_INT("xmlSchemaAssembleByXSI",
21774: "assembling schemata");
21775: return (-1);
21776: }
21777: } while (*cur != 0);
21778: return (ret);
21779: }
21780:
21781: static const xmlChar *
21782: xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21783: const xmlChar *prefix)
21784: {
21785: if (vctxt->sax != NULL) {
21786: int i, j;
21787: xmlSchemaNodeInfoPtr inode;
21788:
21789: for (i = vctxt->depth; i >= 0; i--) {
21790: if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21791: inode = vctxt->elemInfos[i];
21792: for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21793: if (((prefix == NULL) &&
21794: (inode->nsBindings[j] == NULL)) ||
21795: ((prefix != NULL) && xmlStrEqual(prefix,
21796: inode->nsBindings[j]))) {
21797:
21798: /*
21799: * Note that the namespace bindings are already
21800: * in a string dict.
21801: */
21802: return (inode->nsBindings[j+1]);
21803: }
21804: }
21805: }
21806: }
21807: return (NULL);
21808: #ifdef LIBXML_READER_ENABLED
21809: } else if (vctxt->reader != NULL) {
21810: xmlChar *nsName;
21811:
21812: nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21813: if (nsName != NULL) {
21814: const xmlChar *ret;
21815:
21816: ret = xmlDictLookup(vctxt->dict, nsName, -1);
21817: xmlFree(nsName);
21818: return (ret);
21819: } else
21820: return (NULL);
21821: #endif
21822: } else {
21823: xmlNsPtr ns;
21824:
21825: if ((vctxt->inode->node == NULL) ||
21826: (vctxt->inode->node->doc == NULL)) {
21827: VERROR_INT("xmlSchemaLookupNamespace",
21828: "no node or node's doc avaliable");
21829: return (NULL);
21830: }
21831: ns = xmlSearchNs(vctxt->inode->node->doc,
21832: vctxt->inode->node, prefix);
21833: if (ns != NULL)
21834: return (ns->href);
21835: return (NULL);
21836: }
21837: }
21838:
21839: /*
21840: * This one works on the schema of the validation context.
21841: */
21842: static int
21843: xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21844: xmlSchemaPtr schema,
21845: xmlNodePtr node,
21846: const xmlChar *value,
21847: xmlSchemaValPtr *val,
21848: int valNeeded)
21849: {
21850: int ret;
21851:
21852: if (vctxt && (vctxt->schema == NULL)) {
21853: VERROR_INT("xmlSchemaValidateNotation",
21854: "a schema is needed on the validation context");
21855: return (-1);
21856: }
21857: ret = xmlValidateQName(value, 1);
21858: if (ret != 0)
21859: return (ret);
21860: {
21861: xmlChar *localName = NULL;
21862: xmlChar *prefix = NULL;
21863:
21864: localName = xmlSplitQName2(value, &prefix);
21865: if (prefix != NULL) {
21866: const xmlChar *nsName = NULL;
21867:
21868: if (vctxt != NULL)
21869: nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21870: else if (node != NULL) {
21871: xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21872: if (ns != NULL)
21873: nsName = ns->href;
21874: } else {
21875: xmlFree(prefix);
21876: xmlFree(localName);
21877: return (1);
21878: }
21879: if (nsName == NULL) {
21880: xmlFree(prefix);
21881: xmlFree(localName);
21882: return (1);
21883: }
21884: if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21885: if ((valNeeded) && (val != NULL)) {
21886: (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21887: xmlStrdup(nsName));
21888: if (*val == NULL)
21889: ret = -1;
21890: }
21891: } else
21892: ret = 1;
21893: xmlFree(prefix);
21894: xmlFree(localName);
21895: } else {
21896: if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21897: if (valNeeded && (val != NULL)) {
21898: (*val) = xmlSchemaNewNOTATIONValue(
21899: BAD_CAST xmlStrdup(value), NULL);
21900: if (*val == NULL)
21901: ret = -1;
21902: }
21903: } else
21904: return (1);
21905: }
21906: }
21907: return (ret);
21908: }
21909:
21910: static int
21911: xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21912: const xmlChar* lname,
21913: const xmlChar* nsname)
21914: {
21915: int i;
21916:
21917: lname = xmlDictLookup(vctxt->dict, lname, -1);
21918: if (lname == NULL)
21919: return(-1);
21920: if (nsname != NULL) {
21921: nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21922: if (nsname == NULL)
21923: return(-1);
21924: }
21925: for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21926: if ((vctxt->nodeQNames->items [i] == lname) &&
21927: (vctxt->nodeQNames->items[i +1] == nsname))
21928: /* Already there */
21929: return(i);
21930: }
21931: /* Add new entry. */
21932: i = vctxt->nodeQNames->nbItems;
21933: xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21934: xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21935: return(i);
21936: }
21937:
21938: /************************************************************************
21939: * *
21940: * Validation of identity-constraints (IDC) *
21941: * *
21942: ************************************************************************/
21943:
21944: /**
21945: * xmlSchemaAugmentIDC:
21946: * @idcDef: the IDC definition
21947: *
21948: * Creates an augmented IDC definition item.
21949: *
21950: * Returns the item, or NULL on internal errors.
21951: */
21952: static void
21953: xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21954: xmlSchemaValidCtxtPtr vctxt)
21955: {
21956: xmlSchemaIDCAugPtr aidc;
21957:
21958: aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21959: if (aidc == NULL) {
21960: xmlSchemaVErrMemory(vctxt,
21961: "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21962: NULL);
21963: return;
21964: }
21965: aidc->keyrefDepth = -1;
21966: aidc->def = idcDef;
21967: aidc->next = NULL;
21968: if (vctxt->aidcs == NULL)
21969: vctxt->aidcs = aidc;
21970: else {
21971: aidc->next = vctxt->aidcs;
21972: vctxt->aidcs = aidc;
21973: }
21974: /*
21975: * Save if we have keyrefs at all.
21976: */
21977: if ((vctxt->hasKeyrefs == 0) &&
21978: (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21979: vctxt->hasKeyrefs = 1;
21980: }
21981:
21982: /**
21983: * xmlSchemaAugmentImportedIDC:
21984: * @imported: the imported schema
21985: *
21986: * Creates an augmented IDC definition for the imported schema.
21987: */
21988: static void
21989: xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
21990: if (imported->schema->idcDef != NULL) {
21991: xmlHashScan(imported->schema->idcDef ,
21992: (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
21993: }
21994: }
21995:
21996: /**
21997: * xmlSchemaIDCNewBinding:
21998: * @idcDef: the IDC definition of this binding
21999: *
22000: * Creates a new IDC binding.
22001: *
22002: * Returns the new IDC binding, NULL on internal errors.
22003: */
22004: static xmlSchemaPSVIIDCBindingPtr
22005: xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22006: {
22007: xmlSchemaPSVIIDCBindingPtr ret;
22008:
22009: ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22010: sizeof(xmlSchemaPSVIIDCBinding));
22011: if (ret == NULL) {
22012: xmlSchemaVErrMemory(NULL,
22013: "allocating a PSVI IDC binding item", NULL);
22014: return (NULL);
22015: }
22016: memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22017: ret->definition = idcDef;
22018: return (ret);
22019: }
22020:
22021: /**
22022: * xmlSchemaIDCStoreNodeTableItem:
22023: * @vctxt: the WXS validation context
22024: * @item: the IDC node table item
22025: *
22026: * The validation context is used to store IDC node table items.
22027: * They are stored to avoid copying them if IDC node-tables are merged
22028: * with corresponding parent IDC node-tables (bubbling).
22029: *
22030: * Returns 0 if succeeded, -1 on internal errors.
22031: */
22032: static int
22033: xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22034: xmlSchemaPSVIIDCNodePtr item)
22035: {
22036: /*
22037: * Add to gobal list.
22038: */
22039: if (vctxt->idcNodes == NULL) {
22040: vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22041: xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22042: if (vctxt->idcNodes == NULL) {
22043: xmlSchemaVErrMemory(vctxt,
22044: "allocating the IDC node table item list", NULL);
22045: return (-1);
22046: }
22047: vctxt->sizeIdcNodes = 20;
22048: } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22049: vctxt->sizeIdcNodes *= 2;
22050: vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22051: xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22052: sizeof(xmlSchemaPSVIIDCNodePtr));
22053: if (vctxt->idcNodes == NULL) {
22054: xmlSchemaVErrMemory(vctxt,
22055: "re-allocating the IDC node table item list", NULL);
22056: return (-1);
22057: }
22058: }
22059: vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22060:
22061: return (0);
22062: }
22063:
22064: /**
22065: * xmlSchemaIDCStoreKey:
22066: * @vctxt: the WXS validation context
22067: * @item: the IDC key
22068: *
22069: * The validation context is used to store an IDC key.
22070: *
22071: * Returns 0 if succeeded, -1 on internal errors.
22072: */
22073: static int
22074: xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22075: xmlSchemaPSVIIDCKeyPtr key)
22076: {
22077: /*
22078: * Add to gobal list.
22079: */
22080: if (vctxt->idcKeys == NULL) {
22081: vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22082: xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22083: if (vctxt->idcKeys == NULL) {
22084: xmlSchemaVErrMemory(vctxt,
22085: "allocating the IDC key storage list", NULL);
22086: return (-1);
22087: }
22088: vctxt->sizeIdcKeys = 40;
22089: } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22090: vctxt->sizeIdcKeys *= 2;
22091: vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22092: xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22093: sizeof(xmlSchemaPSVIIDCKeyPtr));
22094: if (vctxt->idcKeys == NULL) {
22095: xmlSchemaVErrMemory(vctxt,
22096: "re-allocating the IDC key storage list", NULL);
22097: return (-1);
22098: }
22099: }
22100: vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22101:
22102: return (0);
22103: }
22104:
22105: /**
22106: * xmlSchemaIDCAppendNodeTableItem:
22107: * @bind: the IDC binding
22108: * @ntItem: the node-table item
22109: *
22110: * Appends the IDC node-table item to the binding.
22111: *
22112: * Returns 0 on success and -1 on internal errors.
22113: */
22114: static int
22115: xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22116: xmlSchemaPSVIIDCNodePtr ntItem)
22117: {
22118: if (bind->nodeTable == NULL) {
22119: bind->sizeNodes = 10;
22120: bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22121: xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22122: if (bind->nodeTable == NULL) {
22123: xmlSchemaVErrMemory(NULL,
22124: "allocating an array of IDC node-table items", NULL);
22125: return(-1);
22126: }
22127: } else if (bind->sizeNodes <= bind->nbNodes) {
22128: bind->sizeNodes *= 2;
22129: bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22130: xmlRealloc(bind->nodeTable, bind->sizeNodes *
22131: sizeof(xmlSchemaPSVIIDCNodePtr));
22132: if (bind->nodeTable == NULL) {
22133: xmlSchemaVErrMemory(NULL,
22134: "re-allocating an array of IDC node-table items", NULL);
22135: return(-1);
22136: }
22137: }
22138: bind->nodeTable[bind->nbNodes++] = ntItem;
22139: return(0);
22140: }
22141:
22142: /**
22143: * xmlSchemaIDCAcquireBinding:
22144: * @vctxt: the WXS validation context
22145: * @matcher: the IDC matcher
22146: *
22147: * Looks up an PSVI IDC binding, for the IDC definition and
22148: * of the given matcher. If none found, a new one is created
22149: * and added to the IDC table.
22150: *
22151: * Returns an IDC binding or NULL on internal errors.
22152: */
22153: static xmlSchemaPSVIIDCBindingPtr
22154: xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22155: xmlSchemaIDCMatcherPtr matcher)
22156: {
22157: xmlSchemaNodeInfoPtr ielem;
22158:
22159: ielem = vctxt->elemInfos[matcher->depth];
22160:
22161: if (ielem->idcTable == NULL) {
22162: ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22163: if (ielem->idcTable == NULL)
22164: return (NULL);
22165: return(ielem->idcTable);
22166: } else {
22167: xmlSchemaPSVIIDCBindingPtr bind = NULL;
22168:
22169: bind = ielem->idcTable;
22170: do {
22171: if (bind->definition == matcher->aidc->def)
22172: return(bind);
22173: if (bind->next == NULL) {
22174: bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22175: if (bind->next == NULL)
22176: return (NULL);
22177: return(bind->next);
22178: }
22179: bind = bind->next;
22180: } while (bind != NULL);
22181: }
22182: return (NULL);
22183: }
22184:
22185: static xmlSchemaItemListPtr
22186: xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22187: xmlSchemaIDCMatcherPtr matcher)
22188: {
22189: if (matcher->targets == NULL)
22190: matcher->targets = xmlSchemaItemListCreate();
22191: return(matcher->targets);
22192: }
22193:
22194: /**
22195: * xmlSchemaIDCFreeKey:
22196: * @key: the IDC key
22197: *
22198: * Frees an IDC key together with its compiled value.
22199: */
22200: static void
22201: xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22202: {
22203: if (key->val != NULL)
22204: xmlSchemaFreeValue(key->val);
22205: xmlFree(key);
22206: }
22207:
22208: /**
22209: * xmlSchemaIDCFreeBinding:
22210: *
22211: * Frees an IDC binding. Note that the node table-items
22212: * are not freed.
22213: */
22214: static void
22215: xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22216: {
22217: if (bind->nodeTable != NULL)
22218: xmlFree(bind->nodeTable);
22219: if (bind->dupls != NULL)
22220: xmlSchemaItemListFree(bind->dupls);
22221: xmlFree(bind);
22222: }
22223:
22224: /**
22225: * xmlSchemaIDCFreeIDCTable:
22226: * @bind: the first IDC binding in the list
22227: *
22228: * Frees an IDC table, i.e. all the IDC bindings in the list.
22229: */
22230: static void
22231: xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22232: {
22233: xmlSchemaPSVIIDCBindingPtr prev;
22234:
22235: while (bind != NULL) {
22236: prev = bind;
22237: bind = bind->next;
22238: xmlSchemaIDCFreeBinding(prev);
22239: }
22240: }
22241:
22242: /**
22243: * xmlSchemaIDCFreeMatcherList:
22244: * @matcher: the first IDC matcher in the list
22245: *
22246: * Frees a list of IDC matchers.
22247: */
22248: static void
22249: xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22250: {
22251: xmlSchemaIDCMatcherPtr next;
22252:
22253: while (matcher != NULL) {
22254: next = matcher->next;
22255: if (matcher->keySeqs != NULL) {
22256: int i;
22257: for (i = 0; i < matcher->sizeKeySeqs; i++)
22258: if (matcher->keySeqs[i] != NULL)
22259: xmlFree(matcher->keySeqs[i]);
22260: xmlFree(matcher->keySeqs);
22261: }
22262: if (matcher->targets != NULL) {
22263: if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22264: int i;
22265: xmlSchemaPSVIIDCNodePtr idcNode;
22266: /*
22267: * Node-table items for keyrefs are not stored globally
22268: * to the validation context, since they are not bubbled.
22269: * We need to free them here.
22270: */
22271: for (i = 0; i < matcher->targets->nbItems; i++) {
22272: idcNode =
22273: (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22274: xmlFree(idcNode->keys);
22275: xmlFree(idcNode);
22276: }
22277: }
22278: xmlSchemaItemListFree(matcher->targets);
22279: }
22280: xmlFree(matcher);
22281: matcher = next;
22282: }
22283: }
22284:
22285: /**
22286: * xmlSchemaIDCReleaseMatcherList:
22287: * @vctxt: the WXS validation context
22288: * @matcher: the first IDC matcher in the list
22289: *
22290: * Caches a list of IDC matchers for reuse.
22291: */
22292: static void
22293: xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22294: xmlSchemaIDCMatcherPtr matcher)
22295: {
22296: xmlSchemaIDCMatcherPtr next;
22297:
22298: while (matcher != NULL) {
22299: next = matcher->next;
22300: if (matcher->keySeqs != NULL) {
22301: int i;
22302: /*
22303: * Don't free the array, but only the content.
22304: */
22305: for (i = 0; i < matcher->sizeKeySeqs; i++)
22306: if (matcher->keySeqs[i] != NULL) {
22307: xmlFree(matcher->keySeqs[i]);
22308: matcher->keySeqs[i] = NULL;
22309: }
22310: }
22311: if (matcher->targets) {
22312: if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22313: int i;
22314: xmlSchemaPSVIIDCNodePtr idcNode;
22315: /*
22316: * Node-table items for keyrefs are not stored globally
22317: * to the validation context, since they are not bubbled.
22318: * We need to free them here.
22319: */
22320: for (i = 0; i < matcher->targets->nbItems; i++) {
22321: idcNode =
22322: (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22323: xmlFree(idcNode->keys);
22324: xmlFree(idcNode);
22325: }
22326: }
22327: xmlSchemaItemListFree(matcher->targets);
22328: matcher->targets = NULL;
22329: }
22330: matcher->next = NULL;
22331: /*
22332: * Cache the matcher.
22333: */
22334: if (vctxt->idcMatcherCache != NULL)
22335: matcher->nextCached = vctxt->idcMatcherCache;
22336: vctxt->idcMatcherCache = matcher;
22337:
22338: matcher = next;
22339: }
22340: }
22341:
22342: /**
22343: * xmlSchemaIDCAddStateObject:
22344: * @vctxt: the WXS validation context
22345: * @matcher: the IDC matcher
22346: * @sel: the XPath information
22347: * @parent: the parent "selector" state object if any
22348: * @type: "selector" or "field"
22349: *
22350: * Creates/reuses and activates state objects for the given
22351: * XPath information; if the XPath expression consists of unions,
22352: * multiple state objects are created for every unioned expression.
22353: *
22354: * Returns 0 on success and -1 on internal errors.
22355: */
22356: static int
22357: xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22358: xmlSchemaIDCMatcherPtr matcher,
22359: xmlSchemaIDCSelectPtr sel,
22360: int type)
22361: {
22362: xmlSchemaIDCStateObjPtr sto;
22363:
22364: /*
22365: * Reuse the state objects from the pool.
22366: */
22367: if (vctxt->xpathStatePool != NULL) {
22368: sto = vctxt->xpathStatePool;
22369: vctxt->xpathStatePool = sto->next;
22370: sto->next = NULL;
22371: } else {
22372: /*
22373: * Create a new state object.
22374: */
22375: sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22376: if (sto == NULL) {
22377: xmlSchemaVErrMemory(NULL,
22378: "allocating an IDC state object", NULL);
22379: return (-1);
22380: }
22381: memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22382: }
22383: /*
22384: * Add to global list.
22385: */
22386: if (vctxt->xpathStates != NULL)
22387: sto->next = vctxt->xpathStates;
22388: vctxt->xpathStates = sto;
22389:
22390: /*
22391: * Free the old xpath validation context.
22392: */
22393: if (sto->xpathCtxt != NULL)
22394: xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22395:
22396: /*
22397: * Create a new XPath (pattern) validation context.
22398: */
22399: sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22400: (xmlPatternPtr) sel->xpathComp);
22401: if (sto->xpathCtxt == NULL) {
22402: VERROR_INT("xmlSchemaIDCAddStateObject",
22403: "failed to create an XPath validation context");
22404: return (-1);
22405: }
22406: sto->type = type;
22407: sto->depth = vctxt->depth;
22408: sto->matcher = matcher;
22409: sto->sel = sel;
22410: sto->nbHistory = 0;
22411:
22412: #ifdef DEBUG_IDC
22413: xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22414: sto->sel->xpath);
22415: #endif
22416: return (0);
22417: }
22418:
22419: /**
22420: * xmlSchemaXPathEvaluate:
22421: * @vctxt: the WXS validation context
22422: * @nodeType: the nodeType of the current node
22423: *
22424: * Evaluates all active XPath state objects.
22425: *
22426: * Returns the number of IC "field" state objects which resolved to
22427: * this node, 0 if none resolved and -1 on internal errors.
22428: */
22429: static int
22430: xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22431: xmlElementType nodeType)
22432: {
22433: xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22434: int res, resolved = 0, depth = vctxt->depth;
22435:
22436: if (vctxt->xpathStates == NULL)
22437: return (0);
22438:
22439: if (nodeType == XML_ATTRIBUTE_NODE)
22440: depth++;
22441: #ifdef DEBUG_IDC
22442: {
22443: xmlChar *str = NULL;
22444: xmlGenericError(xmlGenericErrorContext,
22445: "IDC: EVAL on %s, depth %d, type %d\n",
22446: xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22447: vctxt->inode->localName), depth, nodeType);
22448: FREE_AND_NULL(str)
22449: }
22450: #endif
22451: /*
22452: * Process all active XPath state objects.
22453: */
22454: first = vctxt->xpathStates;
22455: sto = first;
22456: while (sto != head) {
22457: #ifdef DEBUG_IDC
22458: if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22459: xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22460: sto->matcher->aidc->def->name, sto->sel->xpath);
22461: else
22462: xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22463: sto->matcher->aidc->def->name, sto->sel->xpath);
22464: #endif
22465: if (nodeType == XML_ELEMENT_NODE)
22466: res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22467: vctxt->inode->localName, vctxt->inode->nsName);
22468: else
22469: res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22470: vctxt->inode->localName, vctxt->inode->nsName);
22471:
22472: if (res == -1) {
22473: VERROR_INT("xmlSchemaXPathEvaluate",
22474: "calling xmlStreamPush()");
22475: return (-1);
22476: }
22477: if (res == 0)
22478: goto next_sto;
22479: /*
22480: * Full match.
22481: */
22482: #ifdef DEBUG_IDC
22483: xmlGenericError(xmlGenericErrorContext, "IDC: "
22484: "MATCH\n");
22485: #endif
22486: /*
22487: * Register a match in the state object history.
22488: */
22489: if (sto->history == NULL) {
22490: sto->history = (int *) xmlMalloc(5 * sizeof(int));
22491: if (sto->history == NULL) {
22492: xmlSchemaVErrMemory(NULL,
22493: "allocating the state object history", NULL);
22494: return(-1);
22495: }
22496: sto->sizeHistory = 5;
22497: } else if (sto->sizeHistory <= sto->nbHistory) {
22498: sto->sizeHistory *= 2;
22499: sto->history = (int *) xmlRealloc(sto->history,
22500: sto->sizeHistory * sizeof(int));
22501: if (sto->history == NULL) {
22502: xmlSchemaVErrMemory(NULL,
22503: "re-allocating the state object history", NULL);
22504: return(-1);
22505: }
22506: }
22507: sto->history[sto->nbHistory++] = depth;
22508:
22509: #ifdef DEBUG_IDC
22510: xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22511: vctxt->depth);
22512: #endif
22513:
22514: if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22515: xmlSchemaIDCSelectPtr sel;
22516: /*
22517: * Activate state objects for the IDC fields of
22518: * the IDC selector.
22519: */
22520: #ifdef DEBUG_IDC
22521: xmlGenericError(xmlGenericErrorContext, "IDC: "
22522: "activating field states\n");
22523: #endif
22524: sel = sto->matcher->aidc->def->fields;
22525: while (sel != NULL) {
22526: if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22527: sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22528: return (-1);
22529: sel = sel->next;
22530: }
22531: } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22532: /*
22533: * An IDC key node was found by the IDC field.
22534: */
22535: #ifdef DEBUG_IDC
22536: xmlGenericError(xmlGenericErrorContext,
22537: "IDC: key found\n");
22538: #endif
22539: /*
22540: * Notify that the character value of this node is
22541: * needed.
22542: */
22543: if (resolved == 0) {
22544: if ((vctxt->inode->flags &
22545: XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22546: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22547: }
22548: resolved++;
22549: }
22550: next_sto:
22551: if (sto->next == NULL) {
22552: /*
22553: * Evaluate field state objects created on this node as well.
22554: */
22555: head = first;
22556: sto = vctxt->xpathStates;
22557: } else
22558: sto = sto->next;
22559: }
22560: return (resolved);
22561: }
22562:
22563: static const xmlChar *
22564: xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22565: xmlChar **buf,
22566: xmlSchemaPSVIIDCKeyPtr *seq,
22567: int count)
22568: {
22569: int i, res;
22570: xmlChar *value = NULL;
22571:
22572: *buf = xmlStrdup(BAD_CAST "[");
22573: for (i = 0; i < count; i++) {
22574: *buf = xmlStrcat(*buf, BAD_CAST "'");
22575: res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22576: xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22577: &value);
22578: if (res == 0)
22579: *buf = xmlStrcat(*buf, BAD_CAST value);
22580: else {
22581: VERROR_INT("xmlSchemaFormatIDCKeySequence",
22582: "failed to compute a canonical value");
22583: *buf = xmlStrcat(*buf, BAD_CAST "???");
22584: }
22585: if (i < count -1)
22586: *buf = xmlStrcat(*buf, BAD_CAST "', ");
22587: else
22588: *buf = xmlStrcat(*buf, BAD_CAST "'");
22589: if (value != NULL) {
22590: xmlFree(value);
22591: value = NULL;
22592: }
22593: }
22594: *buf = xmlStrcat(*buf, BAD_CAST "]");
22595:
22596: return (BAD_CAST *buf);
22597: }
22598:
22599: /**
22600: * xmlSchemaXPathPop:
22601: * @vctxt: the WXS validation context
22602: *
22603: * Pops all XPath states.
22604: *
22605: * Returns 0 on success and -1 on internal errors.
22606: */
22607: static int
22608: xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22609: {
22610: xmlSchemaIDCStateObjPtr sto;
22611: int res;
22612:
22613: if (vctxt->xpathStates == NULL)
22614: return(0);
22615: sto = vctxt->xpathStates;
22616: do {
22617: res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22618: if (res == -1)
22619: return (-1);
22620: sto = sto->next;
22621: } while (sto != NULL);
22622: return(0);
22623: }
22624:
22625: /**
22626: * xmlSchemaXPathProcessHistory:
22627: * @vctxt: the WXS validation context
22628: * @type: the simple/complex type of the current node if any at all
22629: * @val: the precompiled value
22630: *
22631: * Processes and pops the history items of the IDC state objects.
22632: * IDC key-sequences are validated/created on IDC bindings.
22633: *
22634: * Returns 0 on success and -1 on internal errors.
22635: */
22636: static int
22637: xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22638: int depth)
22639: {
22640: xmlSchemaIDCStateObjPtr sto, nextsto;
22641: int res, matchDepth;
22642: xmlSchemaPSVIIDCKeyPtr key = NULL;
22643: xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22644:
22645: if (vctxt->xpathStates == NULL)
22646: return (0);
22647: sto = vctxt->xpathStates;
22648:
22649: #ifdef DEBUG_IDC
22650: {
22651: xmlChar *str = NULL;
22652: xmlGenericError(xmlGenericErrorContext,
22653: "IDC: BACK on %s, depth %d\n",
22654: xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22655: vctxt->inode->localName), vctxt->depth);
22656: FREE_AND_NULL(str)
22657: }
22658: #endif
22659: /*
22660: * Evaluate the state objects.
22661: */
22662: while (sto != NULL) {
22663: res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22664: if (res == -1) {
22665: VERROR_INT("xmlSchemaXPathProcessHistory",
22666: "calling xmlStreamPop()");
22667: return (-1);
22668: }
22669: #ifdef DEBUG_IDC
22670: xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22671: sto->sel->xpath);
22672: #endif
22673: if (sto->nbHistory == 0)
22674: goto deregister_check;
22675:
22676: matchDepth = sto->history[sto->nbHistory -1];
22677:
22678: /*
22679: * Only matches at the current depth are of interest.
22680: */
22681: if (matchDepth != depth) {
22682: sto = sto->next;
22683: continue;
22684: }
22685: if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22686: /*
22687: * NOTE: According to
22688: * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22689: * ... the simple-content of complex types is also allowed.
22690: */
22691:
22692: if (WXS_IS_COMPLEX(type)) {
22693: if (WXS_HAS_SIMPLE_CONTENT(type)) {
22694: /*
22695: * Sanity check for complex types with simple content.
22696: */
22697: simpleType = type->contentTypeDef;
22698: if (simpleType == NULL) {
22699: VERROR_INT("xmlSchemaXPathProcessHistory",
22700: "field resolves to a CT with simple content "
22701: "but the CT is missing the ST definition");
22702: return (-1);
22703: }
22704: } else
22705: simpleType = NULL;
22706: } else
22707: simpleType = type;
22708: if (simpleType == NULL) {
22709: xmlChar *str = NULL;
22710:
22711: /*
22712: * Not qualified if the field resolves to a node of non
22713: * simple type.
22714: */
22715: xmlSchemaCustomErr(ACTXT_CAST vctxt,
22716: XML_SCHEMAV_CVC_IDC, NULL,
22717: WXS_BASIC_CAST sto->matcher->aidc->def,
22718: "The XPath '%s' of a field of %s does evaluate to a node of "
22719: "non-simple type",
22720: sto->sel->xpath,
22721: xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22722: FREE_AND_NULL(str);
22723: sto->nbHistory--;
22724: goto deregister_check;
22725: }
22726:
22727: if ((key == NULL) && (vctxt->inode->val == NULL)) {
22728: /*
22729: * Failed to provide the normalized value; maybe
22730: * the value was invalid.
22731: */
22732: VERROR(XML_SCHEMAV_CVC_IDC,
22733: WXS_BASIC_CAST sto->matcher->aidc->def,
22734: "Warning: No precomputed value available, the value "
22735: "was either invalid or something strange happend");
22736: sto->nbHistory--;
22737: goto deregister_check;
22738: } else {
22739: xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22740: xmlSchemaPSVIIDCKeyPtr *keySeq;
22741: int pos, idx;
22742:
22743: /*
22744: * The key will be anchored on the matcher's list of
22745: * key-sequences. The position in this list is determined
22746: * by the target node's depth relative to the matcher's
22747: * depth of creation (i.e. the depth of the scope element).
22748: *
22749: * Element Depth Pos List-entries
22750: * <scope> 0 NULL
22751: * <bar> 1 NULL
22752: * <target/> 2 2 target
22753: * <bar>
22754: * </scope>
22755: *
22756: * The size of the list is only dependant on the depth of
22757: * the tree.
22758: * An entry will be NULLed in selector_leave, i.e. when
22759: * we hit the target's
22760: */
22761: pos = sto->depth - matcher->depth;
22762: idx = sto->sel->index;
22763:
22764: /*
22765: * Create/grow the array of key-sequences.
22766: */
22767: if (matcher->keySeqs == NULL) {
22768: if (pos > 9)
22769: matcher->sizeKeySeqs = pos * 2;
22770: else
22771: matcher->sizeKeySeqs = 10;
22772: matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22773: xmlMalloc(matcher->sizeKeySeqs *
22774: sizeof(xmlSchemaPSVIIDCKeyPtr *));
22775: if (matcher->keySeqs == NULL) {
22776: xmlSchemaVErrMemory(NULL,
22777: "allocating an array of key-sequences",
22778: NULL);
22779: return(-1);
22780: }
22781: memset(matcher->keySeqs, 0,
22782: matcher->sizeKeySeqs *
22783: sizeof(xmlSchemaPSVIIDCKeyPtr *));
22784: } else if (pos >= matcher->sizeKeySeqs) {
22785: int i = matcher->sizeKeySeqs;
22786:
22787: matcher->sizeKeySeqs *= 2;
22788: matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22789: xmlRealloc(matcher->keySeqs,
22790: matcher->sizeKeySeqs *
22791: sizeof(xmlSchemaPSVIIDCKeyPtr *));
22792: if (matcher->keySeqs == NULL) {
22793: xmlSchemaVErrMemory(NULL,
22794: "reallocating an array of key-sequences",
22795: NULL);
22796: return (-1);
22797: }
22798: /*
22799: * The array needs to be NULLed.
22800: * TODO: Use memset?
22801: */
22802: for (; i < matcher->sizeKeySeqs; i++)
22803: matcher->keySeqs[i] = NULL;
22804: }
22805:
22806: /*
22807: * Get/create the key-sequence.
22808: */
22809: keySeq = matcher->keySeqs[pos];
22810: if (keySeq == NULL) {
22811: goto create_sequence;
22812: } else if (keySeq[idx] != NULL) {
22813: xmlChar *str = NULL;
22814: /*
22815: * cvc-identity-constraint:
22816: * 3 For each node in the �target node set� all
22817: * of the {fields}, with that node as the context
22818: * node, evaluate to either an empty node-set or
22819: * a node-set with exactly one member, which must
22820: * have a simple type.
22821: *
22822: * The key was already set; report an error.
22823: */
22824: xmlSchemaCustomErr(ACTXT_CAST vctxt,
22825: XML_SCHEMAV_CVC_IDC, NULL,
22826: WXS_BASIC_CAST matcher->aidc->def,
22827: "The XPath '%s' of a field of %s evaluates to a "
22828: "node-set with more than one member",
22829: sto->sel->xpath,
22830: xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22831: FREE_AND_NULL(str);
22832: sto->nbHistory--;
22833: goto deregister_check;
22834: } else
22835: goto create_key;
22836:
22837: create_sequence:
22838: /*
22839: * Create a key-sequence.
22840: */
22841: keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22842: matcher->aidc->def->nbFields *
22843: sizeof(xmlSchemaPSVIIDCKeyPtr));
22844: if (keySeq == NULL) {
22845: xmlSchemaVErrMemory(NULL,
22846: "allocating an IDC key-sequence", NULL);
22847: return(-1);
22848: }
22849: memset(keySeq, 0, matcher->aidc->def->nbFields *
22850: sizeof(xmlSchemaPSVIIDCKeyPtr));
22851: matcher->keySeqs[pos] = keySeq;
22852: create_key:
22853: /*
22854: * Create a key once per node only.
22855: */
22856: if (key == NULL) {
22857: key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22858: sizeof(xmlSchemaPSVIIDCKey));
22859: if (key == NULL) {
22860: xmlSchemaVErrMemory(NULL,
22861: "allocating a IDC key", NULL);
22862: xmlFree(keySeq);
22863: matcher->keySeqs[pos] = NULL;
22864: return(-1);
22865: }
22866: /*
22867: * Consume the compiled value.
22868: */
22869: key->type = simpleType;
22870: key->val = vctxt->inode->val;
22871: vctxt->inode->val = NULL;
22872: /*
22873: * Store the key in a global list.
22874: */
22875: if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22876: xmlSchemaIDCFreeKey(key);
22877: return (-1);
22878: }
22879: }
22880: keySeq[idx] = key;
22881: }
22882: } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22883:
22884: xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22885: /* xmlSchemaPSVIIDCBindingPtr bind; */
22886: xmlSchemaPSVIIDCNodePtr ntItem;
22887: xmlSchemaIDCMatcherPtr matcher;
22888: xmlSchemaIDCPtr idc;
22889: xmlSchemaItemListPtr targets;
22890: int pos, i, j, nbKeys;
22891: /*
22892: * Here we have the following scenario:
22893: * An IDC 'selector' state object resolved to a target node,
22894: * during the time this target node was in the
22895: * ancestor-or-self axis, the 'field' state object(s) looked
22896: * out for matching nodes to create a key-sequence for this
22897: * target node. Now we are back to this target node and need
22898: * to put the key-sequence, together with the target node
22899: * itself, into the node-table of the corresponding IDC
22900: * binding.
22901: */
22902: matcher = sto->matcher;
22903: idc = matcher->aidc->def;
22904: nbKeys = idc->nbFields;
22905: pos = depth - matcher->depth;
22906: /*
22907: * Check if the matcher has any key-sequences at all, plus
22908: * if it has a key-sequence for the current target node.
22909: */
22910: if ((matcher->keySeqs == NULL) ||
22911: (matcher->sizeKeySeqs <= pos)) {
22912: if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22913: goto selector_key_error;
22914: else
22915: goto selector_leave;
22916: }
22917:
22918: keySeq = &(matcher->keySeqs[pos]);
22919: if (*keySeq == NULL) {
22920: if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22921: goto selector_key_error;
22922: else
22923: goto selector_leave;
22924: }
22925:
22926: for (i = 0; i < nbKeys; i++) {
22927: if ((*keySeq)[i] == NULL) {
22928: /*
22929: * Not qualified, if not all fields did resolve.
22930: */
22931: if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22932: /*
22933: * All fields of a "key" IDC must resolve.
22934: */
22935: goto selector_key_error;
22936: }
22937: goto selector_leave;
22938: }
22939: }
22940: /*
22941: * All fields did resolve.
22942: */
22943:
22944: /*
22945: * 4.1 If the {identity-constraint category} is unique(/key),
22946: * then no two members of the �qualified node set� have
22947: * �key-sequences� whose members are pairwise equal, as
22948: * defined by Equal in [XML Schemas: Datatypes].
22949: *
22950: * Get the IDC binding from the matcher and check for
22951: * duplicate key-sequences.
22952: */
22953: #if 0
22954: bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22955: #endif
22956: targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22957: if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22958: (targets->nbItems != 0)) {
22959: xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22960:
22961: i = 0;
22962: res = 0;
22963: /*
22964: * Compare the key-sequences, key by key.
22965: */
22966: do {
22967: bkeySeq =
22968: ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22969: for (j = 0; j < nbKeys; j++) {
22970: ckey = (*keySeq)[j];
22971: bkey = bkeySeq[j];
22972: res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22973: if (res == -1) {
22974: return (-1);
22975: } else if (res == 0) {
22976: /*
22977: * One of the keys differs, so the key-sequence
22978: * won't be equal; get out.
22979: */
22980: break;
22981: }
22982: }
22983: if (res == 1) {
22984: /*
22985: * Duplicate key-sequence found.
22986: */
22987: break;
22988: }
22989: i++;
22990: } while (i < targets->nbItems);
22991: if (i != targets->nbItems) {
22992: xmlChar *str = NULL, *strB = NULL;
22993: /*
22994: * TODO: Try to report the key-sequence.
22995: */
22996: xmlSchemaCustomErr(ACTXT_CAST vctxt,
22997: XML_SCHEMAV_CVC_IDC, NULL,
22998: WXS_BASIC_CAST idc,
22999: "Duplicate key-sequence %s in %s",
23000: xmlSchemaFormatIDCKeySequence(vctxt, &str,
23001: (*keySeq), nbKeys),
23002: xmlSchemaGetIDCDesignation(&strB, idc));
23003: FREE_AND_NULL(str);
23004: FREE_AND_NULL(strB);
23005: goto selector_leave;
23006: }
23007: }
23008: /*
23009: * Add a node-table item to the IDC binding.
23010: */
23011: ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23012: sizeof(xmlSchemaPSVIIDCNode));
23013: if (ntItem == NULL) {
23014: xmlSchemaVErrMemory(NULL,
23015: "allocating an IDC node-table item", NULL);
23016: xmlFree(*keySeq);
23017: *keySeq = NULL;
23018: return(-1);
23019: }
23020: memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23021:
23022: /*
23023: * Store the node-table item in a global list.
23024: */
23025: if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23026: if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23027: xmlFree(ntItem);
23028: xmlFree(*keySeq);
23029: *keySeq = NULL;
23030: return (-1);
23031: }
23032: ntItem->nodeQNameID = -1;
23033: } else {
23034: /*
23035: * Save a cached QName for this node on the IDC node, to be
23036: * able to report it, even if the node is not saved.
23037: */
23038: ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23039: vctxt->inode->localName, vctxt->inode->nsName);
23040: if (ntItem->nodeQNameID == -1) {
23041: xmlFree(ntItem);
23042: xmlFree(*keySeq);
23043: *keySeq = NULL;
23044: return (-1);
23045: }
23046: }
23047: /*
23048: * Init the node-table item: Save the node, position and
23049: * consume the key-sequence.
23050: */
23051: ntItem->node = vctxt->node;
23052: ntItem->nodeLine = vctxt->inode->nodeLine;
23053: ntItem->keys = *keySeq;
23054: *keySeq = NULL;
23055: #if 0
23056: if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23057: #endif
23058: if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23059: if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23060: /*
23061: * Free the item, since keyref items won't be
23062: * put on a global list.
23063: */
23064: xmlFree(ntItem->keys);
23065: xmlFree(ntItem);
23066: }
23067: return (-1);
23068: }
23069:
23070: goto selector_leave;
23071: selector_key_error:
23072: {
23073: xmlChar *str = NULL;
23074: /*
23075: * 4.2.1 (KEY) The �target node set� and the
23076: * �qualified node set� are equal, that is, every
23077: * member of the �target node set� is also a member
23078: * of the �qualified node set� and vice versa.
23079: */
23080: xmlSchemaCustomErr(ACTXT_CAST vctxt,
23081: XML_SCHEMAV_CVC_IDC, NULL,
23082: WXS_BASIC_CAST idc,
23083: "Not all fields of %s evaluate to a node",
23084: xmlSchemaGetIDCDesignation(&str, idc), NULL);
23085: FREE_AND_NULL(str);
23086: }
23087: selector_leave:
23088: /*
23089: * Free the key-sequence if not added to the IDC table.
23090: */
23091: if ((keySeq != NULL) && (*keySeq != NULL)) {
23092: xmlFree(*keySeq);
23093: *keySeq = NULL;
23094: }
23095: } /* if selector */
23096:
23097: sto->nbHistory--;
23098:
23099: deregister_check:
23100: /*
23101: * Deregister state objects if they reach the depth of creation.
23102: */
23103: if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23104: #ifdef DEBUG_IDC
23105: xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
23106: sto->sel->xpath);
23107: #endif
23108: if (vctxt->xpathStates != sto) {
23109: VERROR_INT("xmlSchemaXPathProcessHistory",
23110: "The state object to be removed is not the first "
23111: "in the list");
23112: }
23113: nextsto = sto->next;
23114: /*
23115: * Unlink from the list of active XPath state objects.
23116: */
23117: vctxt->xpathStates = sto->next;
23118: sto->next = vctxt->xpathStatePool;
23119: /*
23120: * Link it to the pool of reusable state objects.
23121: */
23122: vctxt->xpathStatePool = sto;
23123: sto = nextsto;
23124: } else
23125: sto = sto->next;
23126: } /* while (sto != NULL) */
23127: return (0);
23128: }
23129:
23130: /**
23131: * xmlSchemaIDCRegisterMatchers:
23132: * @vctxt: the WXS validation context
23133: * @elemDecl: the element declaration
23134: *
23135: * Creates helper objects to evaluate IDC selectors/fields
23136: * successively.
23137: *
23138: * Returns 0 if OK and -1 on internal errors.
23139: */
23140: static int
23141: xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23142: xmlSchemaElementPtr elemDecl)
23143: {
23144: xmlSchemaIDCMatcherPtr matcher, last = NULL;
23145: xmlSchemaIDCPtr idc, refIdc;
23146: xmlSchemaIDCAugPtr aidc;
23147:
23148: idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23149: if (idc == NULL)
23150: return (0);
23151:
23152: #ifdef DEBUG_IDC
23153: {
23154: xmlChar *str = NULL;
23155: xmlGenericError(xmlGenericErrorContext,
23156: "IDC: REGISTER on %s, depth %d\n",
23157: (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23158: vctxt->inode->localName), vctxt->depth);
23159: FREE_AND_NULL(str)
23160: }
23161: #endif
23162: if (vctxt->inode->idcMatchers != NULL) {
23163: VERROR_INT("xmlSchemaIDCRegisterMatchers",
23164: "The chain of IDC matchers is expected to be empty");
23165: return (-1);
23166: }
23167: do {
23168: if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23169: /*
23170: * Since IDCs bubbles are expensive we need to know the
23171: * depth at which the bubbles should stop; this will be
23172: * the depth of the top-most keyref IDC. If no keyref
23173: * references a key/unique IDC, the keyrefDepth will
23174: * be -1, indicating that no bubbles are needed.
23175: */
23176: refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23177: if (refIdc != NULL) {
23178: /*
23179: * Remember that we have keyrefs on this node.
23180: */
23181: vctxt->inode->hasKeyrefs = 1;
23182: /*
23183: * Lookup the referenced augmented IDC info.
23184: */
23185: aidc = vctxt->aidcs;
23186: while (aidc != NULL) {
23187: if (aidc->def == refIdc)
23188: break;
23189: aidc = aidc->next;
23190: }
23191: if (aidc == NULL) {
23192: VERROR_INT("xmlSchemaIDCRegisterMatchers",
23193: "Could not find an augmented IDC item for an IDC "
23194: "definition");
23195: return (-1);
23196: }
23197: if ((aidc->keyrefDepth == -1) ||
23198: (vctxt->depth < aidc->keyrefDepth))
23199: aidc->keyrefDepth = vctxt->depth;
23200: }
23201: }
23202: /*
23203: * Lookup the augmented IDC item for the IDC definition.
23204: */
23205: aidc = vctxt->aidcs;
23206: while (aidc != NULL) {
23207: if (aidc->def == idc)
23208: break;
23209: aidc = aidc->next;
23210: }
23211: if (aidc == NULL) {
23212: VERROR_INT("xmlSchemaIDCRegisterMatchers",
23213: "Could not find an augmented IDC item for an IDC definition");
23214: return (-1);
23215: }
23216: /*
23217: * Create an IDC matcher for every IDC definition.
23218: */
23219: if (vctxt->idcMatcherCache != NULL) {
23220: /*
23221: * Reuse a cached matcher.
23222: */
23223: matcher = vctxt->idcMatcherCache;
23224: vctxt->idcMatcherCache = matcher->nextCached;
23225: matcher->nextCached = NULL;
23226: } else {
23227: matcher = (xmlSchemaIDCMatcherPtr)
23228: xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23229: if (matcher == NULL) {
23230: xmlSchemaVErrMemory(vctxt,
23231: "allocating an IDC matcher", NULL);
23232: return (-1);
23233: }
23234: memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23235: }
23236: if (last == NULL)
23237: vctxt->inode->idcMatchers = matcher;
23238: else
23239: last->next = matcher;
23240: last = matcher;
23241:
23242: matcher->type = IDC_MATCHER;
23243: matcher->depth = vctxt->depth;
23244: matcher->aidc = aidc;
23245: matcher->idcType = aidc->def->type;
23246: #ifdef DEBUG_IDC
23247: xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
23248: #endif
23249: /*
23250: * Init the automaton state object.
23251: */
23252: if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23253: idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23254: return (-1);
23255:
23256: idc = idc->next;
23257: } while (idc != NULL);
23258: return (0);
23259: }
23260:
23261: static int
23262: xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23263: xmlSchemaNodeInfoPtr ielem)
23264: {
23265: xmlSchemaPSVIIDCBindingPtr bind;
23266: int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23267: xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23268: xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23269:
23270: xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23271: /* vctxt->createIDCNodeTables */
23272: while (matcher != NULL) {
23273: /*
23274: * Skip keyref IDCs and empty IDC target-lists.
23275: */
23276: if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23277: WXS_ILIST_IS_EMPTY(matcher->targets))
23278: {
23279: matcher = matcher->next;
23280: continue;
23281: }
23282: /*
23283: * If we _want_ the IDC node-table to be created in any case
23284: * then do so. Otherwise create them only if keyrefs need them.
23285: */
23286: if ((! vctxt->createIDCNodeTables) &&
23287: ((matcher->aidc->keyrefDepth == -1) ||
23288: (matcher->aidc->keyrefDepth > vctxt->depth)))
23289: {
23290: matcher = matcher->next;
23291: continue;
23292: }
23293: /*
23294: * Get/create the IDC binding on this element for the IDC definition.
23295: */
23296: bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23297:
23298: if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23299: dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23300: nbDupls = bind->dupls->nbItems;
23301: } else {
23302: dupls = NULL;
23303: nbDupls = 0;
23304: }
23305: if (bind->nodeTable != NULL) {
23306: nbNodeTable = bind->nbNodes;
23307: } else {
23308: nbNodeTable = 0;
23309: }
23310:
23311: if ((nbNodeTable == 0) && (nbDupls == 0)) {
23312: /*
23313: * Transfer all IDC target-nodes to the IDC node-table.
23314: */
23315: bind->nodeTable =
23316: (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23317: bind->sizeNodes = matcher->targets->sizeItems;
23318: bind->nbNodes = matcher->targets->nbItems;
23319:
23320: matcher->targets->items = NULL;
23321: matcher->targets->sizeItems = 0;
23322: matcher->targets->nbItems = 0;
23323: } else {
23324: /*
23325: * Compare the key-sequences and add to the IDC node-table.
23326: */
23327: nbTargets = matcher->targets->nbItems;
23328: targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23329: nbFields = matcher->aidc->def->nbFields;
23330: i = 0;
23331: do {
23332: keys = targets[i]->keys;
23333: if (nbDupls) {
23334: /*
23335: * Search in already found duplicates first.
23336: */
23337: j = 0;
23338: do {
23339: if (nbFields == 1) {
23340: res = xmlSchemaAreValuesEqual(keys[0]->val,
23341: dupls[j]->keys[0]->val);
23342: if (res == -1)
23343: goto internal_error;
23344: if (res == 1) {
23345: /*
23346: * Equal key-sequence.
23347: */
23348: goto next_target;
23349: }
23350: } else {
23351: res = 0;
23352: ntkeys = dupls[j]->keys;
23353: for (k = 0; k < nbFields; k++) {
23354: res = xmlSchemaAreValuesEqual(keys[k]->val,
23355: ntkeys[k]->val);
23356: if (res == -1)
23357: goto internal_error;
23358: if (res == 0) {
23359: /*
23360: * One of the keys differs.
23361: */
23362: break;
23363: }
23364: }
23365: if (res == 1) {
23366: /*
23367: * Equal key-sequence found.
23368: */
23369: goto next_target;
23370: }
23371: }
23372: j++;
23373: } while (j < nbDupls);
23374: }
23375: if (nbNodeTable) {
23376: j = 0;
23377: do {
23378: if (nbFields == 1) {
23379: res = xmlSchemaAreValuesEqual(keys[0]->val,
23380: bind->nodeTable[j]->keys[0]->val);
23381: if (res == -1)
23382: goto internal_error;
23383: if (res == 0) {
23384: /*
23385: * The key-sequence differs.
23386: */
23387: goto next_node_table_entry;
23388: }
23389: } else {
23390: res = 0;
23391: ntkeys = bind->nodeTable[j]->keys;
23392: for (k = 0; k < nbFields; k++) {
23393: res = xmlSchemaAreValuesEqual(keys[k]->val,
23394: ntkeys[k]->val);
23395: if (res == -1)
23396: goto internal_error;
23397: if (res == 0) {
23398: /*
23399: * One of the keys differs.
23400: */
23401: goto next_node_table_entry;
23402: }
23403: }
23404: }
23405: /*
23406: * Add the duplicate to the list of duplicates.
23407: */
23408: if (bind->dupls == NULL) {
23409: bind->dupls = xmlSchemaItemListCreate();
23410: if (bind->dupls == NULL)
23411: goto internal_error;
23412: }
23413: if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23414: goto internal_error;
23415: /*
23416: * Remove the duplicate entry from the IDC node-table.
23417: */
23418: bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23419: bind->nbNodes--;
23420:
23421: goto next_target;
23422:
23423: next_node_table_entry:
23424: j++;
23425: } while (j < nbNodeTable);
23426: }
23427: /*
23428: * If everything is fine, then add the IDC target-node to
23429: * the IDC node-table.
23430: */
23431: if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23432: goto internal_error;
23433:
23434: next_target:
23435: i++;
23436: } while (i < nbTargets);
23437: }
23438: matcher = matcher->next;
23439: }
23440: return(0);
23441:
23442: internal_error:
23443: return(-1);
23444: }
23445:
23446: /**
23447: * xmlSchemaBubbleIDCNodeTables:
23448: * @depth: the current tree depth
23449: *
23450: * Merges IDC bindings of an element at @depth into the corresponding IDC
23451: * bindings of its parent element. If a duplicate note-table entry is found,
23452: * both, the parent node-table entry and child entry are discarded from the
23453: * node-table of the parent.
23454: *
23455: * Returns 0 if OK and -1 on internal errors.
23456: */
23457: static int
23458: xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23459: {
23460: xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23461: xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23462: xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23463: xmlSchemaIDCAugPtr aidc;
23464: int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23465:
23466: bind = vctxt->inode->idcTable;
23467: if (bind == NULL) {
23468: /* Fine, no table, no bubbles. */
23469: return (0);
23470: }
23471:
23472: parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23473: /*
23474: * Walk all bindings; create new or add to existing bindings.
23475: * Remove duplicate key-sequences.
23476: */
23477: while (bind != NULL) {
23478:
23479: if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23480: goto next_binding;
23481: /*
23482: * Check if the key/unique IDC table needs to be bubbled.
23483: */
23484: if (! vctxt->createIDCNodeTables) {
23485: aidc = vctxt->aidcs;
23486: do {
23487: if (aidc->def == bind->definition) {
23488: if ((aidc->keyrefDepth == -1) ||
23489: (aidc->keyrefDepth >= vctxt->depth)) {
23490: goto next_binding;
23491: }
23492: break;
23493: }
23494: aidc = aidc->next;
23495: } while (aidc != NULL);
23496: }
23497:
23498: if (parTable != NULL)
23499: parBind = *parTable;
23500: /*
23501: * Search a matching parent binding for the
23502: * IDC definition.
23503: */
23504: while (parBind != NULL) {
23505: if (parBind->definition == bind->definition)
23506: break;
23507: parBind = parBind->next;
23508: }
23509:
23510: if (parBind != NULL) {
23511: /*
23512: * Compare every node-table entry of the child node,
23513: * i.e. the key-sequence within, ...
23514: */
23515: oldNum = parBind->nbNodes; /* Skip newly added items. */
23516:
23517: if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23518: oldDupls = parBind->dupls->nbItems;
23519: dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23520: } else {
23521: dupls = NULL;
23522: oldDupls = 0;
23523: }
23524:
23525: parNodes = parBind->nodeTable;
23526: nbFields = bind->definition->nbFields;
23527:
23528: for (i = 0; i < bind->nbNodes; i++) {
23529: node = bind->nodeTable[i];
23530: if (node == NULL)
23531: continue;
23532: /*
23533: * ...with every key-sequence of the parent node, already
23534: * evaluated to be a duplicate key-sequence.
23535: */
23536: if (oldDupls) {
23537: j = 0;
23538: while (j < oldDupls) {
23539: if (nbFields == 1) {
23540: ret = xmlSchemaAreValuesEqual(
23541: node->keys[0]->val,
23542: dupls[j]->keys[0]->val);
23543: if (ret == -1)
23544: goto internal_error;
23545: if (ret == 0) {
23546: j++;
23547: continue;
23548: }
23549: } else {
23550: parNode = dupls[j];
23551: for (k = 0; k < nbFields; k++) {
23552: ret = xmlSchemaAreValuesEqual(
23553: node->keys[k]->val,
23554: parNode->keys[k]->val);
23555: if (ret == -1)
23556: goto internal_error;
23557: if (ret == 0)
23558: break;
23559: }
23560: }
23561: if (ret == 1)
23562: /* Duplicate found. */
23563: break;
23564: j++;
23565: }
23566: if (j != oldDupls) {
23567: /* Duplicate found. Skip this entry. */
23568: continue;
23569: }
23570: }
23571: /*
23572: * ... and with every key-sequence of the parent node.
23573: */
23574: if (oldNum) {
23575: j = 0;
23576: while (j < oldNum) {
23577: parNode = parNodes[j];
23578: if (nbFields == 1) {
23579: ret = xmlSchemaAreValuesEqual(
23580: node->keys[0]->val,
23581: parNode->keys[0]->val);
23582: if (ret == -1)
23583: goto internal_error;
23584: if (ret == 0) {
23585: j++;
23586: continue;
23587: }
23588: } else {
23589: for (k = 0; k < nbFields; k++) {
23590: ret = xmlSchemaAreValuesEqual(
23591: node->keys[k]->val,
23592: parNode->keys[k]->val);
23593: if (ret == -1)
23594: goto internal_error;
23595: if (ret == 0)
23596: break;
23597: }
23598: }
23599: if (ret == 1)
23600: /* Duplicate found. */
23601: break;
23602: j++;
23603: }
23604: if (j != oldNum) {
23605: /*
23606: * Handle duplicates. Move the duplicate in
23607: * the parent's node-table to the list of
23608: * duplicates.
23609: */
23610: oldNum--;
23611: parBind->nbNodes--;
23612: /*
23613: * Move last old item to pos of duplicate.
23614: */
23615: parNodes[j] = parNodes[oldNum];
23616:
23617: if (parBind->nbNodes != oldNum) {
23618: /*
23619: * If new items exist, move last new item to
23620: * last of old items.
23621: */
23622: parNodes[oldNum] =
23623: parNodes[parBind->nbNodes];
23624: }
23625: if (parBind->dupls == NULL) {
23626: parBind->dupls = xmlSchemaItemListCreate();
23627: if (parBind->dupls == NULL)
23628: goto internal_error;
23629: }
23630: xmlSchemaItemListAdd(parBind->dupls, parNode);
23631: } else {
23632: /*
23633: * Add the node-table entry (node and key-sequence) of
23634: * the child node to the node table of the parent node.
23635: */
23636: if (parBind->nodeTable == NULL) {
23637: parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23638: xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23639: if (parBind->nodeTable == NULL) {
23640: xmlSchemaVErrMemory(NULL,
23641: "allocating IDC list of node-table items", NULL);
23642: goto internal_error;
23643: }
23644: parBind->sizeNodes = 1;
23645: } else if (parBind->nbNodes >= parBind->sizeNodes) {
23646: parBind->sizeNodes *= 2;
23647: parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23648: xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23649: sizeof(xmlSchemaPSVIIDCNodePtr));
23650: if (parBind->nodeTable == NULL) {
23651: xmlSchemaVErrMemory(NULL,
23652: "re-allocating IDC list of node-table items", NULL);
23653: goto internal_error;
23654: }
23655: }
23656: parNodes = parBind->nodeTable;
23657: /*
23658: * Append the new node-table entry to the 'new node-table
23659: * entries' section.
23660: */
23661: parNodes[parBind->nbNodes++] = node;
23662: }
23663:
23664: }
23665:
23666: }
23667: } else {
23668: /*
23669: * No binding for the IDC was found: create a new one and
23670: * copy all node-tables.
23671: */
23672: parBind = xmlSchemaIDCNewBinding(bind->definition);
23673: if (parBind == NULL)
23674: goto internal_error;
23675:
23676: /*
23677: * TODO: Hmm, how to optimize the initial number of
23678: * allocated entries?
23679: */
23680: if (bind->nbNodes != 0) {
23681: /*
23682: * Add all IDC node-table entries.
23683: */
23684: if (! vctxt->psviExposeIDCNodeTables) {
23685: /*
23686: * Just move the entries.
23687: * NOTE: this is quite save here, since
23688: * all the keyref lookups have already been
23689: * performed.
23690: */
23691: parBind->nodeTable = bind->nodeTable;
23692: bind->nodeTable = NULL;
23693: parBind->sizeNodes = bind->sizeNodes;
23694: bind->sizeNodes = 0;
23695: parBind->nbNodes = bind->nbNodes;
23696: bind->nbNodes = 0;
23697: } else {
23698: /*
23699: * Copy the entries.
23700: */
23701: parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23702: xmlMalloc(bind->nbNodes *
23703: sizeof(xmlSchemaPSVIIDCNodePtr));
23704: if (parBind->nodeTable == NULL) {
23705: xmlSchemaVErrMemory(NULL,
23706: "allocating an array of IDC node-table "
23707: "items", NULL);
23708: xmlSchemaIDCFreeBinding(parBind);
23709: goto internal_error;
23710: }
23711: parBind->sizeNodes = bind->nbNodes;
23712: parBind->nbNodes = bind->nbNodes;
23713: memcpy(parBind->nodeTable, bind->nodeTable,
23714: bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23715: }
23716: }
23717: if (bind->dupls) {
23718: /*
23719: * Move the duplicates.
23720: */
23721: if (parBind->dupls != NULL)
23722: xmlSchemaItemListFree(parBind->dupls);
23723: parBind->dupls = bind->dupls;
23724: bind->dupls = NULL;
23725: }
23726: if (parTable != NULL) {
23727: if (*parTable == NULL)
23728: *parTable = parBind;
23729: else {
23730: parBind->next = *parTable;
23731: *parTable = parBind;
23732: }
23733: }
23734: }
23735:
23736: next_binding:
23737: bind = bind->next;
23738: }
23739: return (0);
23740:
23741: internal_error:
23742: return(-1);
23743: }
23744:
23745: /**
23746: * xmlSchemaCheckCVCIDCKeyRef:
23747: * @vctxt: the WXS validation context
23748: * @elemDecl: the element declaration
23749: *
23750: * Check the cvc-idc-keyref constraints.
23751: */
23752: static int
23753: xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23754: {
23755: xmlSchemaIDCMatcherPtr matcher;
23756: xmlSchemaPSVIIDCBindingPtr bind;
23757:
23758: matcher = vctxt->inode->idcMatchers;
23759: /*
23760: * Find a keyref.
23761: */
23762: while (matcher != NULL) {
23763: if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23764: matcher->targets &&
23765: matcher->targets->nbItems)
23766: {
23767: int i, j, k, res, nbFields, hasDupls;
23768: xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23769: xmlSchemaPSVIIDCNodePtr refNode = NULL;
23770:
23771: nbFields = matcher->aidc->def->nbFields;
23772:
23773: /*
23774: * Find the IDC node-table for the referenced IDC key/unique.
23775: */
23776: bind = vctxt->inode->idcTable;
23777: while (bind != NULL) {
23778: if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23779: bind->definition)
23780: break;
23781: bind = bind->next;
23782: }
23783: hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23784: /*
23785: * Search for a matching key-sequences.
23786: */
23787: for (i = 0; i < matcher->targets->nbItems; i++) {
23788: res = 0;
23789: refNode = matcher->targets->items[i];
23790: if (bind != NULL) {
23791: refKeys = refNode->keys;
23792: for (j = 0; j < bind->nbNodes; j++) {
23793: keys = bind->nodeTable[j]->keys;
23794: for (k = 0; k < nbFields; k++) {
23795: res = xmlSchemaAreValuesEqual(keys[k]->val,
23796: refKeys[k]->val);
23797: if (res == 0)
23798: break;
23799: else if (res == -1) {
23800: return (-1);
23801: }
23802: }
23803: if (res == 1) {
23804: /*
23805: * Match found.
23806: */
23807: break;
23808: }
23809: }
23810: if ((res == 0) && hasDupls) {
23811: /*
23812: * Search in duplicates
23813: */
23814: for (j = 0; j < bind->dupls->nbItems; j++) {
23815: keys = ((xmlSchemaPSVIIDCNodePtr)
23816: bind->dupls->items[j])->keys;
23817: for (k = 0; k < nbFields; k++) {
23818: res = xmlSchemaAreValuesEqual(keys[k]->val,
23819: refKeys[k]->val);
23820: if (res == 0)
23821: break;
23822: else if (res == -1) {
23823: return (-1);
23824: }
23825: }
23826: if (res == 1) {
23827: /*
23828: * Match in duplicates found.
23829: */
23830: xmlChar *str = NULL, *strB = NULL;
23831: xmlSchemaKeyrefErr(vctxt,
23832: XML_SCHEMAV_CVC_IDC, refNode,
23833: (xmlSchemaTypePtr) matcher->aidc->def,
23834: "More than one match found for "
23835: "key-sequence %s of keyref '%s'",
23836: xmlSchemaFormatIDCKeySequence(vctxt, &str,
23837: refNode->keys, nbFields),
23838: xmlSchemaGetComponentQName(&strB,
23839: matcher->aidc->def));
23840: FREE_AND_NULL(str);
23841: FREE_AND_NULL(strB);
23842: break;
23843: }
23844: }
23845: }
23846: }
23847:
23848: if (res == 0) {
23849: xmlChar *str = NULL, *strB = NULL;
23850: xmlSchemaKeyrefErr(vctxt,
23851: XML_SCHEMAV_CVC_IDC, refNode,
23852: (xmlSchemaTypePtr) matcher->aidc->def,
23853: "No match found for key-sequence %s of keyref '%s'",
23854: xmlSchemaFormatIDCKeySequence(vctxt, &str,
23855: refNode->keys, nbFields),
23856: xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23857: FREE_AND_NULL(str);
23858: FREE_AND_NULL(strB);
23859: }
23860: }
23861: }
23862: matcher = matcher->next;
23863: }
23864: /* TODO: Return an error if any error encountered. */
23865: return (0);
23866: }
23867:
23868: /************************************************************************
23869: * *
23870: * XML Reader validation code *
23871: * *
23872: ************************************************************************/
23873:
23874: static xmlSchemaAttrInfoPtr
23875: xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23876: {
23877: xmlSchemaAttrInfoPtr iattr;
23878: /*
23879: * Grow/create list of attribute infos.
23880: */
23881: if (vctxt->attrInfos == NULL) {
23882: vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23883: xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23884: vctxt->sizeAttrInfos = 1;
23885: if (vctxt->attrInfos == NULL) {
23886: xmlSchemaVErrMemory(vctxt,
23887: "allocating attribute info list", NULL);
23888: return (NULL);
23889: }
23890: } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23891: vctxt->sizeAttrInfos++;
23892: vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23893: xmlRealloc(vctxt->attrInfos,
23894: vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23895: if (vctxt->attrInfos == NULL) {
23896: xmlSchemaVErrMemory(vctxt,
23897: "re-allocating attribute info list", NULL);
23898: return (NULL);
23899: }
23900: } else {
23901: iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23902: if (iattr->localName != NULL) {
23903: VERROR_INT("xmlSchemaGetFreshAttrInfo",
23904: "attr info not cleared");
23905: return (NULL);
23906: }
23907: iattr->nodeType = XML_ATTRIBUTE_NODE;
23908: return (iattr);
23909: }
23910: /*
23911: * Create an attribute info.
23912: */
23913: iattr = (xmlSchemaAttrInfoPtr)
23914: xmlMalloc(sizeof(xmlSchemaAttrInfo));
23915: if (iattr == NULL) {
23916: xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23917: return (NULL);
23918: }
23919: memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23920: iattr->nodeType = XML_ATTRIBUTE_NODE;
23921: vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23922:
23923: return (iattr);
23924: }
23925:
23926: static int
23927: xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23928: xmlNodePtr attrNode,
23929: int nodeLine,
23930: const xmlChar *localName,
23931: const xmlChar *nsName,
23932: int ownedNames,
23933: xmlChar *value,
23934: int ownedValue)
23935: {
23936: xmlSchemaAttrInfoPtr attr;
23937:
23938: attr = xmlSchemaGetFreshAttrInfo(vctxt);
23939: if (attr == NULL) {
23940: VERROR_INT("xmlSchemaPushAttribute",
23941: "calling xmlSchemaGetFreshAttrInfo()");
23942: return (-1);
23943: }
23944: attr->node = attrNode;
23945: attr->nodeLine = nodeLine;
23946: attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23947: attr->localName = localName;
23948: attr->nsName = nsName;
23949: if (ownedNames)
23950: attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23951: /*
23952: * Evaluate if it's an XSI attribute.
23953: */
23954: if (nsName != NULL) {
23955: if (xmlStrEqual(localName, BAD_CAST "nil")) {
23956: if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23957: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23958: }
23959: } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23960: if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23961: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23962: }
23963: } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23964: if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23965: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23966: }
23967: } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23968: if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23969: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23970: }
23971: } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23972: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23973: }
23974: }
23975: attr->value = value;
23976: if (ownedValue)
23977: attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23978: if (attr->metaType != 0)
23979: attr->state = XML_SCHEMAS_ATTR_META;
23980: return (0);
23981: }
23982:
23983: /**
23984: * xmlSchemaClearElemInfo:
23985: * @vctxt: the WXS validation context
23986: * @ielem: the element information item
23987: */
23988: static void
23989: xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23990: xmlSchemaNodeInfoPtr ielem)
23991: {
23992: ielem->hasKeyrefs = 0;
23993: ielem->appliedXPath = 0;
23994: if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23995: FREE_AND_NULL(ielem->localName);
23996: FREE_AND_NULL(ielem->nsName);
23997: } else {
23998: ielem->localName = NULL;
23999: ielem->nsName = NULL;
24000: }
24001: if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24002: FREE_AND_NULL(ielem->value);
24003: } else {
24004: ielem->value = NULL;
24005: }
24006: if (ielem->val != NULL) {
24007: /*
24008: * PSVI TODO: Be careful not to free it when the value is
24009: * exposed via PSVI.
24010: */
24011: xmlSchemaFreeValue(ielem->val);
24012: ielem->val = NULL;
24013: }
24014: if (ielem->idcMatchers != NULL) {
24015: /*
24016: * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24017: * Does it work?
24018: */
24019: xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24020: #if 0
24021: xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24022: #endif
24023: ielem->idcMatchers = NULL;
24024: }
24025: if (ielem->idcTable != NULL) {
24026: /*
24027: * OPTIMIZE TODO: Use a pool of IDC tables??.
24028: */
24029: xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24030: ielem->idcTable = NULL;
24031: }
24032: if (ielem->regexCtxt != NULL) {
24033: xmlRegFreeExecCtxt(ielem->regexCtxt);
24034: ielem->regexCtxt = NULL;
24035: }
24036: if (ielem->nsBindings != NULL) {
24037: xmlFree((xmlChar **)ielem->nsBindings);
24038: ielem->nsBindings = NULL;
24039: ielem->nbNsBindings = 0;
24040: ielem->sizeNsBindings = 0;
24041: }
24042: }
24043:
24044: /**
24045: * xmlSchemaGetFreshElemInfo:
24046: * @vctxt: the schema validation context
24047: *
24048: * Creates/reuses and initializes the element info item for
24049: * the currect tree depth.
24050: *
24051: * Returns the element info item or NULL on API or internal errors.
24052: */
24053: static xmlSchemaNodeInfoPtr
24054: xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24055: {
24056: xmlSchemaNodeInfoPtr info = NULL;
24057:
24058: if (vctxt->depth > vctxt->sizeElemInfos) {
24059: VERROR_INT("xmlSchemaGetFreshElemInfo",
24060: "inconsistent depth encountered");
24061: return (NULL);
24062: }
24063: if (vctxt->elemInfos == NULL) {
24064: vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24065: xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24066: if (vctxt->elemInfos == NULL) {
24067: xmlSchemaVErrMemory(vctxt,
24068: "allocating the element info array", NULL);
24069: return (NULL);
24070: }
24071: memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24072: vctxt->sizeElemInfos = 10;
24073: } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24074: int i = vctxt->sizeElemInfos;
24075:
24076: vctxt->sizeElemInfos *= 2;
24077: vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24078: xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24079: sizeof(xmlSchemaNodeInfoPtr));
24080: if (vctxt->elemInfos == NULL) {
24081: xmlSchemaVErrMemory(vctxt,
24082: "re-allocating the element info array", NULL);
24083: return (NULL);
24084: }
24085: /*
24086: * We need the new memory to be NULLed.
24087: * TODO: Use memset instead?
24088: */
24089: for (; i < vctxt->sizeElemInfos; i++)
24090: vctxt->elemInfos[i] = NULL;
24091: } else
24092: info = vctxt->elemInfos[vctxt->depth];
24093:
24094: if (info == NULL) {
24095: info = (xmlSchemaNodeInfoPtr)
24096: xmlMalloc(sizeof(xmlSchemaNodeInfo));
24097: if (info == NULL) {
24098: xmlSchemaVErrMemory(vctxt,
24099: "allocating an element info", NULL);
24100: return (NULL);
24101: }
24102: vctxt->elemInfos[vctxt->depth] = info;
24103: } else {
24104: if (info->localName != NULL) {
24105: VERROR_INT("xmlSchemaGetFreshElemInfo",
24106: "elem info has not been cleared");
24107: return (NULL);
24108: }
24109: }
24110: memset(info, 0, sizeof(xmlSchemaNodeInfo));
24111: info->nodeType = XML_ELEMENT_NODE;
24112: info->depth = vctxt->depth;
24113:
24114: return (info);
24115: }
24116:
24117: #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24118: #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24119: #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24120:
24121: static int
24122: xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24123: xmlNodePtr node,
24124: xmlSchemaTypePtr type,
24125: xmlSchemaValType valType,
24126: const xmlChar * value,
24127: xmlSchemaValPtr val,
24128: unsigned long length,
24129: int fireErrors)
24130: {
24131: int ret, error = 0;
24132:
24133: xmlSchemaTypePtr tmpType;
24134: xmlSchemaFacetLinkPtr facetLink;
24135: xmlSchemaFacetPtr facet;
24136: unsigned long len = 0;
24137: xmlSchemaWhitespaceValueType ws;
24138:
24139: /*
24140: * In Libxml2, derived built-in types have currently no explicit facets.
24141: */
24142: if (type->type == XML_SCHEMA_TYPE_BASIC)
24143: return (0);
24144:
24145: /*
24146: * NOTE: Do not jump away, if the facetSet of the given type is
24147: * empty: until now, "pattern" and "enumeration" facets of the
24148: * *base types* need to be checked as well.
24149: */
24150: if (type->facetSet == NULL)
24151: goto pattern_and_enum;
24152:
24153: if (! WXS_IS_ATOMIC(type)) {
24154: if (WXS_IS_LIST(type))
24155: goto WXS_IS_LIST;
24156: else
24157: goto pattern_and_enum;
24158: }
24159: /*
24160: * Whitespace handling is only of importance for string-based
24161: * types.
24162: */
24163: tmpType = xmlSchemaGetPrimitiveType(type);
24164: if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24165: WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24166: ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24167: } else
24168: ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24169: /*
24170: * If the value was not computed (for string or
24171: * anySimpleType based types), then use the provided
24172: * type.
24173: */
24174: if (val == NULL)
24175: valType = valType;
24176: else
24177: valType = xmlSchemaGetValType(val);
24178:
24179: ret = 0;
24180: for (facetLink = type->facetSet; facetLink != NULL;
24181: facetLink = facetLink->next) {
24182: /*
24183: * Skip the pattern "whiteSpace": it is used to
24184: * format the character content beforehand.
24185: */
24186: switch (facetLink->facet->type) {
24187: case XML_SCHEMA_FACET_WHITESPACE:
24188: case XML_SCHEMA_FACET_PATTERN:
24189: case XML_SCHEMA_FACET_ENUMERATION:
24190: continue;
24191: case XML_SCHEMA_FACET_LENGTH:
24192: case XML_SCHEMA_FACET_MINLENGTH:
24193: case XML_SCHEMA_FACET_MAXLENGTH:
24194: ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24195: valType, value, val, &len, ws);
24196: break;
24197: default:
24198: ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24199: valType, value, val, ws);
24200: break;
24201: }
24202: if (ret < 0) {
24203: AERROR_INT("xmlSchemaValidateFacets",
24204: "validating against a atomic type facet");
24205: return (-1);
24206: } else if (ret > 0) {
24207: if (fireErrors)
24208: xmlSchemaFacetErr(actxt, ret, node,
24209: value, len, type, facetLink->facet, NULL, NULL, NULL);
24210: else
24211: return (ret);
24212: if (error == 0)
24213: error = ret;
24214: }
24215: ret = 0;
24216: }
24217:
24218: WXS_IS_LIST:
24219: if (! WXS_IS_LIST(type))
24220: goto pattern_and_enum;
24221: /*
24222: * "length", "minLength" and "maxLength" of list types.
24223: */
24224: ret = 0;
24225: for (facetLink = type->facetSet; facetLink != NULL;
24226: facetLink = facetLink->next) {
24227:
24228: switch (facetLink->facet->type) {
24229: case XML_SCHEMA_FACET_LENGTH:
24230: case XML_SCHEMA_FACET_MINLENGTH:
24231: case XML_SCHEMA_FACET_MAXLENGTH:
24232: ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24233: value, length, NULL);
24234: break;
24235: default:
24236: continue;
24237: }
24238: if (ret < 0) {
24239: AERROR_INT("xmlSchemaValidateFacets",
24240: "validating against a list type facet");
24241: return (-1);
24242: } else if (ret > 0) {
24243: if (fireErrors)
24244: xmlSchemaFacetErr(actxt, ret, node,
24245: value, length, type, facetLink->facet, NULL, NULL, NULL);
24246: else
24247: return (ret);
24248: if (error == 0)
24249: error = ret;
24250: }
24251: ret = 0;
24252: }
24253:
24254: pattern_and_enum:
24255: if (error >= 0) {
24256: int found = 0;
24257: /*
24258: * Process enumerations. Facet values are in the value space
24259: * of the defining type's base type. This seems to be a bug in the
24260: * XML Schema 1.0 spec. Use the whitespace type of the base type.
24261: * Only the first set of enumerations in the ancestor-or-self axis
24262: * is used for validation.
24263: */
24264: ret = 0;
24265: tmpType = type;
24266: do {
24267: for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24268: if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24269: continue;
24270: found = 1;
24271: ret = xmlSchemaAreValuesEqual(facet->val, val);
24272: if (ret == 1)
24273: break;
24274: else if (ret < 0) {
24275: AERROR_INT("xmlSchemaValidateFacets",
24276: "validating against an enumeration facet");
24277: return (-1);
24278: }
24279: }
24280: if (ret != 0)
24281: break;
24282: /*
24283: * Break on the first set of enumerations. Any additional
24284: * enumerations which might be existent on the ancestors
24285: * of the current type are restricted by this set; thus
24286: * *must* *not* be taken into account.
24287: */
24288: if (found)
24289: break;
24290: tmpType = tmpType->baseType;
24291: } while ((tmpType != NULL) &&
24292: (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24293: if (found && (ret == 0)) {
24294: ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24295: if (fireErrors) {
24296: xmlSchemaFacetErr(actxt, ret, node,
24297: value, 0, type, NULL, NULL, NULL, NULL);
24298: } else
24299: return (ret);
24300: if (error == 0)
24301: error = ret;
24302: }
24303: }
24304:
24305: if (error >= 0) {
24306: int found;
24307: /*
24308: * Process patters. Pattern facets are ORed at type level
24309: * and ANDed if derived. Walk the base type axis.
24310: */
24311: tmpType = type;
24312: facet = NULL;
24313: do {
24314: found = 0;
24315: for (facetLink = tmpType->facetSet; facetLink != NULL;
24316: facetLink = facetLink->next) {
24317: if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24318: continue;
24319: found = 1;
24320: /*
24321: * NOTE that for patterns, @value needs to be the
24322: * normalized vaule.
24323: */
24324: ret = xmlRegexpExec(facetLink->facet->regexp, value);
24325: if (ret == 1)
24326: break;
24327: else if (ret < 0) {
24328: AERROR_INT("xmlSchemaValidateFacets",
24329: "validating against a pattern facet");
24330: return (-1);
24331: } else {
24332: /*
24333: * Save the last non-validating facet.
24334: */
24335: facet = facetLink->facet;
24336: }
24337: }
24338: if (found && (ret != 1)) {
24339: ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24340: if (fireErrors) {
24341: xmlSchemaFacetErr(actxt, ret, node,
24342: value, 0, type, facet, NULL, NULL, NULL);
24343: } else
24344: return (ret);
24345: if (error == 0)
24346: error = ret;
24347: break;
24348: }
24349: tmpType = tmpType->baseType;
24350: } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24351: }
24352:
24353: return (error);
24354: }
24355:
24356: static xmlChar *
24357: xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24358: const xmlChar *value)
24359: {
24360: switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24361: case XML_SCHEMA_WHITESPACE_COLLAPSE:
24362: return (xmlSchemaCollapseString(value));
24363: case XML_SCHEMA_WHITESPACE_REPLACE:
24364: return (xmlSchemaWhiteSpaceReplace(value));
24365: default:
24366: return (NULL);
24367: }
24368: }
24369:
24370: static int
24371: xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24372: const xmlChar *value,
24373: xmlSchemaValPtr *val,
24374: int valNeeded)
24375: {
24376: int ret;
24377: const xmlChar *nsName;
24378: xmlChar *local, *prefix = NULL;
24379:
24380: ret = xmlValidateQName(value, 1);
24381: if (ret != 0) {
24382: if (ret == -1) {
24383: VERROR_INT("xmlSchemaValidateQName",
24384: "calling xmlValidateQName()");
24385: return (-1);
24386: }
24387: return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24388: }
24389: /*
24390: * NOTE: xmlSplitQName2 will always return a duplicated
24391: * strings.
24392: */
24393: local = xmlSplitQName2(value, &prefix);
24394: if (local == NULL)
24395: local = xmlStrdup(value);
24396: /*
24397: * OPTIMIZE TODO: Use flags for:
24398: * - is there any namespace binding?
24399: * - is there a default namespace?
24400: */
24401: nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24402:
24403: if (prefix != NULL) {
24404: xmlFree(prefix);
24405: /*
24406: * A namespace must be found if the prefix is
24407: * NOT NULL.
24408: */
24409: if (nsName == NULL) {
24410: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24411: xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24412: WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24413: "The QName value '%s' has no "
24414: "corresponding namespace declaration in "
24415: "scope", value, NULL);
24416: if (local != NULL)
24417: xmlFree(local);
24418: return (ret);
24419: }
24420: }
24421: if (valNeeded && val) {
24422: if (nsName != NULL)
24423: *val = xmlSchemaNewQNameValue(
24424: BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24425: else
24426: *val = xmlSchemaNewQNameValue(NULL,
24427: BAD_CAST local);
24428: } else
24429: xmlFree(local);
24430: return (0);
24431: }
24432:
24433: /*
24434: * cvc-simple-type
24435: */
24436: static int
24437: xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24438: xmlNodePtr node,
24439: xmlSchemaTypePtr type,
24440: const xmlChar *value,
24441: xmlSchemaValPtr *retVal,
24442: int fireErrors,
24443: int normalize,
24444: int isNormalized)
24445: {
24446: int ret = 0, valNeeded = (retVal) ? 1 : 0;
24447: xmlSchemaValPtr val = NULL;
24448: /* xmlSchemaWhitespaceValueType ws; */
24449: xmlChar *normValue = NULL;
24450:
24451: #define NORMALIZE(atype) \
24452: if ((! isNormalized) && \
24453: (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24454: normValue = xmlSchemaNormalizeValue(atype, value); \
24455: if (normValue != NULL) \
24456: value = normValue; \
24457: isNormalized = 1; \
24458: }
24459:
24460: if ((retVal != NULL) && (*retVal != NULL)) {
24461: xmlSchemaFreeValue(*retVal);
24462: *retVal = NULL;
24463: }
24464: /*
24465: * 3.14.4 Simple Type Definition Validation Rules
24466: * Validation Rule: String Valid
24467: */
24468: /*
24469: * 1 It is schema-valid with respect to that definition as defined
24470: * by Datatype Valid in [XML Schemas: Datatypes].
24471: */
24472: /*
24473: * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24474: * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24475: * the string must be a �declared entity name�.
24476: */
24477: /*
24478: * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24479: * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24480: * then every whitespace-delimited substring of the string must be a �declared
24481: * entity name�.
24482: */
24483: /*
24484: * 2.3 otherwise no further condition applies.
24485: */
24486: if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24487: valNeeded = 1;
24488: if (value == NULL)
24489: value = BAD_CAST "";
24490: if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24491: xmlSchemaTypePtr biType; /* The built-in type. */
24492: /*
24493: * SPEC (1.2.1) "if {variety} is �atomic� then the string must �match�
24494: * a literal in the �lexical space� of {base type definition}"
24495: */
24496: /*
24497: * Whitespace-normalize.
24498: */
24499: NORMALIZE(type);
24500: if (type->type != XML_SCHEMA_TYPE_BASIC) {
24501: /*
24502: * Get the built-in type.
24503: */
24504: biType = type->baseType;
24505: while ((biType != NULL) &&
24506: (biType->type != XML_SCHEMA_TYPE_BASIC))
24507: biType = biType->baseType;
24508:
24509: if (biType == NULL) {
24510: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24511: "could not get the built-in type");
24512: goto internal_error;
24513: }
24514: } else
24515: biType = type;
24516: /*
24517: * NOTATIONs need to be processed here, since they need
24518: * to lookup in the hashtable of NOTATION declarations of the schema.
24519: */
24520: if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24521: switch (biType->builtInType) {
24522: case XML_SCHEMAS_NOTATION:
24523: ret = xmlSchemaValidateNotation(
24524: (xmlSchemaValidCtxtPtr) actxt,
24525: ((xmlSchemaValidCtxtPtr) actxt)->schema,
24526: NULL, value, &val, valNeeded);
24527: break;
24528: case XML_SCHEMAS_QNAME:
24529: ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24530: value, &val, valNeeded);
24531: break;
24532: default:
24533: /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24534: if (valNeeded)
24535: ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24536: value, &val, node);
24537: else
24538: ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24539: value, NULL, node);
24540: break;
24541: }
24542: } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24543: switch (biType->builtInType) {
24544: case XML_SCHEMAS_NOTATION:
24545: ret = xmlSchemaValidateNotation(NULL,
24546: ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24547: value, &val, valNeeded);
24548: break;
24549: default:
24550: /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24551: if (valNeeded)
24552: ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24553: value, &val, node);
24554: else
24555: ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24556: value, NULL, node);
24557: break;
24558: }
24559: } else {
24560: /*
24561: * Validation via a public API is not implemented yet.
24562: */
24563: TODO
24564: goto internal_error;
24565: }
24566: if (ret != 0) {
24567: if (ret < 0) {
24568: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24569: "validating against a built-in type");
24570: goto internal_error;
24571: }
24572: if (WXS_IS_LIST(type))
24573: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24574: else
24575: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24576: }
24577: if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24578: /*
24579: * Check facets.
24580: */
24581: ret = xmlSchemaValidateFacets(actxt, node, type,
24582: (xmlSchemaValType) biType->builtInType, value, val,
24583: 0, fireErrors);
24584: if (ret != 0) {
24585: if (ret < 0) {
24586: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24587: "validating facets of atomic simple type");
24588: goto internal_error;
24589: }
24590: if (WXS_IS_LIST(type))
24591: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24592: else
24593: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24594: }
24595: }
24596: if (fireErrors && (ret > 0))
24597: xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24598: } else if (WXS_IS_LIST(type)) {
24599:
24600: xmlSchemaTypePtr itemType;
24601: const xmlChar *cur, *end;
24602: xmlChar *tmpValue = NULL;
24603: unsigned long len = 0;
24604: xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24605: /* 1.2.2 if {variety} is �list� then the string must be a sequence
24606: * of white space separated tokens, each of which �match�es a literal
24607: * in the �lexical space� of {item type definition}
24608: */
24609: /*
24610: * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24611: * the list type has an enum or pattern facet.
24612: */
24613: NORMALIZE(type);
24614: /*
24615: * VAL TODO: Optimize validation of empty values.
24616: * VAL TODO: We do not have computed values for lists.
24617: */
24618: itemType = WXS_LIST_ITEMTYPE(type);
24619: cur = value;
24620: do {
24621: while (IS_BLANK_CH(*cur))
24622: cur++;
24623: end = cur;
24624: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24625: end++;
24626: if (end == cur)
24627: break;
24628: tmpValue = xmlStrndup(cur, end - cur);
24629: len++;
24630:
24631: if (valNeeded)
24632: ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24633: tmpValue, &curVal, fireErrors, 0, 1);
24634: else
24635: ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24636: tmpValue, NULL, fireErrors, 0, 1);
24637: FREE_AND_NULL(tmpValue);
24638: if (curVal != NULL) {
24639: /*
24640: * Add to list of computed values.
24641: */
24642: if (val == NULL)
24643: val = curVal;
24644: else
24645: xmlSchemaValueAppend(prevVal, curVal);
24646: prevVal = curVal;
24647: curVal = NULL;
24648: }
24649: if (ret != 0) {
24650: if (ret < 0) {
24651: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24652: "validating an item of list simple type");
24653: goto internal_error;
24654: }
24655: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24656: break;
24657: }
24658: cur = end;
24659: } while (*cur != 0);
24660: FREE_AND_NULL(tmpValue);
24661: if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24662: /*
24663: * Apply facets (pattern, enumeration).
24664: */
24665: ret = xmlSchemaValidateFacets(actxt, node, type,
24666: XML_SCHEMAS_UNKNOWN, value, val,
24667: len, fireErrors);
24668: if (ret != 0) {
24669: if (ret < 0) {
24670: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24671: "validating facets of list simple type");
24672: goto internal_error;
24673: }
24674: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24675: }
24676: }
24677: if (fireErrors && (ret > 0)) {
24678: /*
24679: * Report the normalized value.
24680: */
24681: normalize = 1;
24682: NORMALIZE(type);
24683: xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24684: }
24685: } else if (WXS_IS_UNION(type)) {
24686: xmlSchemaTypeLinkPtr memberLink;
24687: /*
24688: * TODO: For all datatypes �derived� by �union� whiteSpace does
24689: * not apply directly; however, the normalization behavior of �union�
24690: * types is controlled by the value of whiteSpace on that one of the
24691: * �memberTypes� against which the �union� is successfully validated.
24692: *
24693: * This means that the value is normalized by the first validating
24694: * member type, then the facets of the union type are applied. This
24695: * needs changing of the value!
24696: */
24697:
24698: /*
24699: * 1.2.3 if {variety} is �union� then the string must �match� a
24700: * literal in the �lexical space� of at least one member of
24701: * {member type definitions}
24702: */
24703: memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24704: if (memberLink == NULL) {
24705: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24706: "union simple type has no member types");
24707: goto internal_error;
24708: }
24709: /*
24710: * Always normalize union type values, since we currently
24711: * cannot store the whitespace information with the value
24712: * itself; otherwise a later value-comparison would be
24713: * not possible.
24714: */
24715: while (memberLink != NULL) {
24716: if (valNeeded)
24717: ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24718: memberLink->type, value, &val, 0, 1, 0);
24719: else
24720: ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24721: memberLink->type, value, NULL, 0, 1, 0);
24722: if (ret <= 0)
24723: break;
24724: memberLink = memberLink->next;
24725: }
24726: if (ret != 0) {
24727: if (ret < 0) {
24728: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24729: "validating members of union simple type");
24730: goto internal_error;
24731: }
24732: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24733: }
24734: /*
24735: * Apply facets (pattern, enumeration).
24736: */
24737: if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24738: /*
24739: * The normalization behavior of �union� types is controlled by
24740: * the value of whiteSpace on that one of the �memberTypes�
24741: * against which the �union� is successfully validated.
24742: */
24743: NORMALIZE(memberLink->type);
24744: ret = xmlSchemaValidateFacets(actxt, node, type,
24745: XML_SCHEMAS_UNKNOWN, value, val,
24746: 0, fireErrors);
24747: if (ret != 0) {
24748: if (ret < 0) {
24749: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24750: "validating facets of union simple type");
24751: goto internal_error;
24752: }
24753: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24754: }
24755: }
24756: if (fireErrors && (ret > 0))
24757: xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24758: }
24759:
24760: if (normValue != NULL)
24761: xmlFree(normValue);
24762: if (ret == 0) {
24763: if (retVal != NULL)
24764: *retVal = val;
24765: else if (val != NULL)
24766: xmlSchemaFreeValue(val);
24767: } else if (val != NULL)
24768: xmlSchemaFreeValue(val);
24769: return (ret);
24770: internal_error:
24771: if (normValue != NULL)
24772: xmlFree(normValue);
24773: if (val != NULL)
24774: xmlSchemaFreeValue(val);
24775: return (-1);
24776: }
24777:
24778: static int
24779: xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24780: const xmlChar *value,
24781: const xmlChar **nsName,
24782: const xmlChar **localName)
24783: {
24784: int ret = 0;
24785:
24786: if ((nsName == NULL) || (localName == NULL))
24787: return (-1);
24788: *nsName = NULL;
24789: *localName = NULL;
24790:
24791: ret = xmlValidateQName(value, 1);
24792: if (ret == -1)
24793: return (-1);
24794: if (ret > 0) {
24795: xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24796: XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24797: value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24798: return (1);
24799: }
24800: {
24801: xmlChar *local = NULL;
24802: xmlChar *prefix;
24803:
24804: /*
24805: * NOTE: xmlSplitQName2 will return a duplicated
24806: * string.
24807: */
24808: local = xmlSplitQName2(value, &prefix);
24809: if (local == NULL)
24810: *localName = xmlDictLookup(vctxt->dict, value, -1);
24811: else {
24812: *localName = xmlDictLookup(vctxt->dict, local, -1);
24813: xmlFree(local);
24814: }
24815:
24816: *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24817:
24818: if (prefix != NULL) {
24819: xmlFree(prefix);
24820: /*
24821: * A namespace must be found if the prefix is NOT NULL.
24822: */
24823: if (*nsName == NULL) {
24824: xmlSchemaCustomErr(ACTXT_CAST vctxt,
24825: XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24826: WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24827: "The QName value '%s' has no "
24828: "corresponding namespace declaration in scope",
24829: value, NULL);
24830: return (2);
24831: }
24832: }
24833: }
24834: return (0);
24835: }
24836:
24837: static int
24838: xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24839: xmlSchemaAttrInfoPtr iattr,
24840: xmlSchemaTypePtr *localType,
24841: xmlSchemaElementPtr elemDecl)
24842: {
24843: int ret = 0;
24844: /*
24845: * cvc-elt (3.3.4) : (4)
24846: * AND
24847: * Schema-Validity Assessment (Element) (cvc-assess-elt)
24848: * (1.2.1.2.1) - (1.2.1.2.4)
24849: * Handle 'xsi:type'.
24850: */
24851: if (localType == NULL)
24852: return (-1);
24853: *localType = NULL;
24854: if (iattr == NULL)
24855: return (0);
24856: else {
24857: const xmlChar *nsName = NULL, *local = NULL;
24858: /*
24859: * TODO: We should report a *warning* that the type was overriden
24860: * by the instance.
24861: */
24862: ACTIVATE_ATTRIBUTE(iattr);
24863: /*
24864: * (cvc-elt) (3.3.4) : (4.1)
24865: * (cvc-assess-elt) (1.2.1.2.2)
24866: */
24867: ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24868: &nsName, &local);
24869: if (ret != 0) {
24870: if (ret < 0) {
24871: VERROR_INT("xmlSchemaValidateElementByDeclaration",
24872: "calling xmlSchemaQNameExpand() to validate the "
24873: "attribute 'xsi:type'");
24874: goto internal_error;
24875: }
24876: goto exit;
24877: }
24878: /*
24879: * (cvc-elt) (3.3.4) : (4.2)
24880: * (cvc-assess-elt) (1.2.1.2.3)
24881: */
24882: *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24883: if (*localType == NULL) {
24884: xmlChar *str = NULL;
24885:
24886: xmlSchemaCustomErr(ACTXT_CAST vctxt,
24887: XML_SCHEMAV_CVC_ELT_4_2, NULL,
24888: WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24889: "The QName value '%s' of the xsi:type attribute does not "
24890: "resolve to a type definition",
24891: xmlSchemaFormatQName(&str, nsName, local), NULL);
24892: FREE_AND_NULL(str);
24893: ret = vctxt->err;
24894: goto exit;
24895: }
24896: if (elemDecl != NULL) {
24897: int set = 0;
24898:
24899: /*
24900: * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24901: * "The �local type definition� must be validly
24902: * derived from the {type definition} given the union of
24903: * the {disallowed substitutions} and the {type definition}'s
24904: * {prohibited substitutions}, as defined in
24905: * Type Derivation OK (Complex) (�3.4.6)
24906: * (if it is a complex type definition),
24907: * or given {disallowed substitutions} as defined in Type
24908: * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24909: * definition)."
24910: *
24911: * {disallowed substitutions}: the "block" on the element decl.
24912: * {prohibited substitutions}: the "block" on the type def.
24913: */
24914: /*
24915: * OPTIMIZE TODO: We could map types already evaluated
24916: * to be validly derived from other types to avoid checking
24917: * this over and over for the same types.
24918: */
24919: if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24920: (elemDecl->subtypes->flags &
24921: XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24922: set |= SUBSET_EXTENSION;
24923:
24924: if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24925: (elemDecl->subtypes->flags &
24926: XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24927: set |= SUBSET_RESTRICTION;
24928:
24929: /*
24930: * REMOVED and CHANGED since this produced a parser context
24931: * which adds to the string dict of the schema. So this would
24932: * change the schema and we don't want this. We don't need
24933: * the parser context anymore.
24934: *
24935: * if ((vctxt->pctxt == NULL) &&
24936: * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24937: * return (-1);
24938: */
24939:
24940: if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24941: elemDecl->subtypes, set) != 0) {
24942: xmlChar *str = NULL;
24943:
24944: xmlSchemaCustomErr(ACTXT_CAST vctxt,
24945: XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24946: "The type definition '%s', specified by xsi:type, is "
24947: "blocked or not validly derived from the type definition "
24948: "of the element declaration",
24949: xmlSchemaFormatQName(&str,
24950: (*localType)->targetNamespace,
24951: (*localType)->name),
24952: NULL);
24953: FREE_AND_NULL(str);
24954: ret = vctxt->err;
24955: *localType = NULL;
24956: }
24957: }
24958: }
24959: exit:
24960: ACTIVATE_ELEM;
24961: return (ret);
24962: internal_error:
24963: ACTIVATE_ELEM;
24964: return (-1);
24965: }
24966:
24967: static int
24968: xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24969: {
24970: xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24971: xmlSchemaTypePtr actualType;
24972:
24973: /*
24974: * cvc-elt (3.3.4) : 1
24975: */
24976: if (elemDecl == NULL) {
24977: VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24978: "No matching declaration available");
24979: return (vctxt->err);
24980: }
24981: actualType = WXS_ELEM_TYPEDEF(elemDecl);
24982: /*
24983: * cvc-elt (3.3.4) : 2
24984: */
24985: if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24986: VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24987: "The element declaration is abstract");
24988: return (vctxt->err);
24989: }
24990: if (actualType == NULL) {
24991: VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24992: "The type definition is absent");
24993: return (XML_SCHEMAV_CVC_TYPE_1);
24994: }
24995: if (vctxt->nbAttrInfos != 0) {
24996: int ret;
24997: xmlSchemaAttrInfoPtr iattr;
24998: /*
24999: * cvc-elt (3.3.4) : 3
25000: * Handle 'xsi:nil'.
25001: */
25002: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25003: XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25004: if (iattr) {
25005: ACTIVATE_ATTRIBUTE(iattr);
25006: /*
25007: * Validate the value.
25008: */
25009: ret = xmlSchemaVCheckCVCSimpleType(
25010: ACTXT_CAST vctxt, NULL,
25011: xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25012: iattr->value, &(iattr->val), 1, 0, 0);
25013: ACTIVATE_ELEM;
25014: if (ret < 0) {
25015: VERROR_INT("xmlSchemaValidateElemDecl",
25016: "calling xmlSchemaVCheckCVCSimpleType() to "
25017: "validate the attribute 'xsi:nil'");
25018: return (-1);
25019: }
25020: if (ret == 0) {
25021: if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25022: /*
25023: * cvc-elt (3.3.4) : 3.1
25024: */
25025: VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25026: "The element is not 'nillable'");
25027: /* Does not return an error on purpose. */
25028: } else {
25029: if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25030: /*
25031: * cvc-elt (3.3.4) : 3.2.2
25032: */
25033: if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25034: (elemDecl->value != NULL)) {
25035: VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25036: "The element cannot be 'nilled' because "
25037: "there is a fixed value constraint defined "
25038: "for it");
25039: /* Does not return an error on purpose. */
25040: } else
25041: vctxt->inode->flags |=
25042: XML_SCHEMA_ELEM_INFO_NILLED;
25043: }
25044: }
25045: }
25046: }
25047: /*
25048: * cvc-elt (3.3.4) : 4
25049: * Handle 'xsi:type'.
25050: */
25051: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25052: XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25053: if (iattr) {
25054: xmlSchemaTypePtr localType = NULL;
25055:
25056: ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25057: elemDecl);
25058: if (ret != 0) {
25059: if (ret == -1) {
25060: VERROR_INT("xmlSchemaValidateElemDecl",
25061: "calling xmlSchemaProcessXSIType() to "
25062: "process the attribute 'xsi:type'");
25063: return (-1);
25064: }
25065: /* Does not return an error on purpose. */
25066: }
25067: if (localType != NULL) {
25068: vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25069: actualType = localType;
25070: }
25071: }
25072: }
25073: /*
25074: * IDC: Register identity-constraint XPath matchers.
25075: */
25076: if ((elemDecl->idcs != NULL) &&
25077: (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25078: return (-1);
25079: /*
25080: * No actual type definition.
25081: */
25082: if (actualType == NULL) {
25083: VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25084: "The type definition is absent");
25085: return (XML_SCHEMAV_CVC_TYPE_1);
25086: }
25087: /*
25088: * Remember the actual type definition.
25089: */
25090: vctxt->inode->typeDef = actualType;
25091:
25092: return (0);
25093: }
25094:
25095: static int
25096: xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25097: {
25098: xmlSchemaAttrInfoPtr iattr;
25099: int ret = 0, i;
25100:
25101: /*
25102: * SPEC cvc-type (3.1.1)
25103: * "The attributes of must be empty, excepting those whose namespace
25104: * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25105: * whose local name is one of type, nil, schemaLocation or
25106: * noNamespaceSchemaLocation."
25107: */
25108: if (vctxt->nbAttrInfos == 0)
25109: return (0);
25110: for (i = 0; i < vctxt->nbAttrInfos; i++) {
25111: iattr = vctxt->attrInfos[i];
25112: if (! iattr->metaType) {
25113: ACTIVATE_ATTRIBUTE(iattr)
25114: xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25115: XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25116: ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25117: }
25118: }
25119: ACTIVATE_ELEM
25120: return (ret);
25121: }
25122:
25123: /*
25124: * Cleanup currently used attribute infos.
25125: */
25126: static void
25127: xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25128: {
25129: int i;
25130: xmlSchemaAttrInfoPtr attr;
25131:
25132: if (vctxt->nbAttrInfos == 0)
25133: return;
25134: for (i = 0; i < vctxt->nbAttrInfos; i++) {
25135: attr = vctxt->attrInfos[i];
25136: if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25137: if (attr->localName != NULL)
25138: xmlFree((xmlChar *) attr->localName);
25139: if (attr->nsName != NULL)
25140: xmlFree((xmlChar *) attr->nsName);
25141: }
25142: if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25143: if (attr->value != NULL)
25144: xmlFree((xmlChar *) attr->value);
25145: }
25146: if (attr->val != NULL) {
25147: xmlSchemaFreeValue(attr->val);
25148: attr->val = NULL;
25149: }
25150: memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25151: }
25152: vctxt->nbAttrInfos = 0;
25153: }
25154:
25155: /*
25156: * 3.4.4 Complex Type Definition Validation Rules
25157: * Element Locally Valid (Complex Type) (cvc-complex-type)
25158: * 3.2.4 Attribute Declaration Validation Rules
25159: * Validation Rule: Attribute Locally Valid (cvc-attribute)
25160: * Attribute Locally Valid (Use) (cvc-au)
25161: *
25162: * Only "assessed" attribute information items will be visible to
25163: * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25164: */
25165: static int
25166: xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25167: {
25168: xmlSchemaTypePtr type = vctxt->inode->typeDef;
25169: xmlSchemaItemListPtr attrUseList;
25170: xmlSchemaAttributeUsePtr attrUse = NULL;
25171: xmlSchemaAttributePtr attrDecl = NULL;
25172: xmlSchemaAttrInfoPtr iattr, tmpiattr;
25173: int i, j, found, nbAttrs, nbUses;
25174: int xpathRes = 0, res, wildIDs = 0, fixed;
25175: xmlNodePtr defAttrOwnerElem = NULL;
25176:
25177: /*
25178: * SPEC (cvc-attribute)
25179: * (1) "The declaration must not be �absent� (see Missing
25180: * Sub-components (�5.3) for how this can fail to be
25181: * the case)."
25182: * (2) "Its {type definition} must not be absent."
25183: *
25184: * NOTE (1) + (2): This is not handled here, since we currently do not
25185: * allow validation against schemas which have missing sub-components.
25186: *
25187: * SPEC (cvc-complex-type)
25188: * (3) "For each attribute information item in the element information
25189: * item's [attributes] excepting those whose [namespace name] is
25190: * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25191: * [local name] is one of type, nil, schemaLocation or
25192: * noNamespaceSchemaLocation, the appropriate case among the following
25193: * must be true:
25194: *
25195: */
25196: attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25197: /*
25198: * @nbAttrs is the number of attributes present in the instance.
25199: */
25200: nbAttrs = vctxt->nbAttrInfos;
25201: if (attrUseList != NULL)
25202: nbUses = attrUseList->nbItems;
25203: else
25204: nbUses = 0;
25205: for (i = 0; i < nbUses; i++) {
25206: found = 0;
25207: attrUse = attrUseList->items[i];
25208: attrDecl = WXS_ATTRUSE_DECL(attrUse);
25209: for (j = 0; j < nbAttrs; j++) {
25210: iattr = vctxt->attrInfos[j];
25211: /*
25212: * SPEC (cvc-complex-type) (3)
25213: * Skip meta attributes.
25214: */
25215: if (iattr->metaType)
25216: continue;
25217: if (iattr->localName[0] != attrDecl->name[0])
25218: continue;
25219: if (!xmlStrEqual(iattr->localName, attrDecl->name))
25220: continue;
25221: if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25222: continue;
25223: found = 1;
25224: /*
25225: * SPEC (cvc-complex-type)
25226: * (3.1) "If there is among the {attribute uses} an attribute
25227: * use with an {attribute declaration} whose {name} matches
25228: * the attribute information item's [local name] and whose
25229: * {target namespace} is identical to the attribute information
25230: * item's [namespace name] (where an �absent� {target namespace}
25231: * is taken to be identical to a [namespace name] with no value),
25232: * then the attribute information must be �valid� with respect
25233: * to that attribute use as per Attribute Locally Valid (Use)
25234: * (�3.5.4). In this case the {attribute declaration} of that
25235: * attribute use is the �context-determined declaration� for the
25236: * attribute information item with respect to Schema-Validity
25237: * Assessment (Attribute) (�3.2.4) and
25238: * Assessment Outcome (Attribute) (�3.2.5).
25239: */
25240: iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25241: iattr->use = attrUse;
25242: /*
25243: * Context-determined declaration.
25244: */
25245: iattr->decl = attrDecl;
25246: iattr->typeDef = attrDecl->subtypes;
25247: break;
25248: }
25249:
25250: if (found)
25251: continue;
25252:
25253: if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25254: /*
25255: * Handle non-existent, required attributes.
25256: *
25257: * SPEC (cvc-complex-type)
25258: * (4) "The {attribute declaration} of each attribute use in
25259: * the {attribute uses} whose {required} is true matches one
25260: * of the attribute information items in the element information
25261: * item's [attributes] as per clause 3.1 above."
25262: */
25263: tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25264: if (tmpiattr == NULL) {
25265: VERROR_INT(
25266: "xmlSchemaVAttributesComplex",
25267: "calling xmlSchemaGetFreshAttrInfo()");
25268: return (-1);
25269: }
25270: tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25271: tmpiattr->use = attrUse;
25272: tmpiattr->decl = attrDecl;
25273: } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25274: ((attrUse->defValue != NULL) ||
25275: (attrDecl->defValue != NULL))) {
25276: /*
25277: * Handle non-existent, optional, default/fixed attributes.
25278: */
25279: tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25280: if (tmpiattr == NULL) {
25281: VERROR_INT(
25282: "xmlSchemaVAttributesComplex",
25283: "calling xmlSchemaGetFreshAttrInfo()");
25284: return (-1);
25285: }
25286: tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25287: tmpiattr->use = attrUse;
25288: tmpiattr->decl = attrDecl;
25289: tmpiattr->typeDef = attrDecl->subtypes;
25290: tmpiattr->localName = attrDecl->name;
25291: tmpiattr->nsName = attrDecl->targetNamespace;
25292: }
25293: }
25294:
25295: if (vctxt->nbAttrInfos == 0)
25296: return (0);
25297: /*
25298: * Validate against the wildcard.
25299: */
25300: if (type->attributeWildcard != NULL) {
25301: /*
25302: * SPEC (cvc-complex-type)
25303: * (3.2.1) "There must be an {attribute wildcard}."
25304: */
25305: for (i = 0; i < nbAttrs; i++) {
25306: iattr = vctxt->attrInfos[i];
25307: /*
25308: * SPEC (cvc-complex-type) (3)
25309: * Skip meta attributes.
25310: */
25311: if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25312: continue;
25313: /*
25314: * SPEC (cvc-complex-type)
25315: * (3.2.2) "The attribute information item must be �valid� with
25316: * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25317: *
25318: * SPEC Item Valid (Wildcard) (cvc-wildcard)
25319: * "... its [namespace name] must be �valid� with respect to
25320: * the wildcard constraint, as defined in Wildcard allows
25321: * Namespace Name (�3.10.4)."
25322: */
25323: if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25324: iattr->nsName) == 0) {
25325: /*
25326: * Handle processContents.
25327: *
25328: * SPEC (cvc-wildcard):
25329: * processContents | context-determined declaration:
25330: * "strict" "mustFind"
25331: * "lax" "none"
25332: * "skip" "skip"
25333: */
25334: if (type->attributeWildcard->processContents ==
25335: XML_SCHEMAS_ANY_SKIP) {
25336: /*
25337: * context-determined declaration = "skip"
25338: *
25339: * SPEC PSVI Assessment Outcome (Attribute)
25340: * [validity] = "notKnown"
25341: * [validation attempted] = "none"
25342: */
25343: iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25344: continue;
25345: }
25346: /*
25347: * Find an attribute declaration.
25348: */
25349: iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25350: iattr->localName, iattr->nsName);
25351: if (iattr->decl != NULL) {
25352: iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25353: /*
25354: * SPEC (cvc-complex-type)
25355: * (5) "Let [Definition:] the wild IDs be the set of
25356: * all attribute information item to which clause 3.2
25357: * applied and whose �validation� resulted in a
25358: * �context-determined declaration� of mustFind or no
25359: * �context-determined declaration� at all, and whose
25360: * [local name] and [namespace name] resolve (as
25361: * defined by QName resolution (Instance) (�3.15.4)) to
25362: * an attribute declaration whose {type definition} is
25363: * or is derived from ID. Then all of the following
25364: * must be true:"
25365: */
25366: iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25367: if (xmlSchemaIsDerivedFromBuiltInType(
25368: iattr->typeDef, XML_SCHEMAS_ID)) {
25369: /*
25370: * SPEC (5.1) "There must be no more than one
25371: * item in �wild IDs�."
25372: */
25373: if (wildIDs != 0) {
25374: /* VAL TODO */
25375: iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25376: TODO
25377: continue;
25378: }
25379: wildIDs++;
25380: /*
25381: * SPEC (cvc-complex-type)
25382: * (5.2) "If �wild IDs� is non-empty, there must not
25383: * be any attribute uses among the {attribute uses}
25384: * whose {attribute declaration}'s {type definition}
25385: * is or is derived from ID."
25386: */
25387: if (attrUseList != NULL) {
25388: for (j = 0; j < attrUseList->nbItems; j++) {
25389: if (xmlSchemaIsDerivedFromBuiltInType(
25390: WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25391: XML_SCHEMAS_ID)) {
25392: /* URGENT VAL TODO: implement */
25393: iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25394: TODO
25395: break;
25396: }
25397: }
25398: }
25399: }
25400: } else if (type->attributeWildcard->processContents ==
25401: XML_SCHEMAS_ANY_LAX) {
25402: iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25403: /*
25404: * SPEC PSVI Assessment Outcome (Attribute)
25405: * [validity] = "notKnown"
25406: * [validation attempted] = "none"
25407: */
25408: } else {
25409: iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25410: }
25411: }
25412: }
25413: }
25414:
25415: if (vctxt->nbAttrInfos == 0)
25416: return (0);
25417:
25418: /*
25419: * Get the owner element; needed for creation of default attributes.
25420: * This fixes bug #341337, reported by David Grohmann.
25421: */
25422: if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25423: xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25424: if (ielem && ielem->node && ielem->node->doc)
25425: defAttrOwnerElem = ielem->node;
25426: }
25427: /*
25428: * Validate values, create default attributes, evaluate IDCs.
25429: */
25430: for (i = 0; i < vctxt->nbAttrInfos; i++) {
25431: iattr = vctxt->attrInfos[i];
25432: /*
25433: * VAL TODO: Note that we won't try to resolve IDCs to
25434: * "lax" and "skip" validated attributes. Check what to
25435: * do in this case.
25436: */
25437: if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25438: (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25439: continue;
25440: /*
25441: * VAL TODO: What to do if the type definition is missing?
25442: */
25443: if (iattr->typeDef == NULL) {
25444: iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25445: continue;
25446: }
25447:
25448: ACTIVATE_ATTRIBUTE(iattr);
25449: fixed = 0;
25450: xpathRes = 0;
25451:
25452: if (vctxt->xpathStates != NULL) {
25453: /*
25454: * Evaluate IDCs.
25455: */
25456: xpathRes = xmlSchemaXPathEvaluate(vctxt,
25457: XML_ATTRIBUTE_NODE);
25458: if (xpathRes == -1) {
25459: VERROR_INT("xmlSchemaVAttributesComplex",
25460: "calling xmlSchemaXPathEvaluate()");
25461: goto internal_error;
25462: }
25463: }
25464:
25465: if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25466: /*
25467: * Default/fixed attributes.
25468: * We need the value only if we need to resolve IDCs or
25469: * will create default attributes.
25470: */
25471: if ((xpathRes) || (defAttrOwnerElem)) {
25472: if (iattr->use->defValue != NULL) {
25473: iattr->value = (xmlChar *) iattr->use->defValue;
25474: iattr->val = iattr->use->defVal;
25475: } else {
25476: iattr->value = (xmlChar *) iattr->decl->defValue;
25477: iattr->val = iattr->decl->defVal;
25478: }
25479: /*
25480: * IDCs will consume the precomputed default value,
25481: * so we need to clone it.
25482: */
25483: if (iattr->val == NULL) {
25484: VERROR_INT("xmlSchemaVAttributesComplex",
25485: "default/fixed value on an attribute use was "
25486: "not precomputed");
25487: goto internal_error;
25488: }
25489: iattr->val = xmlSchemaCopyValue(iattr->val);
25490: if (iattr->val == NULL) {
25491: VERROR_INT("xmlSchemaVAttributesComplex",
25492: "calling xmlSchemaCopyValue()");
25493: goto internal_error;
25494: }
25495: }
25496: /*
25497: * PSVI: Add the default attribute to the current element.
25498: * VAL TODO: Should we use the *normalized* value? This currently
25499: * uses the *initial* value.
25500: */
25501:
25502: if (defAttrOwnerElem) {
25503: xmlChar *normValue;
25504: const xmlChar *value;
25505:
25506: value = iattr->value;
25507: /*
25508: * Normalize the value.
25509: */
25510: normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25511: iattr->value);
25512: if (normValue != NULL)
25513: value = BAD_CAST normValue;
25514:
25515: if (iattr->nsName == NULL) {
25516: if (xmlNewProp(defAttrOwnerElem,
25517: iattr->localName, value) == NULL) {
25518: VERROR_INT("xmlSchemaVAttributesComplex",
25519: "callling xmlNewProp()");
25520: if (normValue != NULL)
25521: xmlFree(normValue);
25522: goto internal_error;
25523: }
25524: } else {
25525: xmlNsPtr ns;
25526:
25527: ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25528: defAttrOwnerElem, iattr->nsName);
25529: if (ns == NULL) {
25530: xmlChar prefix[12];
25531: int counter = 0;
25532:
25533: /*
25534: * Create a namespace declaration on the validation
25535: * root node if no namespace declaration is in scope.
25536: */
25537: do {
25538: snprintf((char *) prefix, 12, "p%d", counter++);
25539: ns = xmlSearchNs(defAttrOwnerElem->doc,
25540: defAttrOwnerElem, BAD_CAST prefix);
25541: if (counter > 1000) {
25542: VERROR_INT(
25543: "xmlSchemaVAttributesComplex",
25544: "could not compute a ns prefix for a "
25545: "default/fixed attribute");
25546: if (normValue != NULL)
25547: xmlFree(normValue);
25548: goto internal_error;
25549: }
25550: } while (ns != NULL);
25551: ns = xmlNewNs(vctxt->validationRoot,
25552: iattr->nsName, BAD_CAST prefix);
25553: }
25554: /*
25555: * TODO:
25556: * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25557: * If we have QNames: do we need to ensure there's a
25558: * prefix defined for the QName?
25559: */
25560: xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25561: }
25562: if (normValue != NULL)
25563: xmlFree(normValue);
25564: }
25565: /*
25566: * Go directly to IDC evaluation.
25567: */
25568: goto eval_idcs;
25569: }
25570: /*
25571: * Validate the value.
25572: */
25573: if (vctxt->value != NULL) {
25574: /*
25575: * Free last computed value; just for safety reasons.
25576: */
25577: xmlSchemaFreeValue(vctxt->value);
25578: vctxt->value = NULL;
25579: }
25580: /*
25581: * Note that the attribute *use* can be unavailable, if
25582: * the attribute was a wild attribute.
25583: */
25584: if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25585: ((iattr->use != NULL) &&
25586: (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25587: fixed = 1;
25588: else
25589: fixed = 0;
25590: /*
25591: * SPEC (cvc-attribute)
25592: * (3) "The item's �normalized value� must be locally �valid�
25593: * with respect to that {type definition} as per
25594: * String Valid (�3.14.4)."
25595: *
25596: * VAL TODO: Do we already have the
25597: * "normalized attribute value" here?
25598: */
25599: if (xpathRes || fixed) {
25600: iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25601: /*
25602: * Request a computed value.
25603: */
25604: res = xmlSchemaVCheckCVCSimpleType(
25605: ACTXT_CAST vctxt,
25606: iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25607: 1, 1, 0);
25608: } else {
25609: res = xmlSchemaVCheckCVCSimpleType(
25610: ACTXT_CAST vctxt,
25611: iattr->node, iattr->typeDef, iattr->value, NULL,
25612: 1, 0, 0);
25613: }
25614:
25615: if (res != 0) {
25616: if (res == -1) {
25617: VERROR_INT("xmlSchemaVAttributesComplex",
25618: "calling xmlSchemaStreamValidateSimpleTypeValue()");
25619: goto internal_error;
25620: }
25621: iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25622: /*
25623: * SPEC PSVI Assessment Outcome (Attribute)
25624: * [validity] = "invalid"
25625: */
25626: goto eval_idcs;
25627: }
25628:
25629: if (fixed) {
25630: /*
25631: * SPEC Attribute Locally Valid (Use) (cvc-au)
25632: * "For an attribute information item to be�valid�
25633: * with respect to an attribute use its *normalized*
25634: * value� must match the *canonical* lexical
25635: * representation of the attribute use's {value
25636: * constraint}value, if it is present and fixed."
25637: *
25638: * VAL TODO: The requirement for the *canonical* value
25639: * will be removed in XML Schema 1.1.
25640: */
25641: /*
25642: * SPEC Attribute Locally Valid (cvc-attribute)
25643: * (4) "The item's *actual* value� must match the *value* of
25644: * the {value constraint}, if it is present and fixed."
25645: */
25646: if (iattr->val == NULL) {
25647: /* VAL TODO: A value was not precomputed. */
25648: TODO
25649: goto eval_idcs;
25650: }
25651: if ((iattr->use != NULL) &&
25652: (iattr->use->defValue != NULL)) {
25653: if (iattr->use->defVal == NULL) {
25654: /* VAL TODO: A default value was not precomputed. */
25655: TODO
25656: goto eval_idcs;
25657: }
25658: iattr->vcValue = iattr->use->defValue;
25659: /*
25660: if (xmlSchemaCompareValuesWhtsp(attr->val,
25661: (xmlSchemaWhitespaceValueType) ws,
25662: attr->use->defVal,
25663: (xmlSchemaWhitespaceValueType) ws) != 0) {
25664: */
25665: if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25666: iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25667: } else {
25668: if (iattr->decl->defVal == NULL) {
25669: /* VAL TODO: A default value was not precomputed. */
25670: TODO
25671: goto eval_idcs;
25672: }
25673: iattr->vcValue = iattr->decl->defValue;
25674: /*
25675: if (xmlSchemaCompareValuesWhtsp(attr->val,
25676: (xmlSchemaWhitespaceValueType) ws,
25677: attrDecl->defVal,
25678: (xmlSchemaWhitespaceValueType) ws) != 0) {
25679: */
25680: if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25681: iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25682: }
25683: /*
25684: * [validity] = "valid"
25685: */
25686: }
25687: eval_idcs:
25688: /*
25689: * Evaluate IDCs.
25690: */
25691: if (xpathRes) {
25692: if (xmlSchemaXPathProcessHistory(vctxt,
25693: vctxt->depth +1) == -1) {
25694: VERROR_INT("xmlSchemaVAttributesComplex",
25695: "calling xmlSchemaXPathEvaluate()");
25696: goto internal_error;
25697: }
25698: } else if (vctxt->xpathStates != NULL)
25699: xmlSchemaXPathPop(vctxt);
25700: }
25701:
25702: /*
25703: * Report errors.
25704: */
25705: for (i = 0; i < vctxt->nbAttrInfos; i++) {
25706: iattr = vctxt->attrInfos[i];
25707: if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25708: (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25709: (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25710: (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25711: continue;
25712: ACTIVATE_ATTRIBUTE(iattr);
25713: switch (iattr->state) {
25714: case XML_SCHEMAS_ATTR_ERR_MISSING: {
25715: xmlChar *str = NULL;
25716: ACTIVATE_ELEM;
25717: xmlSchemaCustomErr(ACTXT_CAST vctxt,
25718: XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25719: "The attribute '%s' is required but missing",
25720: xmlSchemaFormatQName(&str,
25721: iattr->decl->targetNamespace,
25722: iattr->decl->name),
25723: NULL);
25724: FREE_AND_NULL(str)
25725: break;
25726: }
25727: case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25728: VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25729: "The type definition is absent");
25730: break;
25731: case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25732: xmlSchemaCustomErr(ACTXT_CAST vctxt,
25733: XML_SCHEMAV_CVC_AU, NULL, NULL,
25734: "The value '%s' does not match the fixed "
25735: "value constraint '%s'",
25736: iattr->value, iattr->vcValue);
25737: break;
25738: case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25739: VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25740: "No matching global attribute declaration available, but "
25741: "demanded by the strict wildcard");
25742: break;
25743: case XML_SCHEMAS_ATTR_UNKNOWN:
25744: if (iattr->metaType)
25745: break;
25746: /*
25747: * MAYBE VAL TODO: One might report different error messages
25748: * for the following errors.
25749: */
25750: if (type->attributeWildcard == NULL) {
25751: xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25752: XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25753: } else {
25754: xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25755: XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25756: }
25757: break;
25758: default:
25759: break;
25760: }
25761: }
25762:
25763: ACTIVATE_ELEM;
25764: return (0);
25765: internal_error:
25766: ACTIVATE_ELEM;
25767: return (-1);
25768: }
25769:
25770: static int
25771: xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25772: int *skip)
25773: {
25774: xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25775: /*
25776: * The namespace of the element was already identified to be
25777: * matching the wildcard.
25778: */
25779: if ((skip == NULL) || (wild == NULL) ||
25780: (wild->type != XML_SCHEMA_TYPE_ANY)) {
25781: VERROR_INT("xmlSchemaValidateElemWildcard",
25782: "bad arguments");
25783: return (-1);
25784: }
25785: *skip = 0;
25786: if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25787: /*
25788: * URGENT VAL TODO: Either we need to position the stream to the
25789: * next sibling, or walk the whole subtree.
25790: */
25791: *skip = 1;
25792: return (0);
25793: }
25794: {
25795: xmlSchemaElementPtr decl = NULL;
25796:
25797: decl = xmlSchemaGetElem(vctxt->schema,
25798: vctxt->inode->localName, vctxt->inode->nsName);
25799: if (decl != NULL) {
25800: vctxt->inode->decl = decl;
25801: return (0);
25802: }
25803: }
25804: if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25805: /* VAL TODO: Change to proper error code. */
25806: VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25807: "No matching global element declaration available, but "
25808: "demanded by the strict wildcard");
25809: return (vctxt->err);
25810: }
25811: if (vctxt->nbAttrInfos != 0) {
25812: xmlSchemaAttrInfoPtr iattr;
25813: /*
25814: * SPEC Validation Rule: Schema-Validity Assessment (Element)
25815: * (1.2.1.2.1) - (1.2.1.2.3 )
25816: *
25817: * Use the xsi:type attribute for the type definition.
25818: */
25819: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25820: XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25821: if (iattr != NULL) {
25822: if (xmlSchemaProcessXSIType(vctxt, iattr,
25823: &(vctxt->inode->typeDef), NULL) == -1) {
25824: VERROR_INT("xmlSchemaValidateElemWildcard",
25825: "calling xmlSchemaProcessXSIType() to "
25826: "process the attribute 'xsi:nil'");
25827: return (-1);
25828: }
25829: /*
25830: * Don't return an error on purpose.
25831: */
25832: return (0);
25833: }
25834: }
25835: /*
25836: * SPEC Validation Rule: Schema-Validity Assessment (Element)
25837: *
25838: * Fallback to "anyType".
25839: */
25840: vctxt->inode->typeDef =
25841: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25842: return (0);
25843: }
25844:
25845: /*
25846: * xmlSchemaCheckCOSValidDefault:
25847: *
25848: * This will be called if: not nilled, no content and a default/fixed
25849: * value is provided.
25850: */
25851:
25852: static int
25853: xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25854: const xmlChar *value,
25855: xmlSchemaValPtr *val)
25856: {
25857: int ret = 0;
25858: xmlSchemaNodeInfoPtr inode = vctxt->inode;
25859:
25860: /*
25861: * cos-valid-default:
25862: * Schema Component Constraint: Element Default Valid (Immediate)
25863: * For a string to be a valid default with respect to a type
25864: * definition the appropriate case among the following must be true:
25865: */
25866: if WXS_IS_COMPLEX(inode->typeDef) {
25867: /*
25868: * Complex type.
25869: *
25870: * SPEC (2.1) "its {content type} must be a simple type definition
25871: * or mixed."
25872: * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25873: * type}'s particle must be �emptiable� as defined by
25874: * Particle Emptiable (�3.9.6)."
25875: */
25876: if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25877: ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25878: (! WXS_EMPTIABLE(inode->typeDef)))) {
25879: ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25880: /* NOTE that this covers (2.2.2) as well. */
25881: VERROR(ret, NULL,
25882: "For a string to be a valid default, the type definition "
25883: "must be a simple type or a complex type with simple content "
25884: "or mixed content and a particle emptiable");
25885: return(ret);
25886: }
25887: }
25888: /*
25889: * 1 If the type definition is a simple type definition, then the string
25890: * must be �valid� with respect to that definition as defined by String
25891: * Valid (�3.14.4).
25892: *
25893: * AND
25894: *
25895: * 2.2.1 If the {content type} is a simple type definition, then the
25896: * string must be �valid� with respect to that simple type definition
25897: * as defined by String Valid (�3.14.4).
25898: */
25899: if (WXS_IS_SIMPLE(inode->typeDef)) {
25900:
25901: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25902: NULL, inode->typeDef, value, val, 1, 1, 0);
25903:
25904: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25905:
25906: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25907: NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25908: }
25909: if (ret < 0) {
25910: VERROR_INT("xmlSchemaCheckCOSValidDefault",
25911: "calling xmlSchemaVCheckCVCSimpleType()");
25912: }
25913: return (ret);
25914: }
25915:
25916: static void
25917: xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25918: const xmlChar * name ATTRIBUTE_UNUSED,
25919: xmlSchemaElementPtr item,
25920: xmlSchemaNodeInfoPtr inode)
25921: {
25922: inode->decl = item;
25923: #ifdef DEBUG_CONTENT
25924: {
25925: xmlChar *str = NULL;
25926:
25927: if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25928: xmlGenericError(xmlGenericErrorContext,
25929: "AUTOMATON callback for '%s' [declaration]\n",
25930: xmlSchemaFormatQName(&str,
25931: inode->localName, inode->nsName));
25932: } else {
25933: xmlGenericError(xmlGenericErrorContext,
25934: "AUTOMATON callback for '%s' [wildcard]\n",
25935: xmlSchemaFormatQName(&str,
25936: inode->localName, inode->nsName));
25937:
25938: }
25939: FREE_AND_NULL(str)
25940: }
25941: #endif
25942: }
25943:
25944: static int
25945: xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25946: {
25947: vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25948: if (vctxt->inode == NULL) {
25949: VERROR_INT("xmlSchemaValidatorPushElem",
25950: "calling xmlSchemaGetFreshElemInfo()");
25951: return (-1);
25952: }
25953: vctxt->nbAttrInfos = 0;
25954: return (0);
25955: }
25956:
25957: static int
25958: xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25959: xmlSchemaNodeInfoPtr inode,
25960: xmlSchemaTypePtr type,
25961: const xmlChar *value)
25962: {
25963: if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25964: return (xmlSchemaVCheckCVCSimpleType(
25965: ACTXT_CAST vctxt, NULL,
25966: type, value, &(inode->val), 1, 1, 0));
25967: else
25968: return (xmlSchemaVCheckCVCSimpleType(
25969: ACTXT_CAST vctxt, NULL,
25970: type, value, NULL, 1, 0, 0));
25971: }
25972:
25973:
25974:
25975: /*
25976: * Process END of element.
25977: */
25978: static int
25979: xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25980: {
25981: int ret = 0;
25982: xmlSchemaNodeInfoPtr inode = vctxt->inode;
25983:
25984: if (vctxt->nbAttrInfos != 0)
25985: xmlSchemaClearAttrInfos(vctxt);
25986: if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25987: /*
25988: * This element was not expected;
25989: * we will not validate child elements of broken parents.
25990: * Skip validation of all content of the parent.
25991: */
25992: vctxt->skipDepth = vctxt->depth -1;
25993: goto end_elem;
25994: }
25995: if ((inode->typeDef == NULL) ||
25996: (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25997: /*
25998: * 1. the type definition might be missing if the element was
25999: * error prone
26000: * 2. it might be abstract.
26001: */
26002: goto end_elem;
26003: }
26004: /*
26005: * Check the content model.
26006: */
26007: if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26008: (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26009:
26010: /*
26011: * Workaround for "anyType".
26012: */
26013: if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26014: goto character_content;
26015:
26016: if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26017: xmlChar *values[10];
26018: int terminal, nbval = 10, nbneg;
26019:
26020: if (inode->regexCtxt == NULL) {
26021: /*
26022: * Create the regex context.
26023: */
26024: inode->regexCtxt =
26025: xmlRegNewExecCtxt(inode->typeDef->contModel,
26026: (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26027: vctxt);
26028: if (inode->regexCtxt == NULL) {
26029: VERROR_INT("xmlSchemaValidatorPopElem",
26030: "failed to create a regex context");
26031: goto internal_error;
26032: }
26033: #ifdef DEBUG_AUTOMATA
26034: xmlGenericError(xmlGenericErrorContext,
26035: "AUTOMATON create on '%s'\n", inode->localName);
26036: #endif
26037: }
26038: /*
26039: * Get hold of the still expected content, since a further
26040: * call to xmlRegExecPushString() will loose this information.
26041: */
26042: xmlRegExecNextValues(inode->regexCtxt,
26043: &nbval, &nbneg, &values[0], &terminal);
26044: ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26045: if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26046: /*
26047: * Still missing something.
26048: */
26049: ret = 1;
26050: inode->flags |=
26051: XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26052: xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26053: XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26054: "Missing child element(s)",
26055: nbval, nbneg, values);
26056: #ifdef DEBUG_AUTOMATA
26057: xmlGenericError(xmlGenericErrorContext,
26058: "AUTOMATON missing ERROR on '%s'\n",
26059: inode->localName);
26060: #endif
26061: } else {
26062: /*
26063: * Content model is satisfied.
26064: */
26065: ret = 0;
26066: #ifdef DEBUG_AUTOMATA
26067: xmlGenericError(xmlGenericErrorContext,
26068: "AUTOMATON succeeded on '%s'\n",
26069: inode->localName);
26070: #endif
26071: }
26072:
26073: }
26074: }
26075: if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26076: goto end_elem;
26077:
26078: character_content:
26079:
26080: if (vctxt->value != NULL) {
26081: xmlSchemaFreeValue(vctxt->value);
26082: vctxt->value = NULL;
26083: }
26084: /*
26085: * Check character content.
26086: */
26087: if (inode->decl == NULL) {
26088: /*
26089: * Speedup if no declaration exists.
26090: */
26091: if (WXS_IS_SIMPLE(inode->typeDef)) {
26092: ret = xmlSchemaVCheckINodeDataType(vctxt,
26093: inode, inode->typeDef, inode->value);
26094: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26095: ret = xmlSchemaVCheckINodeDataType(vctxt,
26096: inode, inode->typeDef->contentTypeDef,
26097: inode->value);
26098: }
26099: if (ret < 0) {
26100: VERROR_INT("xmlSchemaValidatorPopElem",
26101: "calling xmlSchemaVCheckCVCSimpleType()");
26102: goto internal_error;
26103: }
26104: goto end_elem;
26105: }
26106: /*
26107: * cvc-elt (3.3.4) : 5
26108: * The appropriate case among the following must be true:
26109: */
26110: /*
26111: * cvc-elt (3.3.4) : 5.1
26112: * If the declaration has a {value constraint},
26113: * the item has neither element nor character [children] and
26114: * clause 3.2 has not applied, then all of the following must be true:
26115: */
26116: if ((inode->decl->value != NULL) &&
26117: (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26118: (! INODE_NILLED(inode))) {
26119: /*
26120: * cvc-elt (3.3.4) : 5.1.1
26121: * If the �actual type definition� is a �local type definition�
26122: * then the canonical lexical representation of the {value constraint}
26123: * value must be a valid default for the �actual type definition� as
26124: * defined in Element Default Valid (Immediate) (�3.3.6).
26125: */
26126: /*
26127: * NOTE: 'local' above means types acquired by xsi:type.
26128: * NOTE: Although the *canonical* value is stated, it is not
26129: * relevant if canonical or not. Additionally XML Schema 1.1
26130: * will removed this requirement as well.
26131: */
26132: if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26133:
26134: ret = xmlSchemaCheckCOSValidDefault(vctxt,
26135: inode->decl->value, &(inode->val));
26136: if (ret != 0) {
26137: if (ret < 0) {
26138: VERROR_INT("xmlSchemaValidatorPopElem",
26139: "calling xmlSchemaCheckCOSValidDefault()");
26140: goto internal_error;
26141: }
26142: goto end_elem;
26143: }
26144: /*
26145: * Stop here, to avoid redundant validation of the value
26146: * (see following).
26147: */
26148: goto default_psvi;
26149: }
26150: /*
26151: * cvc-elt (3.3.4) : 5.1.2
26152: * The element information item with the canonical lexical
26153: * representation of the {value constraint} value used as its
26154: * �normalized value� must be �valid� with respect to the
26155: * �actual type definition� as defined by Element Locally Valid (Type)
26156: * (�3.3.4).
26157: */
26158: if (WXS_IS_SIMPLE(inode->typeDef)) {
26159: ret = xmlSchemaVCheckINodeDataType(vctxt,
26160: inode, inode->typeDef, inode->decl->value);
26161: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26162: ret = xmlSchemaVCheckINodeDataType(vctxt,
26163: inode, inode->typeDef->contentTypeDef,
26164: inode->decl->value);
26165: }
26166: if (ret != 0) {
26167: if (ret < 0) {
26168: VERROR_INT("xmlSchemaValidatorPopElem",
26169: "calling xmlSchemaVCheckCVCSimpleType()");
26170: goto internal_error;
26171: }
26172: goto end_elem;
26173: }
26174:
26175: default_psvi:
26176: /*
26177: * PSVI: Create a text node on the instance element.
26178: */
26179: if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26180: (inode->node != NULL)) {
26181: xmlNodePtr textChild;
26182: xmlChar *normValue;
26183: /*
26184: * VAL TODO: Normalize the value.
26185: */
26186: normValue = xmlSchemaNormalizeValue(inode->typeDef,
26187: inode->decl->value);
26188: if (normValue != NULL) {
26189: textChild = xmlNewText(BAD_CAST normValue);
26190: xmlFree(normValue);
26191: } else
26192: textChild = xmlNewText(inode->decl->value);
26193: if (textChild == NULL) {
26194: VERROR_INT("xmlSchemaValidatorPopElem",
26195: "calling xmlNewText()");
26196: goto internal_error;
26197: } else
26198: xmlAddChild(inode->node, textChild);
26199: }
26200:
26201: } else if (! INODE_NILLED(inode)) {
26202: /*
26203: * 5.2.1 The element information item must be �valid� with respect
26204: * to the �actual type definition� as defined by Element Locally
26205: * Valid (Type) (�3.3.4).
26206: */
26207: if (WXS_IS_SIMPLE(inode->typeDef)) {
26208: /*
26209: * SPEC (cvc-type) (3.1)
26210: * "If the type definition is a simple type definition, ..."
26211: * (3.1.3) "If clause 3.2 of Element Locally Valid
26212: * (Element) (�3.3.4) did not apply, then the �normalized value�
26213: * must be �valid� with respect to the type definition as defined
26214: * by String Valid (�3.14.4).
26215: */
26216: ret = xmlSchemaVCheckINodeDataType(vctxt,
26217: inode, inode->typeDef, inode->value);
26218: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26219: /*
26220: * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26221: * definition, then the element information item must be
26222: * �valid� with respect to the type definition as per
26223: * Element Locally Valid (Complex Type) (�3.4.4);"
26224: *
26225: * SPEC (cvc-complex-type) (2.2)
26226: * "If the {content type} is a simple type definition, ...
26227: * the �normalized value� of the element information item is
26228: * �valid� with respect to that simple type definition as
26229: * defined by String Valid (�3.14.4)."
26230: */
26231: ret = xmlSchemaVCheckINodeDataType(vctxt,
26232: inode, inode->typeDef->contentTypeDef, inode->value);
26233: }
26234: if (ret != 0) {
26235: if (ret < 0) {
26236: VERROR_INT("xmlSchemaValidatorPopElem",
26237: "calling xmlSchemaVCheckCVCSimpleType()");
26238: goto internal_error;
26239: }
26240: goto end_elem;
26241: }
26242: /*
26243: * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26244: * not applied, all of the following must be true:
26245: */
26246: if ((inode->decl->value != NULL) &&
26247: (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26248:
26249: /*
26250: * TODO: We will need a computed value, when comparison is
26251: * done on computed values.
26252: */
26253: /*
26254: * 5.2.2.1 The element information item must have no element
26255: * information item [children].
26256: */
26257: if (inode->flags &
26258: XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26259: ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26260: VERROR(ret, NULL,
26261: "The content must not containt element nodes since "
26262: "there is a fixed value constraint");
26263: goto end_elem;
26264: } else {
26265: /*
26266: * 5.2.2.2 The appropriate case among the following must
26267: * be true:
26268: */
26269: if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26270: /*
26271: * 5.2.2.2.1 If the {content type} of the �actual type
26272: * definition� is mixed, then the *initial value* of the
26273: * item must match the canonical lexical representation
26274: * of the {value constraint} value.
26275: *
26276: * ... the *initial value* of an element information
26277: * item is the string composed of, in order, the
26278: * [character code] of each character information item in
26279: * the [children] of that element information item.
26280: */
26281: if (! xmlStrEqual(inode->value, inode->decl->value)){
26282: /*
26283: * VAL TODO: Report invalid & expected values as well.
26284: * VAL TODO: Implement the canonical stuff.
26285: */
26286: ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26287: xmlSchemaCustomErr(ACTXT_CAST vctxt,
26288: ret, NULL, NULL,
26289: "The initial value '%s' does not match the fixed "
26290: "value constraint '%s'",
26291: inode->value, inode->decl->value);
26292: goto end_elem;
26293: }
26294: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26295: /*
26296: * 5.2.2.2.2 If the {content type} of the �actual type
26297: * definition� is a simple type definition, then the
26298: * *actual value* of the item must match the canonical
26299: * lexical representation of the {value constraint} value.
26300: */
26301: /*
26302: * VAL TODO: *actual value* is the normalized value, impl.
26303: * this.
26304: * VAL TODO: Report invalid & expected values as well.
26305: * VAL TODO: Implement a comparison with the computed values.
26306: */
26307: if (! xmlStrEqual(inode->value,
26308: inode->decl->value)) {
26309: ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26310: xmlSchemaCustomErr(ACTXT_CAST vctxt,
26311: ret, NULL, NULL,
26312: "The actual value '%s' does not match the fixed "
26313: "value constraint '%s'",
26314: inode->value,
26315: inode->decl->value);
26316: goto end_elem;
26317: }
26318: }
26319: }
26320: }
26321: }
26322:
26323: end_elem:
26324: if (vctxt->depth < 0) {
26325: /* TODO: raise error? */
26326: return (0);
26327: }
26328: if (vctxt->depth == vctxt->skipDepth)
26329: vctxt->skipDepth = -1;
26330: /*
26331: * Evaluate the history of XPath state objects.
26332: */
26333: if (inode->appliedXPath &&
26334: (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26335: goto internal_error;
26336: /*
26337: * MAYBE TODO:
26338: * SPEC (6) "The element information item must be �valid� with
26339: * respect to each of the {identity-constraint definitions} as per
26340: * Identity-constraint Satisfied (�3.11.4)."
26341: */
26342: /*
26343: * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26344: * need to be built in any case.
26345: * We will currently build IDC node-tables and bubble them only if
26346: * keyrefs do exist.
26347: */
26348:
26349: /*
26350: * Add the current IDC target-nodes to the IDC node-tables.
26351: */
26352: if ((inode->idcMatchers != NULL) &&
26353: (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26354: {
26355: if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26356: goto internal_error;
26357: }
26358: /*
26359: * Validate IDC keyrefs.
26360: */
26361: if (vctxt->inode->hasKeyrefs)
26362: if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26363: goto internal_error;
26364: /*
26365: * Merge/free the IDC table.
26366: */
26367: if (inode->idcTable != NULL) {
26368: #ifdef DEBUG_IDC_NODE_TABLE
26369: xmlSchemaDebugDumpIDCTable(stdout,
26370: inode->nsName,
26371: inode->localName,
26372: inode->idcTable);
26373: #endif
26374: if ((vctxt->depth > 0) &&
26375: (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26376: {
26377: /*
26378: * Merge the IDC node table with the table of the parent node.
26379: */
26380: if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26381: goto internal_error;
26382: }
26383: }
26384: /*
26385: * Clear the current ielem.
26386: * VAL TODO: Don't free the PSVI IDC tables if they are
26387: * requested for the PSVI.
26388: */
26389: xmlSchemaClearElemInfo(vctxt, inode);
26390: /*
26391: * Skip further processing if we are on the validation root.
26392: */
26393: if (vctxt->depth == 0) {
26394: vctxt->depth--;
26395: vctxt->inode = NULL;
26396: return (0);
26397: }
26398: /*
26399: * Reset the keyrefDepth if needed.
26400: */
26401: if (vctxt->aidcs != NULL) {
26402: xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26403: do {
26404: if (aidc->keyrefDepth == vctxt->depth) {
26405: /*
26406: * A 'keyrefDepth' of a key/unique IDC matches the current
26407: * depth, this means that we are leaving the scope of the
26408: * top-most keyref IDC which refers to this IDC.
26409: */
26410: aidc->keyrefDepth = -1;
26411: }
26412: aidc = aidc->next;
26413: } while (aidc != NULL);
26414: }
26415: vctxt->depth--;
26416: vctxt->inode = vctxt->elemInfos[vctxt->depth];
26417: /*
26418: * VAL TODO: 7 If the element information item is the �validation root�, it must be
26419: * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26420: */
26421: return (ret);
26422:
26423: internal_error:
26424: vctxt->err = -1;
26425: return (-1);
26426: }
26427:
26428: /*
26429: * 3.4.4 Complex Type Definition Validation Rules
26430: * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26431: */
26432: static int
26433: xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26434: {
26435: xmlSchemaNodeInfoPtr pielem;
26436: xmlSchemaTypePtr ptype;
26437: int ret = 0;
26438:
26439: if (vctxt->depth <= 0) {
26440: VERROR_INT("xmlSchemaValidateChildElem",
26441: "not intended for the validation root");
26442: return (-1);
26443: }
26444: pielem = vctxt->elemInfos[vctxt->depth -1];
26445: if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26446: pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26447: /*
26448: * Handle 'nilled' elements.
26449: */
26450: if (INODE_NILLED(pielem)) {
26451: /*
26452: * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26453: */
26454: ACTIVATE_PARENT_ELEM;
26455: ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26456: VERROR(ret, NULL,
26457: "Neither character nor element content is allowed, "
26458: "because the element was 'nilled'");
26459: ACTIVATE_ELEM;
26460: goto unexpected_elem;
26461: }
26462:
26463: ptype = pielem->typeDef;
26464:
26465: if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26466: /*
26467: * Workaround for "anyType": we have currently no content model
26468: * assigned for "anyType", so handle it explicitely.
26469: * "anyType" has an unbounded, lax "any" wildcard.
26470: */
26471: vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26472: vctxt->inode->localName,
26473: vctxt->inode->nsName);
26474:
26475: if (vctxt->inode->decl == NULL) {
26476: xmlSchemaAttrInfoPtr iattr;
26477: /*
26478: * Process "xsi:type".
26479: * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26480: */
26481: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26482: XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26483: if (iattr != NULL) {
26484: ret = xmlSchemaProcessXSIType(vctxt, iattr,
26485: &(vctxt->inode->typeDef), NULL);
26486: if (ret != 0) {
26487: if (ret == -1) {
26488: VERROR_INT("xmlSchemaValidateChildElem",
26489: "calling xmlSchemaProcessXSIType() to "
26490: "process the attribute 'xsi:nil'");
26491: return (-1);
26492: }
26493: return (ret);
26494: }
26495: } else {
26496: /*
26497: * Fallback to "anyType".
26498: *
26499: * SPEC (cvc-assess-elt)
26500: * "If the item cannot be �strictly assessed�, [...]
26501: * an element information item's schema validity may be laxly
26502: * assessed if its �context-determined declaration� is not
26503: * skip by �validating� with respect to the �ur-type
26504: * definition� as per Element Locally Valid (Type) (�3.3.4)."
26505: */
26506: vctxt->inode->typeDef =
26507: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26508: }
26509: }
26510: return (0);
26511: }
26512:
26513: switch (ptype->contentType) {
26514: case XML_SCHEMA_CONTENT_EMPTY:
26515: /*
26516: * SPEC (2.1) "If the {content type} is empty, then the
26517: * element information item has no character or element
26518: * information item [children]."
26519: */
26520: ACTIVATE_PARENT_ELEM
26521: ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26522: VERROR(ret, NULL,
26523: "Element content is not allowed, "
26524: "because the content type is empty");
26525: ACTIVATE_ELEM
26526: goto unexpected_elem;
26527: break;
26528:
26529: case XML_SCHEMA_CONTENT_MIXED:
26530: case XML_SCHEMA_CONTENT_ELEMENTS: {
26531: xmlRegExecCtxtPtr regexCtxt;
26532: xmlChar *values[10];
26533: int terminal, nbval = 10, nbneg;
26534:
26535: /* VAL TODO: Optimized "anyType" validation.*/
26536:
26537: if (ptype->contModel == NULL) {
26538: VERROR_INT("xmlSchemaValidateChildElem",
26539: "type has elem content but no content model");
26540: return (-1);
26541: }
26542: /*
26543: * Safety belf for evaluation if the cont. model was already
26544: * examined to be invalid.
26545: */
26546: if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26547: VERROR_INT("xmlSchemaValidateChildElem",
26548: "validating elem, but elem content is already invalid");
26549: return (-1);
26550: }
26551:
26552: regexCtxt = pielem->regexCtxt;
26553: if (regexCtxt == NULL) {
26554: /*
26555: * Create the regex context.
26556: */
26557: regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26558: (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26559: vctxt);
26560: if (regexCtxt == NULL) {
26561: VERROR_INT("xmlSchemaValidateChildElem",
26562: "failed to create a regex context");
26563: return (-1);
26564: }
26565: pielem->regexCtxt = regexCtxt;
26566: #ifdef DEBUG_AUTOMATA
26567: xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26568: pielem->localName);
26569: #endif
26570: }
26571:
26572: /*
26573: * SPEC (2.4) "If the {content type} is element-only or mixed,
26574: * then the sequence of the element information item's
26575: * element information item [children], if any, taken in
26576: * order, is �valid� with respect to the {content type}'s
26577: * particle, as defined in Element Sequence Locally Valid
26578: * (Particle) (�3.9.4)."
26579: */
26580: ret = xmlRegExecPushString2(regexCtxt,
26581: vctxt->inode->localName,
26582: vctxt->inode->nsName,
26583: vctxt->inode);
26584: #ifdef DEBUG_AUTOMATA
26585: if (ret < 0)
26586: xmlGenericError(xmlGenericErrorContext,
26587: "AUTOMATON push ERROR for '%s' on '%s'\n",
26588: vctxt->inode->localName, pielem->localName);
26589: else
26590: xmlGenericError(xmlGenericErrorContext,
26591: "AUTOMATON push OK for '%s' on '%s'\n",
26592: vctxt->inode->localName, pielem->localName);
26593: #endif
26594: if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26595: VERROR_INT("xmlSchemaValidateChildElem",
26596: "calling xmlRegExecPushString2()");
26597: return (-1);
26598: }
26599: if (ret < 0) {
26600: xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26601: &values[0], &terminal);
26602: xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26603: XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26604: "This element is not expected",
26605: nbval, nbneg, values);
26606: ret = vctxt->err;
26607: goto unexpected_elem;
26608: } else
26609: ret = 0;
26610: }
26611: break;
26612: case XML_SCHEMA_CONTENT_SIMPLE:
26613: case XML_SCHEMA_CONTENT_BASIC:
26614: ACTIVATE_PARENT_ELEM
26615: if (WXS_IS_COMPLEX(ptype)) {
26616: /*
26617: * SPEC (cvc-complex-type) (2.2)
26618: * "If the {content type} is a simple type definition, then
26619: * the element information item has no element information
26620: * item [children], ..."
26621: */
26622: ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26623: VERROR(ret, NULL, "Element content is not allowed, "
26624: "because the content type is a simple type definition");
26625: } else {
26626: /*
26627: * SPEC (cvc-type) (3.1.2) "The element information item must
26628: * have no element information item [children]."
26629: */
26630: ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26631: VERROR(ret, NULL, "Element content is not allowed, "
26632: "because the type definition is simple");
26633: }
26634: ACTIVATE_ELEM
26635: ret = vctxt->err;
26636: goto unexpected_elem;
26637: break;
26638:
26639: default:
26640: break;
26641: }
26642: return (ret);
26643: unexpected_elem:
26644: /*
26645: * Pop this element and set the skipDepth to skip
26646: * all further content of the parent element.
26647: */
26648: vctxt->skipDepth = vctxt->depth;
26649: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26650: pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26651: return (ret);
26652: }
26653:
26654: #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26655: #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26656: #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26657:
26658: static int
26659: xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26660: int nodeType, const xmlChar *value, int len,
26661: int mode, int *consumed)
26662: {
26663: /*
26664: * Unfortunately we have to duplicate the text sometimes.
26665: * OPTIMIZE: Maybe we could skip it, if:
26666: * 1. content type is simple
26667: * 2. whitespace is "collapse"
26668: * 3. it consists of whitespace only
26669: *
26670: * Process character content.
26671: */
26672: if (consumed != NULL)
26673: *consumed = 0;
26674: if (INODE_NILLED(vctxt->inode)) {
26675: /*
26676: * SPEC cvc-elt (3.3.4 - 3.2.1)
26677: * "The element information item must have no character or
26678: * element information item [children]."
26679: */
26680: VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26681: "Neither character nor element content is allowed "
26682: "because the element is 'nilled'");
26683: return (vctxt->err);
26684: }
26685: /*
26686: * SPEC (2.1) "If the {content type} is empty, then the
26687: * element information item has no character or element
26688: * information item [children]."
26689: */
26690: if (vctxt->inode->typeDef->contentType ==
26691: XML_SCHEMA_CONTENT_EMPTY) {
26692: VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26693: "Character content is not allowed, "
26694: "because the content type is empty");
26695: return (vctxt->err);
26696: }
26697:
26698: if (vctxt->inode->typeDef->contentType ==
26699: XML_SCHEMA_CONTENT_ELEMENTS) {
26700: if ((nodeType != XML_TEXT_NODE) ||
26701: (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26702: /*
26703: * SPEC cvc-complex-type (2.3)
26704: * "If the {content type} is element-only, then the
26705: * element information item has no character information
26706: * item [children] other than those whose [character
26707: * code] is defined as a white space in [XML 1.0 (Second
26708: * Edition)]."
26709: */
26710: VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26711: "Character content other than whitespace is not allowed "
26712: "because the content type is 'element-only'");
26713: return (vctxt->err);
26714: }
26715: return (0);
26716: }
26717:
26718: if ((value == NULL) || (value[0] == 0))
26719: return (0);
26720: /*
26721: * Save the value.
26722: * NOTE that even if the content type is *mixed*, we need the
26723: * *initial value* for default/fixed value constraints.
26724: */
26725: if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26726: ((vctxt->inode->decl == NULL) ||
26727: (vctxt->inode->decl->value == NULL)))
26728: return (0);
26729:
26730: if (vctxt->inode->value == NULL) {
26731: /*
26732: * Set the value.
26733: */
26734: switch (mode) {
26735: case XML_SCHEMA_PUSH_TEXT_PERSIST:
26736: /*
26737: * When working on a tree.
26738: */
26739: vctxt->inode->value = value;
26740: break;
26741: case XML_SCHEMA_PUSH_TEXT_CREATED:
26742: /*
26743: * When working with the reader.
26744: * The value will be freed by the element info.
26745: */
26746: vctxt->inode->value = value;
26747: if (consumed != NULL)
26748: *consumed = 1;
26749: vctxt->inode->flags |=
26750: XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26751: break;
26752: case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26753: /*
26754: * When working with SAX.
26755: * The value will be freed by the element info.
26756: */
26757: if (len != -1)
26758: vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26759: else
26760: vctxt->inode->value = BAD_CAST xmlStrdup(value);
26761: vctxt->inode->flags |=
26762: XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26763: break;
26764: default:
26765: break;
26766: }
26767: } else {
26768: if (len < 0)
26769: len = xmlStrlen(value);
26770: /*
26771: * Concat the value.
26772: */
26773: if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26774: vctxt->inode->value = BAD_CAST xmlStrncat(
26775: (xmlChar *) vctxt->inode->value, value, len);
26776: } else {
26777: vctxt->inode->value =
26778: BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26779: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26780: }
26781: }
26782:
26783: return (0);
26784: }
26785:
26786: static int
26787: xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26788: {
26789: int ret = 0;
26790:
26791: if ((vctxt->skipDepth != -1) &&
26792: (vctxt->depth >= vctxt->skipDepth)) {
26793: VERROR_INT("xmlSchemaValidateElem",
26794: "in skip-state");
26795: goto internal_error;
26796: }
26797: if (vctxt->xsiAssemble) {
26798: /*
26799: * We will stop validation if there was an error during
26800: * dynamic schema construction.
26801: * Note that we simply set @skipDepth to 0, this could
26802: * mean that a streaming document via SAX would be
26803: * still read to the end but it won't be validated any more.
26804: * TODO: If we are sure how to stop the validation at once
26805: * for all input scenarios, then this should be changed to
26806: * instantly stop the validation.
26807: */
26808: ret = xmlSchemaAssembleByXSI(vctxt);
26809: if (ret != 0) {
26810: if (ret == -1)
26811: goto internal_error;
26812: vctxt->skipDepth = 0;
26813: return(ret);
26814: }
26815: /*
26816: * Augment the IDC definitions for the main schema and all imported ones
26817: * NOTE: main schema is the first in the imported list
26818: */
26819: xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
26820: }
26821: if (vctxt->depth > 0) {
26822: /*
26823: * Validate this element against the content model
26824: * of the parent.
26825: */
26826: ret = xmlSchemaValidateChildElem(vctxt);
26827: if (ret != 0) {
26828: if (ret < 0) {
26829: VERROR_INT("xmlSchemaValidateElem",
26830: "calling xmlSchemaStreamValidateChildElement()");
26831: goto internal_error;
26832: }
26833: goto exit;
26834: }
26835: if (vctxt->depth == vctxt->skipDepth)
26836: goto exit;
26837: if ((vctxt->inode->decl == NULL) &&
26838: (vctxt->inode->typeDef == NULL)) {
26839: VERROR_INT("xmlSchemaValidateElem",
26840: "the child element was valid but neither the "
26841: "declaration nor the type was set");
26842: goto internal_error;
26843: }
26844: } else {
26845: /*
26846: * Get the declaration of the validation root.
26847: */
26848: vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26849: vctxt->inode->localName,
26850: vctxt->inode->nsName);
26851: if (vctxt->inode->decl == NULL) {
26852: ret = XML_SCHEMAV_CVC_ELT_1;
26853: VERROR(ret, NULL,
26854: "No matching global declaration available "
26855: "for the validation root");
26856: goto exit;
26857: }
26858: }
26859:
26860: if (vctxt->inode->decl == NULL)
26861: goto type_validation;
26862:
26863: if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26864: int skip;
26865: /*
26866: * Wildcards.
26867: */
26868: ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26869: if (ret != 0) {
26870: if (ret < 0) {
26871: VERROR_INT("xmlSchemaValidateElem",
26872: "calling xmlSchemaValidateElemWildcard()");
26873: goto internal_error;
26874: }
26875: goto exit;
26876: }
26877: if (skip) {
26878: vctxt->skipDepth = vctxt->depth;
26879: goto exit;
26880: }
26881: /*
26882: * The declaration might be set by the wildcard validation,
26883: * when the processContents is "lax" or "strict".
26884: */
26885: if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26886: /*
26887: * Clear the "decl" field to not confuse further processing.
26888: */
26889: vctxt->inode->decl = NULL;
26890: goto type_validation;
26891: }
26892: }
26893: /*
26894: * Validate against the declaration.
26895: */
26896: ret = xmlSchemaValidateElemDecl(vctxt);
26897: if (ret != 0) {
26898: if (ret < 0) {
26899: VERROR_INT("xmlSchemaValidateElem",
26900: "calling xmlSchemaValidateElemDecl()");
26901: goto internal_error;
26902: }
26903: goto exit;
26904: }
26905: /*
26906: * Validate against the type definition.
26907: */
26908: type_validation:
26909:
26910: if (vctxt->inode->typeDef == NULL) {
26911: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26912: ret = XML_SCHEMAV_CVC_TYPE_1;
26913: VERROR(ret, NULL,
26914: "The type definition is absent");
26915: goto exit;
26916: }
26917: if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26918: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26919: ret = XML_SCHEMAV_CVC_TYPE_2;
26920: VERROR(ret, NULL,
26921: "The type definition is abstract");
26922: goto exit;
26923: }
26924: /*
26925: * Evaluate IDCs. Do it here, since new IDC matchers are registered
26926: * during validation against the declaration. This must be done
26927: * _before_ attribute validation.
26928: */
26929: if (vctxt->xpathStates != NULL) {
26930: ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26931: vctxt->inode->appliedXPath = 1;
26932: if (ret == -1) {
26933: VERROR_INT("xmlSchemaValidateElem",
26934: "calling xmlSchemaXPathEvaluate()");
26935: goto internal_error;
26936: }
26937: }
26938: /*
26939: * Validate attributes.
26940: */
26941: if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26942: if ((vctxt->nbAttrInfos != 0) ||
26943: (vctxt->inode->typeDef->attrUses != NULL)) {
26944:
26945: ret = xmlSchemaVAttributesComplex(vctxt);
26946: }
26947: } else if (vctxt->nbAttrInfos != 0) {
26948:
26949: ret = xmlSchemaVAttributesSimple(vctxt);
26950: }
26951: /*
26952: * Clear registered attributes.
26953: */
26954: if (vctxt->nbAttrInfos != 0)
26955: xmlSchemaClearAttrInfos(vctxt);
26956: if (ret == -1) {
26957: VERROR_INT("xmlSchemaValidateElem",
26958: "calling attributes validation");
26959: goto internal_error;
26960: }
26961: /*
26962: * Don't return an error if attributes are invalid on purpose.
26963: */
26964: ret = 0;
26965:
26966: exit:
26967: if (ret != 0)
26968: vctxt->skipDepth = vctxt->depth;
26969: return (ret);
26970: internal_error:
26971: return (-1);
26972: }
26973:
26974: #ifdef XML_SCHEMA_READER_ENABLED
26975: static int
26976: xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26977: {
26978: const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26979: int depth, nodeType, ret = 0, consumed;
26980: xmlSchemaNodeInfoPtr ielem;
26981:
26982: vctxt->depth = -1;
26983: ret = xmlTextReaderRead(vctxt->reader);
26984: /*
26985: * Move to the document element.
26986: */
26987: while (ret == 1) {
26988: nodeType = xmlTextReaderNodeType(vctxt->reader);
26989: if (nodeType == XML_ELEMENT_NODE)
26990: goto root_found;
26991: ret = xmlTextReaderRead(vctxt->reader);
26992: }
26993: goto exit;
26994:
26995: root_found:
26996:
26997: do {
26998: depth = xmlTextReaderDepth(vctxt->reader);
26999: nodeType = xmlTextReaderNodeType(vctxt->reader);
27000:
27001: if (nodeType == XML_ELEMENT_NODE) {
27002:
27003: vctxt->depth++;
27004: if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27005: VERROR_INT("xmlSchemaVReaderWalk",
27006: "calling xmlSchemaValidatorPushElem()");
27007: goto internal_error;
27008: }
27009: ielem = vctxt->inode;
27010: ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27011: ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27012: ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27013: /*
27014: * Is the element empty?
27015: */
27016: ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27017: if (ret == -1) {
27018: VERROR_INT("xmlSchemaVReaderWalk",
27019: "calling xmlTextReaderIsEmptyElement()");
27020: goto internal_error;
27021: }
27022: if (ret) {
27023: ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27024: }
27025: /*
27026: * Register attributes.
27027: */
27028: vctxt->nbAttrInfos = 0;
27029: ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27030: if (ret == -1) {
27031: VERROR_INT("xmlSchemaVReaderWalk",
27032: "calling xmlTextReaderMoveToFirstAttribute()");
27033: goto internal_error;
27034: }
27035: if (ret == 1) {
27036: do {
27037: /*
27038: * VAL TODO: How do we know that the reader works on a
27039: * node tree, to be able to pass a node here?
27040: */
27041: if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27042: (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27043: xmlTextReaderNamespaceUri(vctxt->reader), 1,
27044: xmlTextReaderValue(vctxt->reader), 1) == -1) {
27045:
27046: VERROR_INT("xmlSchemaVReaderWalk",
27047: "calling xmlSchemaValidatorPushAttribute()");
27048: goto internal_error;
27049: }
27050: ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27051: if (ret == -1) {
27052: VERROR_INT("xmlSchemaVReaderWalk",
27053: "calling xmlTextReaderMoveToFirstAttribute()");
27054: goto internal_error;
27055: }
27056: } while (ret == 1);
27057: /*
27058: * Back to element position.
27059: */
27060: ret = xmlTextReaderMoveToElement(vctxt->reader);
27061: if (ret == -1) {
27062: VERROR_INT("xmlSchemaVReaderWalk",
27063: "calling xmlTextReaderMoveToElement()");
27064: goto internal_error;
27065: }
27066: }
27067: /*
27068: * Validate the element.
27069: */
27070: ret= xmlSchemaValidateElem(vctxt);
27071: if (ret != 0) {
27072: if (ret == -1) {
27073: VERROR_INT("xmlSchemaVReaderWalk",
27074: "calling xmlSchemaValidateElem()");
27075: goto internal_error;
27076: }
27077: goto exit;
27078: }
27079: if (vctxt->depth == vctxt->skipDepth) {
27080: int curDepth;
27081: /*
27082: * Skip all content.
27083: */
27084: if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27085: ret = xmlTextReaderRead(vctxt->reader);
27086: curDepth = xmlTextReaderDepth(vctxt->reader);
27087: while ((ret == 1) && (curDepth != depth)) {
27088: ret = xmlTextReaderRead(vctxt->reader);
27089: curDepth = xmlTextReaderDepth(vctxt->reader);
27090: }
27091: if (ret < 0) {
27092: /*
27093: * VAL TODO: A reader error occured; what to do here?
27094: */
27095: ret = 1;
27096: goto exit;
27097: }
27098: }
27099: goto leave_elem;
27100: }
27101: /*
27102: * READER VAL TODO: Is an END_ELEM really never called
27103: * if the elem is empty?
27104: */
27105: if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27106: goto leave_elem;
27107: } else if (nodeType == END_ELEM) {
27108: /*
27109: * Process END of element.
27110: */
27111: leave_elem:
27112: ret = xmlSchemaValidatorPopElem(vctxt);
27113: if (ret != 0) {
27114: if (ret < 0) {
27115: VERROR_INT("xmlSchemaVReaderWalk",
27116: "calling xmlSchemaValidatorPopElem()");
27117: goto internal_error;
27118: }
27119: goto exit;
27120: }
27121: if (vctxt->depth >= 0)
27122: ielem = vctxt->inode;
27123: else
27124: ielem = NULL;
27125: } else if ((nodeType == XML_TEXT_NODE) ||
27126: (nodeType == XML_CDATA_SECTION_NODE) ||
27127: (nodeType == WHTSP) ||
27128: (nodeType == SIGN_WHTSP)) {
27129: /*
27130: * Process character content.
27131: */
27132: xmlChar *value;
27133:
27134: if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27135: nodeType = XML_TEXT_NODE;
27136:
27137: value = xmlTextReaderValue(vctxt->reader);
27138: ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27139: -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27140: if (! consumed)
27141: xmlFree(value);
27142: if (ret == -1) {
27143: VERROR_INT("xmlSchemaVReaderWalk",
27144: "calling xmlSchemaVPushText()");
27145: goto internal_error;
27146: }
27147: } else if ((nodeType == XML_ENTITY_NODE) ||
27148: (nodeType == XML_ENTITY_REF_NODE)) {
27149: /*
27150: * VAL TODO: What to do with entities?
27151: */
27152: TODO
27153: }
27154: /*
27155: * Read next node.
27156: */
27157: ret = xmlTextReaderRead(vctxt->reader);
27158: } while (ret == 1);
27159:
27160: exit:
27161: return (ret);
27162: internal_error:
27163: return (-1);
27164: }
27165: #endif
27166:
27167: /************************************************************************
27168: * *
27169: * SAX validation handlers *
27170: * *
27171: ************************************************************************/
27172:
27173: /*
27174: * Process text content.
27175: */
27176: static void
27177: xmlSchemaSAXHandleText(void *ctx,
27178: const xmlChar * ch,
27179: int len)
27180: {
27181: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27182:
27183: if (vctxt->depth < 0)
27184: return;
27185: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27186: return;
27187: if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27188: vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27189: if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27190: XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27191: VERROR_INT("xmlSchemaSAXHandleCDataSection",
27192: "calling xmlSchemaVPushText()");
27193: vctxt->err = -1;
27194: xmlStopParser(vctxt->parserCtxt);
27195: }
27196: }
27197:
27198: /*
27199: * Process CDATA content.
27200: */
27201: static void
27202: xmlSchemaSAXHandleCDataSection(void *ctx,
27203: const xmlChar * ch,
27204: int len)
27205: {
27206: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27207:
27208: if (vctxt->depth < 0)
27209: return;
27210: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27211: return;
27212: if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27213: vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27214: if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27215: XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27216: VERROR_INT("xmlSchemaSAXHandleCDataSection",
27217: "calling xmlSchemaVPushText()");
27218: vctxt->err = -1;
27219: xmlStopParser(vctxt->parserCtxt);
27220: }
27221: }
27222:
27223: static void
27224: xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27225: const xmlChar * name ATTRIBUTE_UNUSED)
27226: {
27227: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27228:
27229: if (vctxt->depth < 0)
27230: return;
27231: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27232: return;
27233: /* SAX VAL TODO: What to do here? */
27234: TODO
27235: }
27236:
27237: static void
27238: xmlSchemaSAXHandleStartElementNs(void *ctx,
27239: const xmlChar * localname,
27240: const xmlChar * prefix ATTRIBUTE_UNUSED,
27241: const xmlChar * URI,
27242: int nb_namespaces,
27243: const xmlChar ** namespaces,
27244: int nb_attributes,
27245: int nb_defaulted ATTRIBUTE_UNUSED,
27246: const xmlChar ** attributes)
27247: {
27248: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27249: int ret;
27250: xmlSchemaNodeInfoPtr ielem;
27251: int i, j;
27252:
27253: /*
27254: * SAX VAL TODO: What to do with nb_defaulted?
27255: */
27256: /*
27257: * Skip elements if inside a "skip" wildcard or invalid.
27258: */
27259: vctxt->depth++;
27260: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27261: return;
27262: /*
27263: * Push the element.
27264: */
27265: if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27266: VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27267: "calling xmlSchemaValidatorPushElem()");
27268: goto internal_error;
27269: }
27270: ielem = vctxt->inode;
27271: /*
27272: * TODO: Is this OK?
27273: */
27274: ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27275: ielem->localName = localname;
27276: ielem->nsName = URI;
27277: ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27278: /*
27279: * Register namespaces on the elem info.
27280: */
27281: if (nb_namespaces != 0) {
27282: /*
27283: * Although the parser builds its own namespace list,
27284: * we have no access to it, so we'll use an own one.
27285: */
27286: for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27287: /*
27288: * Store prefix and namespace name.
27289: */
27290: if (ielem->nsBindings == NULL) {
27291: ielem->nsBindings =
27292: (const xmlChar **) xmlMalloc(10 *
27293: sizeof(const xmlChar *));
27294: if (ielem->nsBindings == NULL) {
27295: xmlSchemaVErrMemory(vctxt,
27296: "allocating namespace bindings for SAX validation",
27297: NULL);
27298: goto internal_error;
27299: }
27300: ielem->nbNsBindings = 0;
27301: ielem->sizeNsBindings = 5;
27302: } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27303: ielem->sizeNsBindings *= 2;
27304: ielem->nsBindings =
27305: (const xmlChar **) xmlRealloc(
27306: (void *) ielem->nsBindings,
27307: ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27308: if (ielem->nsBindings == NULL) {
27309: xmlSchemaVErrMemory(vctxt,
27310: "re-allocating namespace bindings for SAX validation",
27311: NULL);
27312: goto internal_error;
27313: }
27314: }
27315:
27316: ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27317: if (namespaces[j+1][0] == 0) {
27318: /*
27319: * Handle xmlns="".
27320: */
27321: ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27322: } else
27323: ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27324: namespaces[j+1];
27325: ielem->nbNsBindings++;
27326: }
27327: }
27328: /*
27329: * Register attributes.
27330: * SAX VAL TODO: We are not adding namespace declaration
27331: * attributes yet.
27332: */
27333: if (nb_attributes != 0) {
27334: xmlChar *value;
27335:
27336: for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27337: /*
27338: * Duplicate the value.
27339: */
27340: value = xmlStrndup(attributes[j+3],
27341: attributes[j+4] - attributes[j+3]);
27342: /*
27343: * TODO: Set the node line.
27344: */
27345: ret = xmlSchemaValidatorPushAttribute(vctxt,
27346: NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27347: value, 1);
27348: if (ret == -1) {
27349: VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27350: "calling xmlSchemaValidatorPushAttribute()");
27351: goto internal_error;
27352: }
27353: }
27354: }
27355: /*
27356: * Validate the element.
27357: */
27358: ret = xmlSchemaValidateElem(vctxt);
27359: if (ret != 0) {
27360: if (ret == -1) {
27361: VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27362: "calling xmlSchemaValidateElem()");
27363: goto internal_error;
27364: }
27365: goto exit;
27366: }
27367:
27368: exit:
27369: return;
27370: internal_error:
27371: vctxt->err = -1;
27372: xmlStopParser(vctxt->parserCtxt);
27373: return;
27374: }
27375:
27376: static void
27377: xmlSchemaSAXHandleEndElementNs(void *ctx,
27378: const xmlChar * localname ATTRIBUTE_UNUSED,
27379: const xmlChar * prefix ATTRIBUTE_UNUSED,
27380: const xmlChar * URI ATTRIBUTE_UNUSED)
27381: {
27382: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27383: int res;
27384:
27385: /*
27386: * Skip elements if inside a "skip" wildcard or if invalid.
27387: */
27388: if (vctxt->skipDepth != -1) {
27389: if (vctxt->depth > vctxt->skipDepth) {
27390: vctxt->depth--;
27391: return;
27392: } else
27393: vctxt->skipDepth = -1;
27394: }
27395: /*
27396: * SAX VAL TODO: Just a temporary check.
27397: */
27398: if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27399: (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27400: VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27401: "elem pop mismatch");
27402: }
27403: res = xmlSchemaValidatorPopElem(vctxt);
27404: if (res != 0) {
27405: if (res < 0) {
27406: VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27407: "calling xmlSchemaValidatorPopElem()");
27408: goto internal_error;
27409: }
27410: goto exit;
27411: }
27412: exit:
27413: return;
27414: internal_error:
27415: vctxt->err = -1;
27416: xmlStopParser(vctxt->parserCtxt);
27417: return;
27418: }
27419:
27420: /************************************************************************
27421: * *
27422: * Validation interfaces *
27423: * *
27424: ************************************************************************/
27425:
27426: /**
27427: * xmlSchemaNewValidCtxt:
27428: * @schema: a precompiled XML Schemas
27429: *
27430: * Create an XML Schemas validation context based on the given schema.
27431: *
27432: * Returns the validation context or NULL in case of error
27433: */
27434: xmlSchemaValidCtxtPtr
27435: xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27436: {
27437: xmlSchemaValidCtxtPtr ret;
27438:
27439: ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27440: if (ret == NULL) {
27441: xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27442: return (NULL);
27443: }
27444: memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27445: ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27446: ret->dict = xmlDictCreate();
27447: ret->nodeQNames = xmlSchemaItemListCreate();
27448: ret->schema = schema;
27449: return (ret);
27450: }
27451:
27452: /**
27453: * xmlSchemaClearValidCtxt:
27454: * @ctxt: the schema validation context
27455: *
27456: * Free the resources associated to the schema validation context;
27457: * leaves some fields alive intended for reuse of the context.
27458: */
27459: static void
27460: xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27461: {
27462: if (vctxt == NULL)
27463: return;
27464:
27465: /*
27466: * TODO: Should we clear the flags?
27467: * Might be problematic if one reuses the context
27468: * and assumes that the options remain the same.
27469: */
27470: vctxt->flags = 0;
27471: vctxt->validationRoot = NULL;
27472: vctxt->doc = NULL;
27473: #ifdef LIBXML_READER_ENABLED
27474: vctxt->reader = NULL;
27475: #endif
27476: vctxt->hasKeyrefs = 0;
27477:
27478: if (vctxt->value != NULL) {
27479: xmlSchemaFreeValue(vctxt->value);
27480: vctxt->value = NULL;
27481: }
27482: /*
27483: * Augmented IDC information.
27484: */
27485: if (vctxt->aidcs != NULL) {
27486: xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27487: do {
27488: next = cur->next;
27489: xmlFree(cur);
27490: cur = next;
27491: } while (cur != NULL);
27492: vctxt->aidcs = NULL;
27493: }
27494: if (vctxt->idcMatcherCache != NULL) {
27495: xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27496:
27497: while (matcher) {
27498: tmp = matcher;
27499: matcher = matcher->nextCached;
27500: xmlSchemaIDCFreeMatcherList(tmp);
27501: }
27502: vctxt->idcMatcherCache = NULL;
27503: }
27504:
27505:
27506: if (vctxt->idcNodes != NULL) {
27507: int i;
27508: xmlSchemaPSVIIDCNodePtr item;
27509:
27510: for (i = 0; i < vctxt->nbIdcNodes; i++) {
27511: item = vctxt->idcNodes[i];
27512: xmlFree(item->keys);
27513: xmlFree(item);
27514: }
27515: xmlFree(vctxt->idcNodes);
27516: vctxt->idcNodes = NULL;
27517: vctxt->nbIdcNodes = 0;
27518: vctxt->sizeIdcNodes = 0;
27519: }
27520: /*
27521: * Note that we won't delete the XPath state pool here.
27522: */
27523: if (vctxt->xpathStates != NULL) {
27524: xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27525: vctxt->xpathStates = NULL;
27526: }
27527: /*
27528: * Attribute info.
27529: */
27530: if (vctxt->nbAttrInfos != 0) {
27531: xmlSchemaClearAttrInfos(vctxt);
27532: }
27533: /*
27534: * Element info.
27535: */
27536: if (vctxt->elemInfos != NULL) {
27537: int i;
27538: xmlSchemaNodeInfoPtr ei;
27539:
27540: for (i = 0; i < vctxt->sizeElemInfos; i++) {
27541: ei = vctxt->elemInfos[i];
27542: if (ei == NULL)
27543: break;
27544: xmlSchemaClearElemInfo(vctxt, ei);
27545: }
27546: }
27547: xmlSchemaItemListClear(vctxt->nodeQNames);
27548: /* Recreate the dict. */
27549: xmlDictFree(vctxt->dict);
27550: /*
27551: * TODO: Is is save to recreate it? Do we have a scenario
27552: * where the user provides the dict?
27553: */
27554: vctxt->dict = xmlDictCreate();
27555: }
27556:
27557: /**
27558: * xmlSchemaFreeValidCtxt:
27559: * @ctxt: the schema validation context
27560: *
27561: * Free the resources associated to the schema validation context
27562: */
27563: void
27564: xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27565: {
27566: if (ctxt == NULL)
27567: return;
27568: if (ctxt->value != NULL)
27569: xmlSchemaFreeValue(ctxt->value);
27570: if (ctxt->pctxt != NULL)
27571: xmlSchemaFreeParserCtxt(ctxt->pctxt);
27572: if (ctxt->idcNodes != NULL) {
27573: int i;
27574: xmlSchemaPSVIIDCNodePtr item;
27575:
27576: for (i = 0; i < ctxt->nbIdcNodes; i++) {
27577: item = ctxt->idcNodes[i];
27578: xmlFree(item->keys);
27579: xmlFree(item);
27580: }
27581: xmlFree(ctxt->idcNodes);
27582: }
27583: if (ctxt->idcKeys != NULL) {
27584: int i;
27585: for (i = 0; i < ctxt->nbIdcKeys; i++)
27586: xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27587: xmlFree(ctxt->idcKeys);
27588: }
27589:
27590: if (ctxt->xpathStates != NULL) {
27591: xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27592: ctxt->xpathStates = NULL;
27593: }
27594: if (ctxt->xpathStatePool != NULL) {
27595: xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27596: ctxt->xpathStatePool = NULL;
27597: }
27598:
27599: /*
27600: * Augmented IDC information.
27601: */
27602: if (ctxt->aidcs != NULL) {
27603: xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27604: do {
27605: next = cur->next;
27606: xmlFree(cur);
27607: cur = next;
27608: } while (cur != NULL);
27609: }
27610: if (ctxt->attrInfos != NULL) {
27611: int i;
27612: xmlSchemaAttrInfoPtr attr;
27613:
27614: /* Just a paranoid call to the cleanup. */
27615: if (ctxt->nbAttrInfos != 0)
27616: xmlSchemaClearAttrInfos(ctxt);
27617: for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27618: attr = ctxt->attrInfos[i];
27619: xmlFree(attr);
27620: }
27621: xmlFree(ctxt->attrInfos);
27622: }
27623: if (ctxt->elemInfos != NULL) {
27624: int i;
27625: xmlSchemaNodeInfoPtr ei;
27626:
27627: for (i = 0; i < ctxt->sizeElemInfos; i++) {
27628: ei = ctxt->elemInfos[i];
27629: if (ei == NULL)
27630: break;
27631: xmlSchemaClearElemInfo(ctxt, ei);
27632: xmlFree(ei);
27633: }
27634: xmlFree(ctxt->elemInfos);
27635: }
27636: if (ctxt->nodeQNames != NULL)
27637: xmlSchemaItemListFree(ctxt->nodeQNames);
27638: if (ctxt->dict != NULL)
27639: xmlDictFree(ctxt->dict);
27640: xmlFree(ctxt);
27641: }
27642:
27643: /**
27644: * xmlSchemaIsValid:
27645: * @ctxt: the schema validation context
27646: *
27647: * Check if any error was detected during validation.
27648: *
27649: * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27650: * of internal error.
27651: */
27652: int
27653: xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27654: {
27655: if (ctxt == NULL)
27656: return(-1);
27657: return(ctxt->err == 0);
27658: }
27659:
27660: /**
27661: * xmlSchemaSetValidErrors:
27662: * @ctxt: a schema validation context
27663: * @err: the error function
27664: * @warn: the warning function
27665: * @ctx: the functions context
27666: *
27667: * Set the error and warning callback informations
27668: */
27669: void
27670: xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27671: xmlSchemaValidityErrorFunc err,
27672: xmlSchemaValidityWarningFunc warn, void *ctx)
27673: {
27674: if (ctxt == NULL)
27675: return;
27676: ctxt->error = err;
27677: ctxt->warning = warn;
27678: ctxt->errCtxt = ctx;
27679: if (ctxt->pctxt != NULL)
27680: xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27681: }
27682:
27683: /**
27684: * xmlSchemaSetValidStructuredErrors:
27685: * @ctxt: a schema validation context
27686: * @serror: the structured error function
27687: * @ctx: the functions context
27688: *
27689: * Set the structured error callback
27690: */
27691: void
27692: xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27693: xmlStructuredErrorFunc serror, void *ctx)
27694: {
27695: if (ctxt == NULL)
27696: return;
27697: ctxt->serror = serror;
27698: ctxt->error = NULL;
27699: ctxt->warning = NULL;
27700: ctxt->errCtxt = ctx;
27701: if (ctxt->pctxt != NULL)
27702: xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27703: }
27704:
27705: /**
27706: * xmlSchemaGetValidErrors:
27707: * @ctxt: a XML-Schema validation context
27708: * @err: the error function result
27709: * @warn: the warning function result
27710: * @ctx: the functions context result
27711: *
27712: * Get the error and warning callback informations
27713: *
27714: * Returns -1 in case of error and 0 otherwise
27715: */
27716: int
27717: xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27718: xmlSchemaValidityErrorFunc * err,
27719: xmlSchemaValidityWarningFunc * warn, void **ctx)
27720: {
27721: if (ctxt == NULL)
27722: return (-1);
27723: if (err != NULL)
27724: *err = ctxt->error;
27725: if (warn != NULL)
27726: *warn = ctxt->warning;
27727: if (ctx != NULL)
27728: *ctx = ctxt->errCtxt;
27729: return (0);
27730: }
27731:
27732:
27733: /**
27734: * xmlSchemaSetValidOptions:
27735: * @ctxt: a schema validation context
27736: * @options: a combination of xmlSchemaValidOption
27737: *
27738: * Sets the options to be used during the validation.
27739: *
27740: * Returns 0 in case of success, -1 in case of an
27741: * API error.
27742: */
27743: int
27744: xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27745: int options)
27746:
27747: {
27748: int i;
27749:
27750: if (ctxt == NULL)
27751: return (-1);
27752: /*
27753: * WARNING: Change the start value if adding to the
27754: * xmlSchemaValidOption.
27755: * TODO: Is there an other, more easy to maintain,
27756: * way?
27757: */
27758: for (i = 1; i < (int) sizeof(int) * 8; i++) {
27759: if (options & 1<<i)
27760: return (-1);
27761: }
27762: ctxt->options = options;
27763: return (0);
27764: }
27765:
27766: /**
27767: * xmlSchemaValidCtxtGetOptions:
27768: * @ctxt: a schema validation context
27769: *
27770: * Get the validation context options.
27771: *
27772: * Returns the option combination or -1 on error.
27773: */
27774: int
27775: xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27776:
27777: {
27778: if (ctxt == NULL)
27779: return (-1);
27780: else
27781: return (ctxt->options);
27782: }
27783:
27784: static int
27785: xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27786: {
27787: xmlAttrPtr attr;
27788: int ret = 0;
27789: xmlSchemaNodeInfoPtr ielem = NULL;
27790: xmlNodePtr node, valRoot;
27791: const xmlChar *nsName;
27792:
27793: /* DOC VAL TODO: Move this to the start function. */
27794: valRoot = xmlDocGetRootElement(vctxt->doc);
27795: if (valRoot == NULL) {
27796: /* VAL TODO: Error code? */
27797: VERROR(1, NULL, "The document has no document element");
27798: return (1);
27799: }
27800: vctxt->depth = -1;
27801: vctxt->validationRoot = valRoot;
27802: node = valRoot;
27803: while (node != NULL) {
27804: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27805: goto next_sibling;
27806: if (node->type == XML_ELEMENT_NODE) {
27807:
27808: /*
27809: * Init the node-info.
27810: */
27811: vctxt->depth++;
27812: if (xmlSchemaValidatorPushElem(vctxt) == -1)
27813: goto internal_error;
27814: ielem = vctxt->inode;
27815: ielem->node = node;
27816: ielem->nodeLine = node->line;
27817: ielem->localName = node->name;
27818: if (node->ns != NULL)
27819: ielem->nsName = node->ns->href;
27820: ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27821: /*
27822: * Register attributes.
27823: * DOC VAL TODO: We do not register namespace declaration
27824: * attributes yet.
27825: */
27826: vctxt->nbAttrInfos = 0;
27827: if (node->properties != NULL) {
27828: attr = node->properties;
27829: do {
27830: if (attr->ns != NULL)
27831: nsName = attr->ns->href;
27832: else
27833: nsName = NULL;
27834: ret = xmlSchemaValidatorPushAttribute(vctxt,
27835: (xmlNodePtr) attr,
27836: /*
27837: * Note that we give it the line number of the
27838: * parent element.
27839: */
27840: ielem->nodeLine,
27841: attr->name, nsName, 0,
27842: xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27843: if (ret == -1) {
27844: VERROR_INT("xmlSchemaDocWalk",
27845: "calling xmlSchemaValidatorPushAttribute()");
27846: goto internal_error;
27847: }
27848: attr = attr->next;
27849: } while (attr);
27850: }
27851: /*
27852: * Validate the element.
27853: */
27854: ret = xmlSchemaValidateElem(vctxt);
27855: if (ret != 0) {
27856: if (ret == -1) {
27857: VERROR_INT("xmlSchemaDocWalk",
27858: "calling xmlSchemaValidateElem()");
27859: goto internal_error;
27860: }
27861: /*
27862: * Don't stop validation; just skip the content
27863: * of this element.
27864: */
27865: goto leave_node;
27866: }
27867: if ((vctxt->skipDepth != -1) &&
27868: (vctxt->depth >= vctxt->skipDepth))
27869: goto leave_node;
27870: } else if ((node->type == XML_TEXT_NODE) ||
27871: (node->type == XML_CDATA_SECTION_NODE)) {
27872: /*
27873: * Process character content.
27874: */
27875: if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27876: ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27877: ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27878: -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27879: if (ret < 0) {
27880: VERROR_INT("xmlSchemaVDocWalk",
27881: "calling xmlSchemaVPushText()");
27882: goto internal_error;
27883: }
27884: /*
27885: * DOC VAL TODO: Should we skip further validation of the
27886: * element content here?
27887: */
27888: } else if ((node->type == XML_ENTITY_NODE) ||
27889: (node->type == XML_ENTITY_REF_NODE)) {
27890: /*
27891: * DOC VAL TODO: What to do with entities?
27892: */
27893: VERROR_INT("xmlSchemaVDocWalk",
27894: "there is at least one entity reference in the node-tree "
27895: "currently being validated. Processing of entities with "
27896: "this XML Schema processor is not supported (yet). Please "
27897: "substitute entities before validation.");
27898: goto internal_error;
27899: } else {
27900: goto leave_node;
27901: /*
27902: * DOC VAL TODO: XInclude nodes, etc.
27903: */
27904: }
27905: /*
27906: * Walk the doc.
27907: */
27908: if (node->children != NULL) {
27909: node = node->children;
27910: continue;
27911: }
27912: leave_node:
27913: if (node->type == XML_ELEMENT_NODE) {
27914: /*
27915: * Leaving the scope of an element.
27916: */
27917: if (node != vctxt->inode->node) {
27918: VERROR_INT("xmlSchemaVDocWalk",
27919: "element position mismatch");
27920: goto internal_error;
27921: }
27922: ret = xmlSchemaValidatorPopElem(vctxt);
27923: if (ret != 0) {
27924: if (ret < 0) {
27925: VERROR_INT("xmlSchemaVDocWalk",
27926: "calling xmlSchemaValidatorPopElem()");
27927: goto internal_error;
27928: }
27929: }
27930: if (node == valRoot)
27931: goto exit;
27932: }
27933: next_sibling:
27934: if (node->next != NULL)
27935: node = node->next;
27936: else {
27937: node = node->parent;
27938: goto leave_node;
27939: }
27940: }
27941:
27942: exit:
27943: return (ret);
27944: internal_error:
27945: return (-1);
27946: }
27947:
27948: static int
27949: xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27950: /*
27951: * Some initialization.
27952: */
27953: vctxt->err = 0;
27954: vctxt->nberrors = 0;
27955: vctxt->depth = -1;
27956: vctxt->skipDepth = -1;
27957: vctxt->xsiAssemble = 0;
27958: vctxt->hasKeyrefs = 0;
27959: #ifdef ENABLE_IDC_NODE_TABLES_TEST
27960: vctxt->createIDCNodeTables = 1;
27961: #else
27962: vctxt->createIDCNodeTables = 0;
27963: #endif
27964: /*
27965: * Create a schema + parser if necessary.
27966: */
27967: if (vctxt->schema == NULL) {
27968: xmlSchemaParserCtxtPtr pctxt;
27969:
27970: vctxt->xsiAssemble = 1;
27971: /*
27972: * If not schema was given then we will create a schema
27973: * dynamically using XSI schema locations.
27974: *
27975: * Create the schema parser context.
27976: */
27977: if ((vctxt->pctxt == NULL) &&
27978: (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27979: return (-1);
27980: pctxt = vctxt->pctxt;
27981: pctxt->xsiAssemble = 1;
27982: /*
27983: * Create the schema.
27984: */
27985: vctxt->schema = xmlSchemaNewSchema(pctxt);
27986: if (vctxt->schema == NULL)
27987: return (-1);
27988: /*
27989: * Create the schema construction context.
27990: */
27991: pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27992: if (pctxt->constructor == NULL)
27993: return(-1);
27994: pctxt->constructor->mainSchema = vctxt->schema;
27995: /*
27996: * Take ownership of the constructor to be able to free it.
27997: */
27998: pctxt->ownsConstructor = 1;
27999: }
28000: /*
28001: * Augment the IDC definitions for the main schema and all imported ones
28002: * NOTE: main schema if the first in the imported list
28003: */
28004: xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
28005:
28006: return(0);
28007: }
28008:
28009: static void
28010: xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28011: if (vctxt->xsiAssemble) {
28012: if (vctxt->schema != NULL) {
28013: xmlSchemaFree(vctxt->schema);
28014: vctxt->schema = NULL;
28015: }
28016: }
28017: xmlSchemaClearValidCtxt(vctxt);
28018: }
28019:
28020: static int
28021: xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28022: {
28023: int ret = 0;
28024:
28025: if (xmlSchemaPreRun(vctxt) < 0)
28026: return(-1);
28027:
28028: if (vctxt->doc != NULL) {
28029: /*
28030: * Tree validation.
28031: */
28032: ret = xmlSchemaVDocWalk(vctxt);
28033: #ifdef LIBXML_READER_ENABLED
28034: } else if (vctxt->reader != NULL) {
28035: /*
28036: * XML Reader validation.
28037: */
28038: #ifdef XML_SCHEMA_READER_ENABLED
28039: ret = xmlSchemaVReaderWalk(vctxt);
28040: #endif
28041: #endif
28042: } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28043: /*
28044: * SAX validation.
28045: */
28046: ret = xmlParseDocument(vctxt->parserCtxt);
28047: } else {
28048: VERROR_INT("xmlSchemaVStart",
28049: "no instance to validate");
28050: ret = -1;
28051: }
28052:
28053: xmlSchemaPostRun(vctxt);
28054: if (ret == 0)
28055: ret = vctxt->err;
28056: return (ret);
28057: }
28058:
28059: /**
28060: * xmlSchemaValidateOneElement:
28061: * @ctxt: a schema validation context
28062: * @elem: an element node
28063: *
28064: * Validate a branch of a tree, starting with the given @elem.
28065: *
28066: * Returns 0 if the element and its subtree is valid, a positive error
28067: * code number otherwise and -1 in case of an internal or API error.
28068: */
28069: int
28070: xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28071: {
28072: if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28073: return (-1);
28074:
28075: if (ctxt->schema == NULL)
28076: return (-1);
28077:
28078: ctxt->doc = elem->doc;
28079: ctxt->node = elem;
28080: ctxt->validationRoot = elem;
28081: return(xmlSchemaVStart(ctxt));
28082: }
28083:
28084: /**
28085: * xmlSchemaValidateDoc:
28086: * @ctxt: a schema validation context
28087: * @doc: a parsed document tree
28088: *
28089: * Validate a document tree in memory.
28090: *
28091: * Returns 0 if the document is schemas valid, a positive error code
28092: * number otherwise and -1 in case of internal or API error.
28093: */
28094: int
28095: xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28096: {
28097: if ((ctxt == NULL) || (doc == NULL))
28098: return (-1);
28099:
28100: ctxt->doc = doc;
28101: ctxt->node = xmlDocGetRootElement(doc);
28102: if (ctxt->node == NULL) {
28103: xmlSchemaCustomErr(ACTXT_CAST ctxt,
28104: XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28105: (xmlNodePtr) doc, NULL,
28106: "The document has no document element", NULL, NULL);
28107: return (ctxt->err);
28108: }
28109: ctxt->validationRoot = ctxt->node;
28110: return (xmlSchemaVStart(ctxt));
28111: }
28112:
28113:
28114: /************************************************************************
28115: * *
28116: * Function and data for SAX streaming API *
28117: * *
28118: ************************************************************************/
28119: typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28120: typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28121:
28122: struct _xmlSchemaSplitSAXData {
28123: xmlSAXHandlerPtr user_sax;
28124: void *user_data;
28125: xmlSchemaValidCtxtPtr ctxt;
28126: xmlSAXHandlerPtr schemas_sax;
28127: };
28128:
28129: #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28130:
28131: struct _xmlSchemaSAXPlug {
28132: unsigned int magic;
28133:
28134: /* the original callbacks informations */
28135: xmlSAXHandlerPtr *user_sax_ptr;
28136: xmlSAXHandlerPtr user_sax;
28137: void **user_data_ptr;
28138: void *user_data;
28139:
28140: /* the block plugged back and validation informations */
28141: xmlSAXHandler schemas_sax;
28142: xmlSchemaValidCtxtPtr ctxt;
28143: };
28144:
28145: /* All those functions just bounces to the user provided SAX handlers */
28146: static void
28147: internalSubsetSplit(void *ctx, const xmlChar *name,
28148: const xmlChar *ExternalID, const xmlChar *SystemID)
28149: {
28150: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28151: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28152: (ctxt->user_sax->internalSubset != NULL))
28153: ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28154: SystemID);
28155: }
28156:
28157: static int
28158: isStandaloneSplit(void *ctx)
28159: {
28160: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28161: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28162: (ctxt->user_sax->isStandalone != NULL))
28163: return(ctxt->user_sax->isStandalone(ctxt->user_data));
28164: return(0);
28165: }
28166:
28167: static int
28168: hasInternalSubsetSplit(void *ctx)
28169: {
28170: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28171: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28172: (ctxt->user_sax->hasInternalSubset != NULL))
28173: return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28174: return(0);
28175: }
28176:
28177: static int
28178: hasExternalSubsetSplit(void *ctx)
28179: {
28180: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28181: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28182: (ctxt->user_sax->hasExternalSubset != NULL))
28183: return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28184: return(0);
28185: }
28186:
28187: static void
28188: externalSubsetSplit(void *ctx, const xmlChar *name,
28189: const xmlChar *ExternalID, const xmlChar *SystemID)
28190: {
28191: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28192: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28193: (ctxt->user_sax->externalSubset != NULL))
28194: ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28195: SystemID);
28196: }
28197:
28198: static xmlParserInputPtr
28199: resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28200: {
28201: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28202: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28203: (ctxt->user_sax->resolveEntity != NULL))
28204: return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28205: systemId));
28206: return(NULL);
28207: }
28208:
28209: static xmlEntityPtr
28210: getEntitySplit(void *ctx, const xmlChar *name)
28211: {
28212: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28213: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28214: (ctxt->user_sax->getEntity != NULL))
28215: return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28216: return(NULL);
28217: }
28218:
28219: static xmlEntityPtr
28220: getParameterEntitySplit(void *ctx, const xmlChar *name)
28221: {
28222: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28223: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28224: (ctxt->user_sax->getParameterEntity != NULL))
28225: return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28226: return(NULL);
28227: }
28228:
28229:
28230: static void
28231: entityDeclSplit(void *ctx, const xmlChar *name, int type,
28232: const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28233: {
28234: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28235: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28236: (ctxt->user_sax->entityDecl != NULL))
28237: ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28238: systemId, content);
28239: }
28240:
28241: static void
28242: attributeDeclSplit(void *ctx, const xmlChar * elem,
28243: const xmlChar * name, int type, int def,
28244: const xmlChar * defaultValue, xmlEnumerationPtr tree)
28245: {
28246: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28247: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28248: (ctxt->user_sax->attributeDecl != NULL)) {
28249: ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28250: def, defaultValue, tree);
28251: } else {
28252: xmlFreeEnumeration(tree);
28253: }
28254: }
28255:
28256: static void
28257: elementDeclSplit(void *ctx, const xmlChar *name, int type,
28258: xmlElementContentPtr content)
28259: {
28260: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28261: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28262: (ctxt->user_sax->elementDecl != NULL))
28263: ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28264: }
28265:
28266: static void
28267: notationDeclSplit(void *ctx, const xmlChar *name,
28268: const xmlChar *publicId, const xmlChar *systemId)
28269: {
28270: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28271: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28272: (ctxt->user_sax->notationDecl != NULL))
28273: ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28274: systemId);
28275: }
28276:
28277: static void
28278: unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28279: const xmlChar *publicId, const xmlChar *systemId,
28280: const xmlChar *notationName)
28281: {
28282: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28283: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28284: (ctxt->user_sax->unparsedEntityDecl != NULL))
28285: ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28286: systemId, notationName);
28287: }
28288:
28289: static void
28290: setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28291: {
28292: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28293: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28294: (ctxt->user_sax->setDocumentLocator != NULL))
28295: ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28296: }
28297:
28298: static void
28299: startDocumentSplit(void *ctx)
28300: {
28301: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28302: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28303: (ctxt->user_sax->startDocument != NULL))
28304: ctxt->user_sax->startDocument(ctxt->user_data);
28305: }
28306:
28307: static void
28308: endDocumentSplit(void *ctx)
28309: {
28310: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28311: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28312: (ctxt->user_sax->endDocument != NULL))
28313: ctxt->user_sax->endDocument(ctxt->user_data);
28314: }
28315:
28316: static void
28317: processingInstructionSplit(void *ctx, const xmlChar *target,
28318: const xmlChar *data)
28319: {
28320: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28321: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28322: (ctxt->user_sax->processingInstruction != NULL))
28323: ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28324: }
28325:
28326: static void
28327: commentSplit(void *ctx, const xmlChar *value)
28328: {
28329: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28330: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28331: (ctxt->user_sax->comment != NULL))
28332: ctxt->user_sax->comment(ctxt->user_data, value);
28333: }
28334:
28335: /*
28336: * Varargs error callbacks to the user application, harder ...
28337: */
28338:
28339: static void XMLCDECL
28340: warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28341: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28342: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28343: (ctxt->user_sax->warning != NULL)) {
28344: TODO
28345: }
28346: }
28347: static void XMLCDECL
28348: errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28349: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28350: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28351: (ctxt->user_sax->error != NULL)) {
28352: TODO
28353: }
28354: }
28355: static void XMLCDECL
28356: fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28357: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28358: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28359: (ctxt->user_sax->fatalError != NULL)) {
28360: TODO
28361: }
28362: }
28363:
28364: /*
28365: * Those are function where both the user handler and the schemas handler
28366: * need to be called.
28367: */
28368: static void
28369: charactersSplit(void *ctx, const xmlChar *ch, int len)
28370: {
28371: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28372: if (ctxt == NULL)
28373: return;
28374: if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28375: ctxt->user_sax->characters(ctxt->user_data, ch, len);
28376: if (ctxt->ctxt != NULL)
28377: xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28378: }
28379:
28380: static void
28381: ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28382: {
28383: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28384: if (ctxt == NULL)
28385: return;
28386: if ((ctxt->user_sax != NULL) &&
28387: (ctxt->user_sax->ignorableWhitespace != NULL))
28388: ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28389: if (ctxt->ctxt != NULL)
28390: xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28391: }
28392:
28393: static void
28394: cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28395: {
28396: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28397: if (ctxt == NULL)
28398: return;
28399: if ((ctxt->user_sax != NULL) &&
28400: (ctxt->user_sax->cdataBlock != NULL))
28401: ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28402: if (ctxt->ctxt != NULL)
28403: xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28404: }
28405:
28406: static void
28407: referenceSplit(void *ctx, const xmlChar *name)
28408: {
28409: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28410: if (ctxt == NULL)
28411: return;
28412: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28413: (ctxt->user_sax->reference != NULL))
28414: ctxt->user_sax->reference(ctxt->user_data, name);
28415: if (ctxt->ctxt != NULL)
28416: xmlSchemaSAXHandleReference(ctxt->user_data, name);
28417: }
28418:
28419: static void
28420: startElementNsSplit(void *ctx, const xmlChar * localname,
28421: const xmlChar * prefix, const xmlChar * URI,
28422: int nb_namespaces, const xmlChar ** namespaces,
28423: int nb_attributes, int nb_defaulted,
28424: const xmlChar ** attributes) {
28425: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28426: if (ctxt == NULL)
28427: return;
28428: if ((ctxt->user_sax != NULL) &&
28429: (ctxt->user_sax->startElementNs != NULL))
28430: ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28431: URI, nb_namespaces, namespaces,
28432: nb_attributes, nb_defaulted,
28433: attributes);
28434: if (ctxt->ctxt != NULL)
28435: xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28436: URI, nb_namespaces, namespaces,
28437: nb_attributes, nb_defaulted,
28438: attributes);
28439: }
28440:
28441: static void
28442: endElementNsSplit(void *ctx, const xmlChar * localname,
28443: const xmlChar * prefix, const xmlChar * URI) {
28444: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28445: if (ctxt == NULL)
28446: return;
28447: if ((ctxt->user_sax != NULL) &&
28448: (ctxt->user_sax->endElementNs != NULL))
28449: ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28450: if (ctxt->ctxt != NULL)
28451: xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28452: }
28453:
28454: /**
28455: * xmlSchemaSAXPlug:
28456: * @ctxt: a schema validation context
28457: * @sax: a pointer to the original xmlSAXHandlerPtr
28458: * @user_data: a pointer to the original SAX user data pointer
28459: *
28460: * Plug a SAX based validation layer in a SAX parsing event flow.
28461: * The original @saxptr and @dataptr data are replaced by new pointers
28462: * but the calls to the original will be maintained.
28463: *
28464: * Returns a pointer to a data structure needed to unplug the validation layer
28465: * or NULL in case of errors.
28466: */
28467: xmlSchemaSAXPlugPtr
28468: xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28469: xmlSAXHandlerPtr *sax, void **user_data)
28470: {
28471: xmlSchemaSAXPlugPtr ret;
28472: xmlSAXHandlerPtr old_sax;
28473:
28474: if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28475: return(NULL);
28476:
28477: /*
28478: * We only allow to plug into SAX2 event streams
28479: */
28480: old_sax = *sax;
28481: if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28482: return(NULL);
28483: if ((old_sax != NULL) &&
28484: (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28485: ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28486: return(NULL);
28487:
28488: /*
28489: * everything seems right allocate the local data needed for that layer
28490: */
28491: ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28492: if (ret == NULL) {
28493: return(NULL);
28494: }
28495: memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28496: ret->magic = XML_SAX_PLUG_MAGIC;
28497: ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28498: ret->ctxt = ctxt;
28499: ret->user_sax_ptr = sax;
28500: ret->user_sax = old_sax;
28501: if (old_sax == NULL) {
28502: /*
28503: * go direct, no need for the split block and functions.
28504: */
28505: ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28506: ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28507: /*
28508: * Note that we use the same text-function for both, to prevent
28509: * the parser from testing for ignorable whitespace.
28510: */
28511: ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28512: ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28513:
28514: ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28515: ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28516:
28517: ret->user_data = ctxt;
28518: *user_data = ctxt;
28519: } else {
28520: /*
28521: * for each callback unused by Schemas initialize it to the Split
28522: * routine only if non NULL in the user block, this can speed up
28523: * things at the SAX level.
28524: */
28525: if (old_sax->internalSubset != NULL)
28526: ret->schemas_sax.internalSubset = internalSubsetSplit;
28527: if (old_sax->isStandalone != NULL)
28528: ret->schemas_sax.isStandalone = isStandaloneSplit;
28529: if (old_sax->hasInternalSubset != NULL)
28530: ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28531: if (old_sax->hasExternalSubset != NULL)
28532: ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28533: if (old_sax->resolveEntity != NULL)
28534: ret->schemas_sax.resolveEntity = resolveEntitySplit;
28535: if (old_sax->getEntity != NULL)
28536: ret->schemas_sax.getEntity = getEntitySplit;
28537: if (old_sax->entityDecl != NULL)
28538: ret->schemas_sax.entityDecl = entityDeclSplit;
28539: if (old_sax->notationDecl != NULL)
28540: ret->schemas_sax.notationDecl = notationDeclSplit;
28541: if (old_sax->attributeDecl != NULL)
28542: ret->schemas_sax.attributeDecl = attributeDeclSplit;
28543: if (old_sax->elementDecl != NULL)
28544: ret->schemas_sax.elementDecl = elementDeclSplit;
28545: if (old_sax->unparsedEntityDecl != NULL)
28546: ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28547: if (old_sax->setDocumentLocator != NULL)
28548: ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28549: if (old_sax->startDocument != NULL)
28550: ret->schemas_sax.startDocument = startDocumentSplit;
28551: if (old_sax->endDocument != NULL)
28552: ret->schemas_sax.endDocument = endDocumentSplit;
28553: if (old_sax->processingInstruction != NULL)
28554: ret->schemas_sax.processingInstruction = processingInstructionSplit;
28555: if (old_sax->comment != NULL)
28556: ret->schemas_sax.comment = commentSplit;
28557: if (old_sax->warning != NULL)
28558: ret->schemas_sax.warning = warningSplit;
28559: if (old_sax->error != NULL)
28560: ret->schemas_sax.error = errorSplit;
28561: if (old_sax->fatalError != NULL)
28562: ret->schemas_sax.fatalError = fatalErrorSplit;
28563: if (old_sax->getParameterEntity != NULL)
28564: ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28565: if (old_sax->externalSubset != NULL)
28566: ret->schemas_sax.externalSubset = externalSubsetSplit;
28567:
28568: /*
28569: * the 6 schemas callback have to go to the splitter functions
28570: * Note that we use the same text-function for ignorableWhitespace
28571: * if possible, to prevent the parser from testing for ignorable
28572: * whitespace.
28573: */
28574: ret->schemas_sax.characters = charactersSplit;
28575: if ((old_sax->ignorableWhitespace != NULL) &&
28576: (old_sax->ignorableWhitespace != old_sax->characters))
28577: ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28578: else
28579: ret->schemas_sax.ignorableWhitespace = charactersSplit;
28580: ret->schemas_sax.cdataBlock = cdataBlockSplit;
28581: ret->schemas_sax.reference = referenceSplit;
28582: ret->schemas_sax.startElementNs = startElementNsSplit;
28583: ret->schemas_sax.endElementNs = endElementNsSplit;
28584:
28585: ret->user_data_ptr = user_data;
28586: ret->user_data = *user_data;
28587: *user_data = ret;
28588: }
28589:
28590: /*
28591: * plug the pointers back.
28592: */
28593: *sax = &(ret->schemas_sax);
28594: ctxt->sax = *sax;
28595: ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28596: xmlSchemaPreRun(ctxt);
28597: return(ret);
28598: }
28599:
28600: /**
28601: * xmlSchemaSAXUnplug:
28602: * @plug: a data structure returned by xmlSchemaSAXPlug
28603: *
28604: * Unplug a SAX based validation layer in a SAX parsing event flow.
28605: * The original pointers used in the call are restored.
28606: *
28607: * Returns 0 in case of success and -1 in case of failure.
28608: */
28609: int
28610: xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28611: {
28612: xmlSAXHandlerPtr *sax;
28613: void **user_data;
28614:
28615: if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28616: return(-1);
28617: plug->magic = 0;
28618:
28619: xmlSchemaPostRun(plug->ctxt);
28620: /* restore the data */
28621: sax = plug->user_sax_ptr;
28622: *sax = plug->user_sax;
28623: if (plug->user_sax != NULL) {
28624: user_data = plug->user_data_ptr;
28625: *user_data = plug->user_data;
28626: }
28627:
28628: /* free and return */
28629: xmlFree(plug);
28630: return(0);
28631: }
28632:
28633: /**
28634: * xmlSchemaValidateStream:
28635: * @ctxt: a schema validation context
28636: * @input: the input to use for reading the data
28637: * @enc: an optional encoding information
28638: * @sax: a SAX handler for the resulting events
28639: * @user_data: the context to provide to the SAX handler.
28640: *
28641: * Validate an input based on a flow of SAX event from the parser
28642: * and forward the events to the @sax handler with the provided @user_data
28643: * the user provided @sax handler must be a SAX2 one.
28644: *
28645: * Returns 0 if the document is schemas valid, a positive error code
28646: * number otherwise and -1 in case of internal or API error.
28647: */
28648: int
28649: xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28650: xmlParserInputBufferPtr input, xmlCharEncoding enc,
28651: xmlSAXHandlerPtr sax, void *user_data)
28652: {
28653: xmlSchemaSAXPlugPtr plug = NULL;
28654: xmlSAXHandlerPtr old_sax = NULL;
28655: xmlParserCtxtPtr pctxt = NULL;
28656: xmlParserInputPtr inputStream = NULL;
28657: int ret;
28658:
28659: if ((ctxt == NULL) || (input == NULL))
28660: return (-1);
28661:
28662: /*
28663: * prepare the parser
28664: */
28665: pctxt = xmlNewParserCtxt();
28666: if (pctxt == NULL)
28667: return (-1);
28668: old_sax = pctxt->sax;
28669: pctxt->sax = sax;
28670: pctxt->userData = user_data;
28671: #if 0
28672: if (options)
28673: xmlCtxtUseOptions(pctxt, options);
28674: #endif
28675: pctxt->linenumbers = 1;
28676:
28677: inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28678: if (inputStream == NULL) {
28679: ret = -1;
28680: goto done;
28681: }
28682: inputPush(pctxt, inputStream);
28683: ctxt->parserCtxt = pctxt;
28684: ctxt->input = input;
28685:
28686: /*
28687: * Plug the validation and launch the parsing
28688: */
28689: plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28690: if (plug == NULL) {
28691: ret = -1;
28692: goto done;
28693: }
28694: ctxt->input = input;
28695: ctxt->enc = enc;
28696: ctxt->sax = pctxt->sax;
28697: ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28698: ret = xmlSchemaVStart(ctxt);
28699:
28700: if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28701: ret = ctxt->parserCtxt->errNo;
28702: if (ret == 0)
28703: ret = 1;
28704: }
28705:
28706: done:
28707: ctxt->parserCtxt = NULL;
28708: ctxt->sax = NULL;
28709: ctxt->input = NULL;
28710: if (plug != NULL) {
28711: xmlSchemaSAXUnplug(plug);
28712: }
28713: /* cleanup */
28714: if (pctxt != NULL) {
28715: pctxt->sax = old_sax;
28716: xmlFreeParserCtxt(pctxt);
28717: }
28718: return (ret);
28719: }
28720:
28721: /**
28722: * xmlSchemaValidateFile:
28723: * @ctxt: a schema validation context
28724: * @filename: the URI of the instance
28725: * @options: a future set of options, currently unused
28726: *
28727: * Do a schemas validation of the given resource, it will use the
28728: * SAX streamable validation internally.
28729: *
28730: * Returns 0 if the document is valid, a positive error code
28731: * number otherwise and -1 in case of an internal or API error.
28732: */
28733: int
28734: xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28735: const char * filename,
28736: int options ATTRIBUTE_UNUSED)
28737: {
28738: int ret;
28739: xmlParserInputBufferPtr input;
28740:
28741: if ((ctxt == NULL) || (filename == NULL))
28742: return (-1);
28743:
28744: input = xmlParserInputBufferCreateFilename(filename,
28745: XML_CHAR_ENCODING_NONE);
28746: if (input == NULL)
28747: return (-1);
28748: ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28749: NULL, NULL);
28750: return (ret);
28751: }
28752:
28753: /**
28754: * xmlSchemaValidCtxtGetParserCtxt:
28755: * @ctxt: a schema validation context
28756: *
28757: * allow access to the parser context of the schema validation context
28758: *
28759: * Returns the parser context of the schema validation context or NULL
28760: * in case of error.
28761: */
28762: xmlParserCtxtPtr
28763: xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28764: {
28765: if (ctxt == NULL)
28766: return(NULL);
28767: return (ctxt->parserCtxt);
28768: }
28769:
28770: #define bottom_xmlschemas
28771: #include "elfgcchack.h"
28772: #endif /* LIBXML_SCHEMAS_ENABLED */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>