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) &&
13949: (sub->negNsSet->value == sub->negNsSet->value))
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: }
15159: if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15160: (WXS_IS_RESTRICTION(type) == 0) &&
15161: (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
15162: xmlSchemaPCustomErr(ctxt,
15163: XML_SCHEMAP_ST_PROPS_CORRECT_1,
15164: WXS_BASIC_CAST type, NULL,
15165: "A type, derived by list or union, must have "
15166: "the simple ur-type definition as base type, not '%s'",
15167: xmlSchemaGetComponentQName(&str, baseType));
15168: FREE_AND_NULL(str)
15169: return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15170: }
15171: /*
15172: * Variety: One of {atomic, list, union}.
15173: */
15174: if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15175: (! WXS_IS_LIST(type))) {
15176: xmlSchemaPCustomErr(ctxt,
15177: XML_SCHEMAP_ST_PROPS_CORRECT_1,
15178: WXS_BASIC_CAST type, NULL,
15179: "The variety is absent", NULL);
15180: return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15181: }
15182: /* TODO: Finish this. Hmm, is this finished? */
15183:
15184: /*
15185: * 3 The {final} of the {base type definition} must not contain restriction.
15186: */
15187: if (xmlSchemaTypeFinalContains(baseType,
15188: XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15189: xmlSchemaPCustomErr(ctxt,
15190: XML_SCHEMAP_ST_PROPS_CORRECT_3,
15191: WXS_BASIC_CAST type, NULL,
15192: "The 'final' of its base type '%s' must not contain "
15193: "'restriction'",
15194: xmlSchemaGetComponentQName(&str, baseType));
15195: FREE_AND_NULL(str)
15196: return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15197: }
15198:
15199: /*
15200: * 2 All simple type definitions must be derived ultimately from the �simple
15201: * ur-type definition (so� circular definitions are disallowed). That is, it
15202: * must be possible to reach a built-in primitive datatype or the �simple
15203: * ur-type definition� by repeatedly following the {base type definition}.
15204: *
15205: * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15206: */
15207: return (0);
15208: }
15209:
15210: /**
15211: * xmlSchemaCheckCOSSTRestricts:
15212: * @ctxt: the schema parser context
15213: * @type: the simple type definition
15214: *
15215: * Schema Component Constraint:
15216: * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15217:
15218: * Checks if the given @type (simpleType) is derived validly by restriction.
15219: * STATUS:
15220: *
15221: * Returns -1 on internal errors, 0 if the type is validly derived,
15222: * a positive error code otherwise.
15223: */
15224: static int
15225: xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15226: xmlSchemaTypePtr type)
15227: {
15228: xmlChar *str = NULL;
15229:
15230: if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15231: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15232: "given type is not a user-derived simpleType");
15233: return (-1);
15234: }
15235:
15236: if (WXS_IS_ATOMIC(type)) {
15237: xmlSchemaTypePtr primitive;
15238: /*
15239: * 1.1 The {base type definition} must be an atomic simple
15240: * type definition or a built-in primitive datatype.
15241: */
15242: if (! WXS_IS_ATOMIC(type->baseType)) {
15243: xmlSchemaPCustomErr(pctxt,
15244: XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15245: WXS_BASIC_CAST type, NULL,
15246: "The base type '%s' is not an atomic simple type",
15247: xmlSchemaGetComponentQName(&str, type->baseType));
15248: FREE_AND_NULL(str)
15249: return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15250: }
15251: /* 1.2 The {final} of the {base type definition} must not contain
15252: * restriction.
15253: */
15254: /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15255: if (xmlSchemaTypeFinalContains(type->baseType,
15256: XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15257: xmlSchemaPCustomErr(pctxt,
15258: XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15259: WXS_BASIC_CAST type, NULL,
15260: "The final of its base type '%s' must not contain 'restriction'",
15261: xmlSchemaGetComponentQName(&str, type->baseType));
15262: FREE_AND_NULL(str)
15263: return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15264: }
15265:
15266: /*
15267: * 1.3.1 DF must be an allowed constraining facet for the {primitive
15268: * type definition}, as specified in the appropriate subsection of 3.2
15269: * Primitive datatypes.
15270: */
15271: if (type->facets != NULL) {
15272: xmlSchemaFacetPtr facet;
15273: int ok = 1;
15274:
15275: primitive = xmlSchemaGetPrimitiveType(type);
15276: if (primitive == NULL) {
15277: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15278: "failed to get primitive type");
15279: return (-1);
15280: }
15281: facet = type->facets;
15282: do {
15283: if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15284: ok = 0;
15285: xmlSchemaPIllegalFacetAtomicErr(pctxt,
15286: XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15287: type, primitive, facet);
15288: }
15289: facet = facet->next;
15290: } while (facet != NULL);
15291: if (ok == 0)
15292: return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15293: }
15294: /*
15295: * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15296: * of the {base type definition} (call this BF),then the DF's {value}
15297: * must be a valid restriction of BF's {value} as defined in
15298: * [XML Schemas: Datatypes]."
15299: *
15300: * NOTE (1.3.2) Facet derivation constraints are currently handled in
15301: * xmlSchemaDeriveAndValidateFacets()
15302: */
15303: } else if (WXS_IS_LIST(type)) {
15304: xmlSchemaTypePtr itemType = NULL;
15305:
15306: itemType = type->subtypes;
15307: if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15308: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15309: "failed to evaluate the item type");
15310: return (-1);
15311: }
15312: if (WXS_IS_TYPE_NOT_FIXED(itemType))
15313: xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15314: /*
15315: * 2.1 The {item type definition} must have a {variety} of atomic or
15316: * union (in which case all the {member type definitions}
15317: * must be atomic).
15318: */
15319: if ((! WXS_IS_ATOMIC(itemType)) &&
15320: (! WXS_IS_UNION(itemType))) {
15321: xmlSchemaPCustomErr(pctxt,
15322: XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15323: WXS_BASIC_CAST type, NULL,
15324: "The item type '%s' does not have a variety of atomic or union",
15325: xmlSchemaGetComponentQName(&str, itemType));
15326: FREE_AND_NULL(str)
15327: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15328: } else if (WXS_IS_UNION(itemType)) {
15329: xmlSchemaTypeLinkPtr member;
15330:
15331: member = itemType->memberTypes;
15332: while (member != NULL) {
15333: if (! WXS_IS_ATOMIC(member->type)) {
15334: xmlSchemaPCustomErr(pctxt,
15335: XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15336: WXS_BASIC_CAST type, NULL,
15337: "The item type is a union type, but the "
15338: "member type '%s' of this item type is not atomic",
15339: xmlSchemaGetComponentQName(&str, member->type));
15340: FREE_AND_NULL(str)
15341: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15342: }
15343: member = member->next;
15344: }
15345: }
15346:
15347: if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15348: xmlSchemaFacetPtr facet;
15349: /*
15350: * This is the case if we have: <simpleType><list ..
15351: */
15352: /*
15353: * 2.3.1
15354: * 2.3.1.1 The {final} of the {item type definition} must not
15355: * contain list.
15356: */
15357: if (xmlSchemaTypeFinalContains(itemType,
15358: XML_SCHEMAS_TYPE_FINAL_LIST)) {
15359: xmlSchemaPCustomErr(pctxt,
15360: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15361: WXS_BASIC_CAST type, NULL,
15362: "The final of its item type '%s' must not contain 'list'",
15363: xmlSchemaGetComponentQName(&str, itemType));
15364: FREE_AND_NULL(str)
15365: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15366: }
15367: /*
15368: * 2.3.1.2 The {facets} must only contain the whiteSpace
15369: * facet component.
15370: * OPTIMIZE TODO: the S4S already disallows any facet
15371: * to be specified.
15372: */
15373: if (type->facets != NULL) {
15374: facet = type->facets;
15375: do {
15376: if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15377: xmlSchemaPIllegalFacetListUnionErr(pctxt,
15378: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15379: type, facet);
15380: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15381: }
15382: facet = facet->next;
15383: } while (facet != NULL);
15384: }
15385: /*
15386: * MAYBE TODO: (Hmm, not really) Datatypes states:
15387: * A �list� datatype can be �derived� from an �atomic� datatype
15388: * whose �lexical space� allows space (such as string or anyURI)or
15389: * a �union� datatype any of whose {member type definitions}'s
15390: * �lexical space� allows space.
15391: */
15392: } else {
15393: /*
15394: * This is the case if we have: <simpleType><restriction ...
15395: * I.e. the variety of "list" is inherited.
15396: */
15397: /*
15398: * 2.3.2
15399: * 2.3.2.1 The {base type definition} must have a {variety} of list.
15400: */
15401: if (! WXS_IS_LIST(type->baseType)) {
15402: xmlSchemaPCustomErr(pctxt,
15403: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15404: WXS_BASIC_CAST type, NULL,
15405: "The base type '%s' must be a list type",
15406: xmlSchemaGetComponentQName(&str, type->baseType));
15407: FREE_AND_NULL(str)
15408: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15409: }
15410: /*
15411: * 2.3.2.2 The {final} of the {base type definition} must not
15412: * contain restriction.
15413: */
15414: if (xmlSchemaTypeFinalContains(type->baseType,
15415: XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15416: xmlSchemaPCustomErr(pctxt,
15417: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15418: WXS_BASIC_CAST type, NULL,
15419: "The 'final' of the base type '%s' must not contain 'restriction'",
15420: xmlSchemaGetComponentQName(&str, type->baseType));
15421: FREE_AND_NULL(str)
15422: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15423: }
15424: /*
15425: * 2.3.2.3 The {item type definition} must be validly derived
15426: * from the {base type definition}'s {item type definition} given
15427: * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15428: */
15429: {
15430: xmlSchemaTypePtr baseItemType;
15431:
15432: baseItemType = type->baseType->subtypes;
15433: if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15434: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15435: "failed to eval the item type of a base type");
15436: return (-1);
15437: }
15438: if ((itemType != baseItemType) &&
15439: (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15440: baseItemType, 0) != 0)) {
15441: xmlChar *strBIT = NULL, *strBT = NULL;
15442: xmlSchemaPCustomErrExt(pctxt,
15443: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15444: WXS_BASIC_CAST type, NULL,
15445: "The item type '%s' is not validly derived from "
15446: "the item type '%s' of the base type '%s'",
15447: xmlSchemaGetComponentQName(&str, itemType),
15448: xmlSchemaGetComponentQName(&strBIT, baseItemType),
15449: xmlSchemaGetComponentQName(&strBT, type->baseType));
15450:
15451: FREE_AND_NULL(str)
15452: FREE_AND_NULL(strBIT)
15453: FREE_AND_NULL(strBT)
15454: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15455: }
15456: }
15457:
15458: if (type->facets != NULL) {
15459: xmlSchemaFacetPtr facet;
15460: int ok = 1;
15461: /*
15462: * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15463: * and enumeration facet components are allowed among the {facets}.
15464: */
15465: facet = type->facets;
15466: do {
15467: switch (facet->type) {
15468: case XML_SCHEMA_FACET_LENGTH:
15469: case XML_SCHEMA_FACET_MINLENGTH:
15470: case XML_SCHEMA_FACET_MAXLENGTH:
15471: case XML_SCHEMA_FACET_WHITESPACE:
15472: /*
15473: * TODO: 2.5.1.2 List datatypes
15474: * The value of �whiteSpace� is fixed to the value collapse.
15475: */
15476: case XML_SCHEMA_FACET_PATTERN:
15477: case XML_SCHEMA_FACET_ENUMERATION:
15478: break;
15479: default: {
15480: xmlSchemaPIllegalFacetListUnionErr(pctxt,
15481: XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15482: type, facet);
15483: /*
15484: * We could return, but it's nicer to report all
15485: * invalid facets.
15486: */
15487: ok = 0;
15488: }
15489: }
15490: facet = facet->next;
15491: } while (facet != NULL);
15492: if (ok == 0)
15493: return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15494: /*
15495: * SPEC (2.3.2.5) (same as 1.3.2)
15496: *
15497: * NOTE (2.3.2.5) This is currently done in
15498: * xmlSchemaDeriveAndValidateFacets()
15499: */
15500: }
15501: }
15502: } else if (WXS_IS_UNION(type)) {
15503: /*
15504: * 3.1 The {member type definitions} must all have {variety} of
15505: * atomic or list.
15506: */
15507: xmlSchemaTypeLinkPtr member;
15508:
15509: member = type->memberTypes;
15510: while (member != NULL) {
15511: if (WXS_IS_TYPE_NOT_FIXED(member->type))
15512: xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15513:
15514: if ((! WXS_IS_ATOMIC(member->type)) &&
15515: (! WXS_IS_LIST(member->type))) {
15516: xmlSchemaPCustomErr(pctxt,
15517: XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15518: WXS_BASIC_CAST type, NULL,
15519: "The member type '%s' is neither an atomic, nor a list type",
15520: xmlSchemaGetComponentQName(&str, member->type));
15521: FREE_AND_NULL(str)
15522: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15523: }
15524: member = member->next;
15525: }
15526: /*
15527: * 3.3.1 If the {base type definition} is the �simple ur-type
15528: * definition�
15529: */
15530: if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15531: /*
15532: * 3.3.1.1 All of the {member type definitions} must have a
15533: * {final} which does not contain union.
15534: */
15535: member = type->memberTypes;
15536: while (member != NULL) {
15537: if (xmlSchemaTypeFinalContains(member->type,
15538: XML_SCHEMAS_TYPE_FINAL_UNION)) {
15539: xmlSchemaPCustomErr(pctxt,
15540: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15541: WXS_BASIC_CAST type, NULL,
15542: "The 'final' of member type '%s' contains 'union'",
15543: xmlSchemaGetComponentQName(&str, member->type));
15544: FREE_AND_NULL(str)
15545: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15546: }
15547: member = member->next;
15548: }
15549: /*
15550: * 3.3.1.2 The {facets} must be empty.
15551: */
15552: if (type->facetSet != NULL) {
15553: xmlSchemaPCustomErr(pctxt,
15554: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15555: WXS_BASIC_CAST type, NULL,
15556: "No facets allowed", NULL);
15557: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15558: }
15559: } else {
15560: /*
15561: * 3.3.2.1 The {base type definition} must have a {variety} of union.
15562: * I.e. the variety of "list" is inherited.
15563: */
15564: if (! WXS_IS_UNION(type->baseType)) {
15565: xmlSchemaPCustomErr(pctxt,
15566: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15567: WXS_BASIC_CAST type, NULL,
15568: "The base type '%s' is not a union type",
15569: xmlSchemaGetComponentQName(&str, type->baseType));
15570: FREE_AND_NULL(str)
15571: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15572: }
15573: /*
15574: * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15575: */
15576: if (xmlSchemaTypeFinalContains(type->baseType,
15577: XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15578: xmlSchemaPCustomErr(pctxt,
15579: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15580: WXS_BASIC_CAST type, NULL,
15581: "The 'final' of its base type '%s' must not contain 'restriction'",
15582: xmlSchemaGetComponentQName(&str, type->baseType));
15583: FREE_AND_NULL(str)
15584: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15585: }
15586: /*
15587: * 3.3.2.3 The {member type definitions}, in order, must be validly
15588: * derived from the corresponding type definitions in the {base
15589: * type definition}'s {member type definitions} given the empty set,
15590: * as defined in Type Derivation OK (Simple) (�3.14.6).
15591: */
15592: {
15593: xmlSchemaTypeLinkPtr baseMember;
15594:
15595: /*
15596: * OPTIMIZE: if the type is restricting, it has no local defined
15597: * member types and inherits the member types of the base type;
15598: * thus a check for equality can be skipped.
15599: */
15600: /*
15601: * Even worse: I cannot see a scenario where a restricting
15602: * union simple type can have other member types as the member
15603: * types of it's base type. This check seems not necessary with
15604: * respect to the derivation process in libxml2.
15605: * But necessary if constructing types with an API.
15606: */
15607: if (type->memberTypes != NULL) {
15608: member = type->memberTypes;
15609: baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15610: if ((member == NULL) && (baseMember != NULL)) {
15611: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15612: "different number of member types in base");
15613: }
15614: while (member != NULL) {
15615: if (baseMember == NULL) {
15616: PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15617: "different number of member types in base");
15618: } else if ((member->type != baseMember->type) &&
15619: (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15620: member->type, baseMember->type, 0) != 0)) {
15621: xmlChar *strBMT = NULL, *strBT = NULL;
15622:
15623: xmlSchemaPCustomErrExt(pctxt,
15624: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15625: WXS_BASIC_CAST type, NULL,
15626: "The member type %s is not validly "
15627: "derived from its corresponding member "
15628: "type %s of the base type %s",
15629: xmlSchemaGetComponentQName(&str, member->type),
15630: xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15631: xmlSchemaGetComponentQName(&strBT, type->baseType));
15632: FREE_AND_NULL(str)
15633: FREE_AND_NULL(strBMT)
15634: FREE_AND_NULL(strBT)
15635: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15636: }
15637: member = member->next;
15638: if (baseMember != NULL)
15639: baseMember = baseMember->next;
15640: }
15641: }
15642: }
15643: /*
15644: * 3.3.2.4 Only pattern and enumeration facet components are
15645: * allowed among the {facets}.
15646: */
15647: if (type->facets != NULL) {
15648: xmlSchemaFacetPtr facet;
15649: int ok = 1;
15650:
15651: facet = type->facets;
15652: do {
15653: if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15654: (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15655: xmlSchemaPIllegalFacetListUnionErr(pctxt,
15656: XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15657: type, facet);
15658: ok = 0;
15659: }
15660: facet = facet->next;
15661: } while (facet != NULL);
15662: if (ok == 0)
15663: return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15664:
15665: }
15666: /*
15667: * SPEC (3.3.2.5) (same as 1.3.2)
15668: *
15669: * NOTE (3.3.2.5) This is currently done in
15670: * xmlSchemaDeriveAndValidateFacets()
15671: */
15672: }
15673: }
15674:
15675: return (0);
15676: }
15677:
15678: /**
15679: * xmlSchemaCheckSRCSimpleType:
15680: * @ctxt: the schema parser context
15681: * @type: the simple type definition
15682: *
15683: * Checks crc-simple-type constraints.
15684: *
15685: * Returns 0 if the constraints are satisfied,
15686: * if not a positive error code and -1 on internal
15687: * errors.
15688: */
15689: #if 0
15690: static int
15691: xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15692: xmlSchemaTypePtr type)
15693: {
15694: /*
15695: * src-simple-type.1 The corresponding simple type definition, if any,
15696: * must satisfy the conditions set out in Constraints on Simple Type
15697: * Definition Schema Components (�3.14.6).
15698: */
15699: if (WXS_IS_RESTRICTION(type)) {
15700: /*
15701: * src-simple-type.2 "If the <restriction> alternative is chosen,
15702: * either it must have a base [attribute] or a <simpleType> among its
15703: * [children], but not both."
15704: * NOTE: This is checked in the parse function of <restriction>.
15705: */
15706: /*
15707: *
15708: */
15709: } else if (WXS_IS_LIST(type)) {
15710: /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15711: * an itemType [attribute] or a <simpleType> among its [children],
15712: * but not both."
15713: *
15714: * NOTE: This is checked in the parse function of <list>.
15715: */
15716: } else if (WXS_IS_UNION(type)) {
15717: /*
15718: * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15719: */
15720: }
15721: return (0);
15722: }
15723: #endif
15724:
15725: static int
15726: xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15727: {
15728: if (ctxt->vctxt == NULL) {
15729: ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15730: if (ctxt->vctxt == NULL) {
15731: xmlSchemaPErr(ctxt, NULL,
15732: XML_SCHEMAP_INTERNAL,
15733: "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15734: "failed to create a temp. validation context.\n",
15735: NULL, NULL);
15736: return (-1);
15737: }
15738: /* TODO: Pass user data. */
15739: xmlSchemaSetValidErrors(ctxt->vctxt,
15740: ctxt->error, ctxt->warning, ctxt->errCtxt);
15741: xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15742: ctxt->serror, ctxt->errCtxt);
15743: }
15744: return (0);
15745: }
15746:
15747: static int
15748: xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15749: xmlNodePtr node,
15750: xmlSchemaTypePtr type,
15751: const xmlChar *value,
15752: xmlSchemaValPtr *retVal,
15753: int fireErrors,
15754: int normalize,
15755: int isNormalized);
15756:
15757: /**
15758: * xmlSchemaParseCheckCOSValidDefault:
15759: * @pctxt: the schema parser context
15760: * @type: the simple type definition
15761: * @value: the default value
15762: * @node: an optional node (the holder of the value)
15763: *
15764: * Schema Component Constraint: Element Default Valid (Immediate)
15765: * (cos-valid-default)
15766: * This will be used by the parser only. For the validator there's
15767: * an other version.
15768: *
15769: * Returns 0 if the constraints are satisfied,
15770: * if not, a positive error code and -1 on internal
15771: * errors.
15772: */
15773: static int
15774: xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15775: xmlNodePtr node,
15776: xmlSchemaTypePtr type,
15777: const xmlChar *value,
15778: xmlSchemaValPtr *val)
15779: {
15780: int ret = 0;
15781:
15782: /*
15783: * cos-valid-default:
15784: * Schema Component Constraint: Element Default Valid (Immediate)
15785: * For a string to be a valid default with respect to a type
15786: * definition the appropriate case among the following must be true:
15787: */
15788: if WXS_IS_COMPLEX(type) {
15789: /*
15790: * Complex type.
15791: *
15792: * SPEC (2.1) "its {content type} must be a simple type definition
15793: * or mixed."
15794: * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15795: * type}'s particle must be �emptiable� as defined by
15796: * Particle Emptiable (�3.9.6)."
15797: */
15798: if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15799: ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15800: /* NOTE that this covers (2.2.2) as well. */
15801: xmlSchemaPCustomErr(pctxt,
15802: XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15803: WXS_BASIC_CAST type, type->node,
15804: "For a string to be a valid default, the type definition "
15805: "must be a simple type or a complex type with mixed content "
15806: "and a particle emptiable", NULL);
15807: return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15808: }
15809: }
15810: /*
15811: * 1 If the type definition is a simple type definition, then the string
15812: * must be �valid� with respect to that definition as defined by String
15813: * Valid (�3.14.4).
15814: *
15815: * AND
15816: *
15817: * 2.2.1 If the {content type} is a simple type definition, then the
15818: * string must be �valid� with respect to that simple type definition
15819: * as defined by String Valid (�3.14.4).
15820: */
15821: if (WXS_IS_SIMPLE(type))
15822: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15823: type, value, val, 1, 1, 0);
15824: else if (WXS_HAS_SIMPLE_CONTENT(type))
15825: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15826: type->contentTypeDef, value, val, 1, 1, 0);
15827: else
15828: return (ret);
15829:
15830: if (ret < 0) {
15831: PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15832: "calling xmlSchemaVCheckCVCSimpleType()");
15833: }
15834:
15835: return (ret);
15836: }
15837:
15838: /**
15839: * xmlSchemaCheckCTPropsCorrect:
15840: * @ctxt: the schema parser context
15841: * @type: the complex type definition
15842: *
15843: *.(4.6) Constraints on Complex Type Definition Schema Components
15844: * Schema Component Constraint:
15845: * Complex Type Definition Properties Correct (ct-props-correct)
15846: * STATUS: (seems) complete
15847: *
15848: * Returns 0 if the constraints are satisfied, a positive
15849: * error code if not and -1 if an internal error occured.
15850: */
15851: static int
15852: xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15853: xmlSchemaTypePtr type)
15854: {
15855: /*
15856: * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15857: *
15858: * SPEC (1) "The values of the properties of a complex type definition must
15859: * be as described in the property tableau in The Complex Type Definition
15860: * Schema Component (�3.4.1), modulo the impact of Missing
15861: * Sub-components (�5.3)."
15862: */
15863: if ((type->baseType != NULL) &&
15864: (WXS_IS_SIMPLE(type->baseType)) &&
15865: (WXS_IS_EXTENSION(type) == 0)) {
15866: /*
15867: * SPEC (2) "If the {base type definition} is a simple type definition,
15868: * the {derivation method} must be extension."
15869: */
15870: xmlSchemaCustomErr(ACTXT_CAST pctxt,
15871: XML_SCHEMAP_SRC_CT_1,
15872: NULL, WXS_BASIC_CAST type,
15873: "If the base type is a simple type, the derivation method must be "
15874: "'extension'", NULL, NULL);
15875: return (XML_SCHEMAP_SRC_CT_1);
15876: }
15877: /*
15878: * SPEC (3) "Circular definitions are disallowed, except for the �ur-type
15879: * definition�. That is, it must be possible to reach the �ur-type
15880: * definition by repeatedly following the {base type definition}."
15881: *
15882: * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15883: */
15884: /*
15885: * NOTE that (4) and (5) need the following:
15886: * - attribute uses need to be already inherited (apply attr. prohibitions)
15887: * - attribute group references need to be expanded already
15888: * - simple types need to be typefixed already
15889: */
15890: if (type->attrUses &&
15891: (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15892: {
15893: xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15894: xmlSchemaAttributeUsePtr use, tmp;
15895: int i, j, hasId = 0;
15896:
15897: for (i = uses->nbItems -1; i >= 0; i--) {
15898: use = uses->items[i];
15899:
15900: /*
15901: * SPEC ct-props-correct
15902: * (4) "Two distinct attribute declarations in the
15903: * {attribute uses} must not have identical {name}s and
15904: * {target namespace}s."
15905: */
15906: if (i > 0) {
15907: for (j = i -1; j >= 0; j--) {
15908: tmp = uses->items[j];
15909: if ((WXS_ATTRUSE_DECL_NAME(use) ==
15910: WXS_ATTRUSE_DECL_NAME(tmp)) &&
15911: (WXS_ATTRUSE_DECL_TNS(use) ==
15912: WXS_ATTRUSE_DECL_TNS(tmp)))
15913: {
15914: xmlChar *str = NULL;
15915:
15916: xmlSchemaCustomErr(ACTXT_CAST pctxt,
15917: XML_SCHEMAP_AG_PROPS_CORRECT,
15918: NULL, WXS_BASIC_CAST type,
15919: "Duplicate %s",
15920: xmlSchemaGetComponentDesignation(&str, use),
15921: NULL);
15922: FREE_AND_NULL(str);
15923: /*
15924: * Remove the duplicate.
15925: */
15926: if (xmlSchemaItemListRemove(uses, i) == -1)
15927: goto exit_failure;
15928: goto next_use;
15929: }
15930: }
15931: }
15932: /*
15933: * SPEC ct-props-correct
15934: * (5) "Two distinct attribute declarations in the
15935: * {attribute uses} must not have {type definition}s which
15936: * are or are derived from ID."
15937: */
15938: if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15939: if (xmlSchemaIsDerivedFromBuiltInType(
15940: WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15941: {
15942: if (hasId) {
15943: xmlChar *str = NULL;
15944:
15945: xmlSchemaCustomErr(ACTXT_CAST pctxt,
15946: XML_SCHEMAP_AG_PROPS_CORRECT,
15947: NULL, WXS_BASIC_CAST type,
15948: "There must not exist more than one attribute "
15949: "declaration of type 'xs:ID' "
15950: "(or derived from 'xs:ID'). The %s violates this "
15951: "constraint",
15952: xmlSchemaGetComponentDesignation(&str, use),
15953: NULL);
15954: FREE_AND_NULL(str);
15955: if (xmlSchemaItemListRemove(uses, i) == -1)
15956: goto exit_failure;
15957: }
15958:
15959: hasId = 1;
15960: }
15961: }
15962: next_use: {}
15963: }
15964: }
15965: return (0);
15966: exit_failure:
15967: return(-1);
15968: }
15969:
15970: static int
15971: xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15972: xmlSchemaTypePtr typeB)
15973: {
15974: /*
15975: * TODO: This should implement component-identity
15976: * in the future.
15977: */
15978: if ((typeA == NULL) || (typeB == NULL))
15979: return (0);
15980: return (typeA == typeB);
15981: }
15982:
15983: /**
15984: * xmlSchemaCheckCOSCTDerivedOK:
15985: * @ctxt: the schema parser context
15986: * @type: the to-be derived complex type definition
15987: * @baseType: the base complex type definition
15988: * @set: the given set
15989: *
15990: * Schema Component Constraint:
15991: * Type Derivation OK (Complex) (cos-ct-derived-ok)
15992: *
15993: * STATUS: completed
15994: *
15995: * Returns 0 if the constraints are satisfied, or 1
15996: * if not.
15997: */
15998: static int
15999: xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16000: xmlSchemaTypePtr type,
16001: xmlSchemaTypePtr baseType,
16002: int set)
16003: {
16004: int equal = xmlSchemaAreEqualTypes(type, baseType);
16005: /* TODO: Error codes. */
16006: /*
16007: * SPEC "For a complex type definition (call it D, for derived)
16008: * to be validly derived from a type definition (call this
16009: * B, for base) given a subset of {extension, restriction}
16010: * all of the following must be true:"
16011: */
16012: if (! equal) {
16013: /*
16014: * SPEC (1) "If B and D are not the same type definition, then the
16015: * {derivation method} of D must not be in the subset."
16016: */
16017: if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16018: ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16019: return (1);
16020: } else {
16021: /*
16022: * SPEC (2.1) "B and D must be the same type definition."
16023: */
16024: return (0);
16025: }
16026: /*
16027: * SPEC (2.2) "B must be D's {base type definition}."
16028: */
16029: if (type->baseType == baseType)
16030: return (0);
16031: /*
16032: * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type
16033: * definition�."
16034: */
16035: if (WXS_IS_ANYTYPE(type->baseType))
16036: return (1);
16037:
16038: if (WXS_IS_COMPLEX(type->baseType)) {
16039: /*
16040: * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16041: * must be validly derived from B given the subset as defined by this
16042: * constraint."
16043: */
16044: return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16045: baseType, set));
16046: } else {
16047: /*
16048: * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16049: * must be validly derived from B given the subset as defined in Type
16050: * Derivation OK (Simple) (�3.14.6).
16051: */
16052: return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16053: baseType, set));
16054: }
16055: }
16056:
16057: /**
16058: * xmlSchemaCheckCOSDerivedOK:
16059: * @type: the derived simple type definition
16060: * @baseType: the base type definition
16061: *
16062: * Calls:
16063: * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16064: *
16065: * Checks wheter @type can be validly derived from @baseType.
16066: *
16067: * Returns 0 on success, an positive error code otherwise.
16068: */
16069: static int
16070: xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16071: xmlSchemaTypePtr type,
16072: xmlSchemaTypePtr baseType,
16073: int set)
16074: {
16075: if (WXS_IS_SIMPLE(type))
16076: return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16077: else
16078: return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16079: }
16080:
16081: /**
16082: * xmlSchemaCheckCOSCTExtends:
16083: * @ctxt: the schema parser context
16084: * @type: the complex type definition
16085: *
16086: * (3.4.6) Constraints on Complex Type Definition Schema Components
16087: * Schema Component Constraint:
16088: * Derivation Valid (Extension) (cos-ct-extends)
16089: *
16090: * STATUS:
16091: * missing:
16092: * (1.5)
16093: * (1.4.3.2.2.2) "Particle Valid (Extension)"
16094: *
16095: * Returns 0 if the constraints are satisfied, a positive
16096: * error code if not and -1 if an internal error occured.
16097: */
16098: static int
16099: xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16100: xmlSchemaTypePtr type)
16101: {
16102: xmlSchemaTypePtr base = type->baseType;
16103: /*
16104: * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16105: * temporarily only.
16106: */
16107: /*
16108: * SPEC (1) "If the {base type definition} is a complex type definition,
16109: * then all of the following must be true:"
16110: */
16111: if (WXS_IS_COMPLEX(base)) {
16112: /*
16113: * SPEC (1.1) "The {final} of the {base type definition} must not
16114: * contain extension."
16115: */
16116: if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16117: xmlSchemaPCustomErr(ctxt,
16118: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16119: WXS_BASIC_CAST type, NULL,
16120: "The 'final' of the base type definition "
16121: "contains 'extension'", NULL);
16122: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16123: }
16124:
16125: /*
16126: * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16127: * since they are automatically satisfied through the
16128: * inheriting mechanism.
16129: * Note that even if redefining components, the inheriting mechanism
16130: * is used.
16131: */
16132: #if 0
16133: /*
16134: * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16135: * uses}
16136: * of the complex type definition itself, that is, for every attribute
16137: * use in the {attribute uses} of the {base type definition}, there
16138: * must be an attribute use in the {attribute uses} of the complex
16139: * type definition itself whose {attribute declaration} has the same
16140: * {name}, {target namespace} and {type definition} as its attribute
16141: * declaration"
16142: */
16143: if (base->attrUses != NULL) {
16144: int i, j, found;
16145: xmlSchemaAttributeUsePtr use, buse;
16146:
16147: for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16148: buse = (WXS_LIST_CAST base->attrUses)->items[i];
16149: found = 0;
16150: if (type->attrUses != NULL) {
16151: use = (WXS_LIST_CAST type->attrUses)->items[j];
16152: for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16153: {
16154: if ((WXS_ATTRUSE_DECL_NAME(use) ==
16155: WXS_ATTRUSE_DECL_NAME(buse)) &&
16156: (WXS_ATTRUSE_DECL_TNS(use) ==
16157: WXS_ATTRUSE_DECL_TNS(buse)) &&
16158: (WXS_ATTRUSE_TYPEDEF(use) ==
16159: WXS_ATTRUSE_TYPEDEF(buse))
16160: {
16161: found = 1;
16162: break;
16163: }
16164: }
16165: }
16166: if (! found) {
16167: xmlChar *str = NULL;
16168:
16169: xmlSchemaCustomErr(ACTXT_CAST ctxt,
16170: XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16171: NULL, WXS_BASIC_CAST type,
16172: /*
16173: * TODO: The report does not indicate that also the
16174: * type needs to be the same.
16175: */
16176: "This type is missing a matching correspondent "
16177: "for its {base type}'s %s in its {attribute uses}",
16178: xmlSchemaGetComponentDesignation(&str,
16179: buse->children),
16180: NULL);
16181: FREE_AND_NULL(str)
16182: }
16183: }
16184: }
16185: /*
16186: * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16187: * definition must also have one, and the base type definition's
16188: * {attribute wildcard}'s {namespace constraint} must be a subset
16189: * of the complex type definition's {attribute wildcard}'s {namespace
16190: * constraint}, as defined by Wildcard Subset (�3.10.6)."
16191: */
16192:
16193: /*
16194: * MAYBE TODO: Enable if ever needed. But this will be needed only
16195: * if created the type via a schema construction API.
16196: */
16197: if (base->attributeWildcard != NULL) {
16198: if (type->attributeWilcard == NULL) {
16199: xmlChar *str = NULL;
16200:
16201: xmlSchemaCustomErr(ACTXT_CAST pctxt,
16202: XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16203: NULL, type,
16204: "The base %s has an attribute wildcard, "
16205: "but this type is missing an attribute wildcard",
16206: xmlSchemaGetComponentDesignation(&str, base));
16207: FREE_AND_NULL(str)
16208:
16209: } else if (xmlSchemaCheckCOSNSSubset(
16210: base->attributeWildcard, type->attributeWildcard))
16211: {
16212: xmlChar *str = NULL;
16213:
16214: xmlSchemaCustomErr(ACTXT_CAST pctxt,
16215: XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16216: NULL, type,
16217: "The attribute wildcard is not a valid "
16218: "superset of the one in the base %s",
16219: xmlSchemaGetComponentDesignation(&str, base));
16220: FREE_AND_NULL(str)
16221: }
16222: }
16223: #endif
16224: /*
16225: * SPEC (1.4) "One of the following must be true:"
16226: */
16227: if ((type->contentTypeDef != NULL) &&
16228: (type->contentTypeDef == base->contentTypeDef)) {
16229: /*
16230: * SPEC (1.4.1) "The {content type} of the {base type definition}
16231: * and the {content type} of the complex type definition itself
16232: * must be the same simple type definition"
16233: * PASS
16234: */
16235: } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16236: (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16237: /*
16238: * SPEC (1.4.2) "The {content type} of both the {base type
16239: * definition} and the complex type definition itself must
16240: * be empty."
16241: * PASS
16242: */
16243: } else {
16244: /*
16245: * SPEC (1.4.3) "All of the following must be true:"
16246: */
16247: if (type->subtypes == NULL) {
16248: /*
16249: * SPEC 1.4.3.1 The {content type} of the complex type
16250: * definition itself must specify a particle.
16251: */
16252: xmlSchemaPCustomErr(ctxt,
16253: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16254: WXS_BASIC_CAST type, NULL,
16255: "The content type must specify a particle", NULL);
16256: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16257: }
16258: /*
16259: * SPEC (1.4.3.2) "One of the following must be true:"
16260: */
16261: if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16262: /*
16263: * SPEC (1.4.3.2.1) "The {content type} of the {base type
16264: * definition} must be empty.
16265: * PASS
16266: */
16267: } else {
16268: /*
16269: * SPEC (1.4.3.2.2) "All of the following must be true:"
16270: */
16271: if ((type->contentType != base->contentType) ||
16272: ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16273: (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16274: /*
16275: * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16276: * or both must be element-only."
16277: */
16278: xmlSchemaPCustomErr(ctxt,
16279: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16280: WXS_BASIC_CAST type, NULL,
16281: "The content type of both, the type and its base "
16282: "type, must either 'mixed' or 'element-only'", NULL);
16283: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16284: }
16285: /*
16286: * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16287: * complex type definition must be a �valid extension�
16288: * of the {base type definition}'s particle, as defined
16289: * in Particle Valid (Extension) (�3.9.6)."
16290: *
16291: * NOTE that we won't check "Particle Valid (Extension)",
16292: * since it is ensured by the derivation process in
16293: * xmlSchemaTypeFixup(). We need to implement this when heading
16294: * for a construction API
16295: * TODO: !! This is needed to be checked if redefining a type !!
16296: */
16297: }
16298: /*
16299: * URGENT TODO (1.5)
16300: */
16301: }
16302: } else {
16303: /*
16304: * SPEC (2) "If the {base type definition} is a simple type definition,
16305: * then all of the following must be true:"
16306: */
16307: if (type->contentTypeDef != base) {
16308: /*
16309: * SPEC (2.1) "The {content type} must be the same simple type
16310: * definition."
16311: */
16312: xmlSchemaPCustomErr(ctxt,
16313: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16314: WXS_BASIC_CAST type, NULL,
16315: "The content type must be the simple base type", NULL);
16316: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16317: }
16318: if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16319: /*
16320: * SPEC (2.2) "The {final} of the {base type definition} must not
16321: * contain extension"
16322: * NOTE that this is the same as (1.1).
16323: */
16324: xmlSchemaPCustomErr(ctxt,
16325: XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16326: WXS_BASIC_CAST type, NULL,
16327: "The 'final' of the base type definition "
16328: "contains 'extension'", NULL);
16329: return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16330: }
16331: }
16332: return (0);
16333: }
16334:
16335: /**
16336: * xmlSchemaCheckDerivationOKRestriction:
16337: * @ctxt: the schema parser context
16338: * @type: the complex type definition
16339: *
16340: * (3.4.6) Constraints on Complex Type Definition Schema Components
16341: * Schema Component Constraint:
16342: * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16343: *
16344: * STATUS:
16345: * missing:
16346: * (5.4.2) ???
16347: *
16348: * ATTENTION:
16349: * In XML Schema 1.1 this will be:
16350: * Validation Rule: Checking complex type subsumption
16351: *
16352: * Returns 0 if the constraints are satisfied, a positive
16353: * error code if not and -1 if an internal error occured.
16354: */
16355: static int
16356: xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16357: xmlSchemaTypePtr type)
16358: {
16359: xmlSchemaTypePtr base;
16360:
16361: /*
16362: * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16363: * temporarily only.
16364: */
16365: base = type->baseType;
16366: if (! WXS_IS_COMPLEX(base)) {
16367: xmlSchemaCustomErr(ACTXT_CAST ctxt,
16368: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16369: type->node, WXS_BASIC_CAST type,
16370: "The base type must be a complex type", NULL, NULL);
16371: return(ctxt->err);
16372: }
16373: if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16374: /*
16375: * SPEC (1) "The {base type definition} must be a complex type
16376: * definition whose {final} does not contain restriction."
16377: */
16378: xmlSchemaCustomErr(ACTXT_CAST ctxt,
16379: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16380: type->node, WXS_BASIC_CAST type,
16381: "The 'final' of the base type definition "
16382: "contains 'restriction'", NULL, NULL);
16383: return (ctxt->err);
16384: }
16385: /*
16386: * SPEC (2), (3) and (4)
16387: * Those are handled in a separate function, since the
16388: * same constraints are needed for redefinition of
16389: * attribute groups as well.
16390: */
16391: if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16392: XML_SCHEMA_ACTION_DERIVE,
16393: WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16394: type->attrUses, base->attrUses,
16395: type->attributeWildcard,
16396: base->attributeWildcard) == -1)
16397: {
16398: return(-1);
16399: }
16400: /*
16401: * SPEC (5) "One of the following must be true:"
16402: */
16403: if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16404: /*
16405: * SPEC (5.1) "The {base type definition} must be the
16406: * �ur-type definition�."
16407: * PASS
16408: */
16409: } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16410: (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16411: /*
16412: * SPEC (5.2.1) "The {content type} of the complex type definition
16413: * must be a simple type definition"
16414: *
16415: * SPEC (5.2.2) "One of the following must be true:"
16416: */
16417: if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16418: (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16419: {
16420: int err;
16421: /*
16422: * SPEC (5.2.2.1) "The {content type} of the {base type
16423: * definition} must be a simple type definition from which
16424: * the {content type} is validly derived given the empty
16425: * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16426: *
16427: * ATTENTION TODO: This seems not needed if the type implicitely
16428: * derived from the base type.
16429: *
16430: */
16431: err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16432: type->contentTypeDef, base->contentTypeDef, 0);
16433: if (err != 0) {
16434: xmlChar *strA = NULL, *strB = NULL;
16435:
16436: if (err == -1)
16437: return(-1);
16438: xmlSchemaCustomErr(ACTXT_CAST ctxt,
16439: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16440: NULL, WXS_BASIC_CAST type,
16441: "The {content type} %s is not validly derived from the "
16442: "base type's {content type} %s",
16443: xmlSchemaGetComponentDesignation(&strA,
16444: type->contentTypeDef),
16445: xmlSchemaGetComponentDesignation(&strB,
16446: base->contentTypeDef));
16447: FREE_AND_NULL(strA);
16448: FREE_AND_NULL(strB);
16449: return(ctxt->err);
16450: }
16451: } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16452: (xmlSchemaIsParticleEmptiable(
16453: (xmlSchemaParticlePtr) base->subtypes))) {
16454: /*
16455: * SPEC (5.2.2.2) "The {base type definition} must be mixed
16456: * and have a particle which is �emptiable� as defined in
16457: * Particle Emptiable (�3.9.6)."
16458: * PASS
16459: */
16460: } else {
16461: xmlSchemaPCustomErr(ctxt,
16462: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16463: WXS_BASIC_CAST type, NULL,
16464: "The content type of the base type must be either "
16465: "a simple type or 'mixed' and an emptiable particle", NULL);
16466: return (ctxt->err);
16467: }
16468: } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16469: /*
16470: * SPEC (5.3.1) "The {content type} of the complex type itself must
16471: * be empty"
16472: */
16473: if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16474: /*
16475: * SPEC (5.3.2.1) "The {content type} of the {base type
16476: * definition} must also be empty."
16477: * PASS
16478: */
16479: } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16480: (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16481: xmlSchemaIsParticleEmptiable(
16482: (xmlSchemaParticlePtr) base->subtypes)) {
16483: /*
16484: * SPEC (5.3.2.2) "The {content type} of the {base type
16485: * definition} must be elementOnly or mixed and have a particle
16486: * which is �emptiable� as defined in Particle Emptiable (�3.9.6)."
16487: * PASS
16488: */
16489: } else {
16490: xmlSchemaPCustomErr(ctxt,
16491: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16492: WXS_BASIC_CAST type, NULL,
16493: "The content type of the base type must be either "
16494: "empty or 'mixed' (or 'elements-only') and an emptiable "
16495: "particle", NULL);
16496: return (ctxt->err);
16497: }
16498: } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16499: WXS_HAS_MIXED_CONTENT(type)) {
16500: /*
16501: * SPEC (5.4.1.1) "The {content type} of the complex type definition
16502: * itself must be element-only"
16503: */
16504: if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16505: /*
16506: * SPEC (5.4.1.2) "The {content type} of the complex type
16507: * definition itself and of the {base type definition} must be
16508: * mixed"
16509: */
16510: xmlSchemaPCustomErr(ctxt,
16511: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16512: WXS_BASIC_CAST type, NULL,
16513: "If the content type is 'mixed', then the content type of the "
16514: "base type must also be 'mixed'", NULL);
16515: return (ctxt->err);
16516: }
16517: /*
16518: * SPEC (5.4.2) "The particle of the complex type definition itself
16519: * must be a �valid restriction� of the particle of the {content
16520: * type} of the {base type definition} as defined in Particle Valid
16521: * (Restriction) (�3.9.6).
16522: *
16523: * URGENT TODO: (5.4.2)
16524: */
16525: } else {
16526: xmlSchemaPCustomErr(ctxt,
16527: XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16528: WXS_BASIC_CAST type, NULL,
16529: "The type is not a valid restriction of its base type", NULL);
16530: return (ctxt->err);
16531: }
16532: return (0);
16533: }
16534:
16535: /**
16536: * xmlSchemaCheckCTComponent:
16537: * @ctxt: the schema parser context
16538: * @type: the complex type definition
16539: *
16540: * (3.4.6) Constraints on Complex Type Definition Schema Components
16541: *
16542: * Returns 0 if the constraints are satisfied, a positive
16543: * error code if not and -1 if an internal error occured.
16544: */
16545: static int
16546: xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16547: xmlSchemaTypePtr type)
16548: {
16549: int ret;
16550: /*
16551: * Complex Type Definition Properties Correct
16552: */
16553: ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16554: if (ret != 0)
16555: return (ret);
16556: if (WXS_IS_EXTENSION(type))
16557: ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16558: else
16559: ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16560: return (ret);
16561: }
16562:
16563: /**
16564: * xmlSchemaCheckSRCCT:
16565: * @ctxt: the schema parser context
16566: * @type: the complex type definition
16567: *
16568: * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16569: * Schema Representation Constraint:
16570: * Complex Type Definition Representation OK (src-ct)
16571: *
16572: * Returns 0 if the constraints are satisfied, a positive
16573: * error code if not and -1 if an internal error occured.
16574: */
16575: static int
16576: xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16577: xmlSchemaTypePtr type)
16578: {
16579: xmlSchemaTypePtr base;
16580: int ret = 0;
16581:
16582: /*
16583: * TODO: Adjust the error codes here, as I used
16584: * XML_SCHEMAP_SRC_CT_1 only yet.
16585: */
16586: base = type->baseType;
16587: if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16588: /*
16589: * 1 If the <complexContent> alternative is chosen, the type definition
16590: * �resolved� to by the �actual value� of the base [attribute]
16591: * must be a complex type definition;
16592: */
16593: if (! WXS_IS_COMPLEX(base)) {
16594: xmlChar *str = NULL;
16595: xmlSchemaPCustomErr(ctxt,
16596: XML_SCHEMAP_SRC_CT_1,
16597: WXS_BASIC_CAST type, type->node,
16598: "If using <complexContent>, the base type is expected to be "
16599: "a complex type. The base type '%s' is a simple type",
16600: xmlSchemaFormatQName(&str, base->targetNamespace,
16601: base->name));
16602: FREE_AND_NULL(str)
16603: return (XML_SCHEMAP_SRC_CT_1);
16604: }
16605: } else {
16606: /*
16607: * SPEC
16608: * 2 If the <simpleContent> alternative is chosen, all of the
16609: * following must be true:
16610: * 2.1 The type definition �resolved� to by the �actual value� of the
16611: * base [attribute] must be one of the following:
16612: */
16613: if (WXS_IS_SIMPLE(base)) {
16614: if (WXS_IS_EXTENSION(type) == 0) {
16615: xmlChar *str = NULL;
16616: /*
16617: * 2.1.3 only if the <extension> alternative is also
16618: * chosen, a simple type definition.
16619: */
16620: /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16621: xmlSchemaPCustomErr(ctxt,
16622: XML_SCHEMAP_SRC_CT_1,
16623: WXS_BASIC_CAST type, NULL,
16624: "If using <simpleContent> and <restriction>, the base "
16625: "type must be a complex type. The base type '%s' is "
16626: "a simple type",
16627: xmlSchemaFormatQName(&str, base->targetNamespace,
16628: base->name));
16629: FREE_AND_NULL(str)
16630: return (XML_SCHEMAP_SRC_CT_1);
16631: }
16632: } else {
16633: /* Base type is a complex type. */
16634: if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16635: (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16636: /*
16637: * 2.1.1 a complex type definition whose {content type} is a
16638: * simple type definition;
16639: * PASS
16640: */
16641: if (base->contentTypeDef == NULL) {
16642: xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16643: WXS_BASIC_CAST type, NULL,
16644: "Internal error: xmlSchemaCheckSRCCT, "
16645: "'%s', base type has no content type",
16646: type->name);
16647: return (-1);
16648: }
16649: } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16650: (WXS_IS_RESTRICTION(type))) {
16651:
16652: /*
16653: * 2.1.2 only if the <restriction> alternative is also
16654: * chosen, a complex type definition whose {content type}
16655: * is mixed and a particle emptiable.
16656: */
16657: if (! xmlSchemaIsParticleEmptiable(
16658: (xmlSchemaParticlePtr) base->subtypes)) {
16659: ret = XML_SCHEMAP_SRC_CT_1;
16660: } else
16661: /*
16662: * Attention: at this point the <simpleType> child is in
16663: * ->contentTypeDef (put there during parsing).
16664: */
16665: if (type->contentTypeDef == NULL) {
16666: xmlChar *str = NULL;
16667: /*
16668: * 2.2 If clause 2.1.2 above is satisfied, then there
16669: * must be a <simpleType> among the [children] of
16670: * <restriction>.
16671: */
16672: /* TODO: Change error code to ..._SRC_CT_2_2. */
16673: xmlSchemaPCustomErr(ctxt,
16674: XML_SCHEMAP_SRC_CT_1,
16675: WXS_BASIC_CAST type, NULL,
16676: "A <simpleType> is expected among the children "
16677: "of <restriction>, if <simpleContent> is used and "
16678: "the base type '%s' is a complex type",
16679: xmlSchemaFormatQName(&str, base->targetNamespace,
16680: base->name));
16681: FREE_AND_NULL(str)
16682: return (XML_SCHEMAP_SRC_CT_1);
16683: }
16684: } else {
16685: ret = XML_SCHEMAP_SRC_CT_1;
16686: }
16687: }
16688: if (ret > 0) {
16689: xmlChar *str = NULL;
16690: if (WXS_IS_RESTRICTION(type)) {
16691: xmlSchemaPCustomErr(ctxt,
16692: XML_SCHEMAP_SRC_CT_1,
16693: WXS_BASIC_CAST type, NULL,
16694: "If <simpleContent> and <restriction> is used, the "
16695: "base type must be a simple type or a complex type with "
16696: "mixed content and particle emptiable. The base type "
16697: "'%s' is none of those",
16698: xmlSchemaFormatQName(&str, base->targetNamespace,
16699: base->name));
16700: } else {
16701: xmlSchemaPCustomErr(ctxt,
16702: XML_SCHEMAP_SRC_CT_1,
16703: WXS_BASIC_CAST type, NULL,
16704: "If <simpleContent> and <extension> is used, the "
16705: "base type must be a simple type. The base type '%s' "
16706: "is a complex type",
16707: xmlSchemaFormatQName(&str, base->targetNamespace,
16708: base->name));
16709: }
16710: FREE_AND_NULL(str)
16711: }
16712: }
16713: /*
16714: * SPEC (3) "The corresponding complex type definition component must
16715: * satisfy the conditions set out in Constraints on Complex Type
16716: * Definition Schema Components (�3.4.6);"
16717: * NOTE (3) will be done in xmlSchemaTypeFixup().
16718: */
16719: /*
16720: * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16721: * above for {attribute wildcard} is satisfied, the intensional
16722: * intersection must be expressible, as defined in Attribute Wildcard
16723: * Intersection (�3.10.6).
16724: * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16725: */
16726: return (ret);
16727: }
16728:
16729: #ifdef ENABLE_PARTICLE_RESTRICTION
16730: /**
16731: * xmlSchemaCheckParticleRangeOK:
16732: * @ctxt: the schema parser context
16733: * @type: the complex type definition
16734: *
16735: * (3.9.6) Constraints on Particle Schema Components
16736: * Schema Component Constraint:
16737: * Occurrence Range OK (range-ok)
16738: *
16739: * STATUS: complete
16740: *
16741: * Returns 0 if the constraints are satisfied, a positive
16742: * error code if not and -1 if an internal error occured.
16743: */
16744: static int
16745: xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16746: int bmin, int bmax)
16747: {
16748: if (rmin < bmin)
16749: return (1);
16750: if ((bmax != UNBOUNDED) &&
16751: (rmax > bmax))
16752: return (1);
16753: return (0);
16754: }
16755:
16756: /**
16757: * xmlSchemaCheckRCaseNameAndTypeOK:
16758: * @ctxt: the schema parser context
16759: * @r: the restricting element declaration particle
16760: * @b: the base element declaration particle
16761: *
16762: * (3.9.6) Constraints on Particle Schema Components
16763: * Schema Component Constraint:
16764: * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16765: * (rcase-NameAndTypeOK)
16766: *
16767: * STATUS:
16768: * MISSING (3.2.3)
16769: * CLARIFY: (3.2.2)
16770: *
16771: * Returns 0 if the constraints are satisfied, a positive
16772: * error code if not and -1 if an internal error occured.
16773: */
16774: static int
16775: xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16776: xmlSchemaParticlePtr r,
16777: xmlSchemaParticlePtr b)
16778: {
16779: xmlSchemaElementPtr elemR, elemB;
16780:
16781: /* TODO: Error codes (rcase-NameAndTypeOK). */
16782: elemR = (xmlSchemaElementPtr) r->children;
16783: elemB = (xmlSchemaElementPtr) b->children;
16784: /*
16785: * SPEC (1) "The declarations' {name}s and {target namespace}s are
16786: * the same."
16787: */
16788: if ((elemR != elemB) &&
16789: ((! xmlStrEqual(elemR->name, elemB->name)) ||
16790: (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16791: return (1);
16792: /*
16793: * SPEC (2) "R's occurrence range is a valid restriction of B's
16794: * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16795: */
16796: if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16797: b->minOccurs, b->maxOccurs) != 0)
16798: return (1);
16799: /*
16800: * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16801: * {scope} are global."
16802: */
16803: if (elemR == elemB)
16804: return (0);
16805: /*
16806: * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16807: */
16808: if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16809: (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16810: return (1);
16811: /*
16812: * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16813: * or is not fixed, or R's declaration's {value constraint} is fixed
16814: * with the same value."
16815: */
16816: if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16817: ((elemR->value == NULL) ||
16818: ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16819: /* TODO: Equality of the initial value or normalized or canonical? */
16820: (! xmlStrEqual(elemR->value, elemB->value))))
16821: return (1);
16822: /*
16823: * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16824: * definitions} is a subset of B's declaration's {identity-constraint
16825: * definitions}, if any."
16826: */
16827: if (elemB->idcs != NULL) {
16828: /* TODO */
16829: }
16830: /*
16831: * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16832: * superset of B's declaration's {disallowed substitutions}."
16833: */
16834: if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16835: ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16836: ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16837: ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16838: ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16839: ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16840: return (1);
16841: /*
16842: * SPEC (3.2.5) "R's {type definition} is validly derived given
16843: * {extension, list, union} from B's {type definition}"
16844: *
16845: * BADSPEC TODO: What's the point of adding "list" and "union" to the
16846: * set, if the corresponding constraints handle "restriction" and
16847: * "extension" only?
16848: *
16849: */
16850: {
16851: int set = 0;
16852:
16853: set |= SUBSET_EXTENSION;
16854: set |= SUBSET_LIST;
16855: set |= SUBSET_UNION;
16856: if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16857: elemB->subtypes, set) != 0)
16858: return (1);
16859: }
16860: return (0);
16861: }
16862:
16863: /**
16864: * xmlSchemaCheckRCaseNSCompat:
16865: * @ctxt: the schema parser context
16866: * @r: the restricting element declaration particle
16867: * @b: the base wildcard particle
16868: *
16869: * (3.9.6) Constraints on Particle Schema Components
16870: * Schema Component Constraint:
16871: * Particle Derivation OK (Elt:Any -- NSCompat)
16872: * (rcase-NSCompat)
16873: *
16874: * STATUS: complete
16875: *
16876: * Returns 0 if the constraints are satisfied, a positive
16877: * error code if not and -1 if an internal error occured.
16878: */
16879: static int
16880: xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16881: xmlSchemaParticlePtr r,
16882: xmlSchemaParticlePtr b)
16883: {
16884: /* TODO:Error codes (rcase-NSCompat). */
16885: /*
16886: * SPEC "For an element declaration particle to be a �valid restriction�
16887: * of a wildcard particle all of the following must be true:"
16888: *
16889: * SPEC (1) "The element declaration's {target namespace} is �valid�
16890: * with respect to the wildcard's {namespace constraint} as defined by
16891: * Wildcard allows Namespace Name (�3.10.4)."
16892: */
16893: if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16894: ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16895: return (1);
16896: /*
16897: * SPEC (2) "R's occurrence range is a valid restriction of B's
16898: * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16899: */
16900: if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16901: b->minOccurs, b->maxOccurs) != 0)
16902: return (1);
16903:
16904: return (0);
16905: }
16906:
16907: /**
16908: * xmlSchemaCheckRCaseRecurseAsIfGroup:
16909: * @ctxt: the schema parser context
16910: * @r: the restricting element declaration particle
16911: * @b: the base model group particle
16912: *
16913: * (3.9.6) Constraints on Particle Schema Components
16914: * Schema Component Constraint:
16915: * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16916: * (rcase-RecurseAsIfGroup)
16917: *
16918: * STATUS: TODO
16919: *
16920: * Returns 0 if the constraints are satisfied, a positive
16921: * error code if not and -1 if an internal error occured.
16922: */
16923: static int
16924: xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16925: xmlSchemaParticlePtr r,
16926: xmlSchemaParticlePtr b)
16927: {
16928: /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16929: TODO
16930: return (0);
16931: }
16932:
16933: /**
16934: * xmlSchemaCheckRCaseNSSubset:
16935: * @ctxt: the schema parser context
16936: * @r: the restricting wildcard particle
16937: * @b: the base wildcard particle
16938: *
16939: * (3.9.6) Constraints on Particle Schema Components
16940: * Schema Component Constraint:
16941: * Particle Derivation OK (Any:Any -- NSSubset)
16942: * (rcase-NSSubset)
16943: *
16944: * STATUS: complete
16945: *
16946: * Returns 0 if the constraints are satisfied, a positive
16947: * error code if not and -1 if an internal error occured.
16948: */
16949: static int
16950: xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16951: xmlSchemaParticlePtr r,
16952: xmlSchemaParticlePtr b,
16953: int isAnyTypeBase)
16954: {
16955: /* TODO: Error codes (rcase-NSSubset). */
16956: /*
16957: * SPEC (1) "R's occurrence range is a valid restriction of B's
16958: * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16959: */
16960: if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16961: b->minOccurs, b->maxOccurs))
16962: return (1);
16963: /*
16964: * SPEC (2) "R's {namespace constraint} must be an intensional subset
16965: * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16966: */
16967: if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16968: (xmlSchemaWildcardPtr) b->children))
16969: return (1);
16970: /*
16971: * SPEC (3) "Unless B is the content model wildcard of the �ur-type
16972: * definition�, R's {process contents} must be identical to or stronger
16973: * than B's {process contents}, where strict is stronger than lax is
16974: * stronger than skip."
16975: */
16976: if (! isAnyTypeBase) {
16977: if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16978: ((xmlSchemaWildcardPtr) b->children)->processContents)
16979: return (1);
16980: }
16981:
16982: return (0);
16983: }
16984:
16985: /**
16986: * xmlSchemaCheckCOSParticleRestrict:
16987: * @ctxt: the schema parser context
16988: * @type: the complex type definition
16989: *
16990: * (3.9.6) Constraints on Particle Schema Components
16991: * Schema Component Constraint:
16992: * Particle Valid (Restriction) (cos-particle-restrict)
16993: *
16994: * STATUS: TODO
16995: *
16996: * Returns 0 if the constraints are satisfied, a positive
16997: * error code if not and -1 if an internal error occured.
16998: */
16999: static int
17000: xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17001: xmlSchemaParticlePtr r,
17002: xmlSchemaParticlePtr b)
17003: {
17004: int ret = 0;
17005:
17006: /*part = WXS_TYPE_PARTICLE(type);
17007: basePart = WXS_TYPE_PARTICLE(base);
17008: */
17009:
17010: TODO
17011:
17012: /*
17013: * SPEC (1) "They are the same particle."
17014: */
17015: if (r == b)
17016: return (0);
17017:
17018:
17019: return (0);
17020: }
17021:
17022: #if 0
17023: /**
17024: * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17025: * @ctxt: the schema parser context
17026: * @r: the model group particle
17027: * @b: the base wildcard particle
17028: *
17029: * (3.9.6) Constraints on Particle Schema Components
17030: * Schema Component Constraint:
17031: * Particle Derivation OK (All/Choice/Sequence:Any --
17032: * NSRecurseCheckCardinality)
17033: * (rcase-NSRecurseCheckCardinality)
17034: *
17035: * STATUS: TODO: subst-groups
17036: *
17037: * Returns 0 if the constraints are satisfied, a positive
17038: * error code if not and -1 if an internal error occured.
17039: */
17040: static int
17041: xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17042: xmlSchemaParticlePtr r,
17043: xmlSchemaParticlePtr b)
17044: {
17045: xmlSchemaParticlePtr part;
17046: /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17047: if ((r->children == NULL) || (r->children->children == NULL))
17048: return (-1);
17049: /*
17050: * SPEC "For a group particle to be a �valid restriction� of a
17051: * wildcard particle..."
17052: *
17053: * SPEC (1) "Every member of the {particles} of the group is a �valid
17054: * restriction� of the wildcard as defined by
17055: * Particle Valid (Restriction) (�3.9.6)."
17056: */
17057: part = (xmlSchemaParticlePtr) r->children->children;
17058: do {
17059: if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17060: return (1);
17061: part = (xmlSchemaParticlePtr) part->next;
17062: } while (part != NULL);
17063: /*
17064: * SPEC (2) "The effective total range of the group [...] is a
17065: * valid restriction of B's occurrence range as defined by
17066: * Occurrence Range OK (�3.9.6)."
17067: */
17068: if (xmlSchemaCheckParticleRangeOK(
17069: xmlSchemaGetParticleTotalRangeMin(r),
17070: xmlSchemaGetParticleTotalRangeMax(r),
17071: b->minOccurs, b->maxOccurs) != 0)
17072: return (1);
17073: return (0);
17074: }
17075: #endif
17076:
17077: /**
17078: * xmlSchemaCheckRCaseRecurse:
17079: * @ctxt: the schema parser context
17080: * @r: the <all> or <sequence> model group particle
17081: * @b: the base <all> or <sequence> model group particle
17082: *
17083: * (3.9.6) Constraints on Particle Schema Components
17084: * Schema Component Constraint:
17085: * Particle Derivation OK (All:All,Sequence:Sequence --
17086: Recurse)
17087: * (rcase-Recurse)
17088: *
17089: * STATUS: ?
17090: * TODO: subst-groups
17091: *
17092: * Returns 0 if the constraints are satisfied, a positive
17093: * error code if not and -1 if an internal error occured.
17094: */
17095: static int
17096: xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17097: xmlSchemaParticlePtr r,
17098: xmlSchemaParticlePtr b)
17099: {
17100: /* xmlSchemaParticlePtr part; */
17101: /* TODO: Error codes (rcase-Recurse). */
17102: if ((r->children == NULL) || (b->children == NULL) ||
17103: (r->children->type != b->children->type))
17104: return (-1);
17105: /*
17106: * SPEC "For an all or sequence group particle to be a �valid
17107: * restriction� of another group particle with the same {compositor}..."
17108: *
17109: * SPEC (1) "R's occurrence range is a valid restriction of B's
17110: * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17111: */
17112: if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17113: b->minOccurs, b->maxOccurs))
17114: return (1);
17115:
17116:
17117: return (0);
17118: }
17119:
17120: #endif
17121:
17122: #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17123: xmlSchemaPCustomErrExt(pctxt, \
17124: XML_SCHEMAP_INVALID_FACET_VALUE, \
17125: WXS_BASIC_CAST fac1, fac1->node, \
17126: "It is an error for both '%s' and '%s' to be specified on the "\
17127: "same type definition", \
17128: BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17129: BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17130:
17131: #define FACET_RESTR_ERR(fac1, msg) \
17132: xmlSchemaPCustomErr(pctxt, \
17133: XML_SCHEMAP_INVALID_FACET_VALUE, \
17134: WXS_BASIC_CAST fac1, fac1->node, \
17135: msg, NULL);
17136:
17137: #define FACET_RESTR_FIXED_ERR(fac) \
17138: xmlSchemaPCustomErr(pctxt, \
17139: XML_SCHEMAP_INVALID_FACET_VALUE, \
17140: WXS_BASIC_CAST fac, fac->node, \
17141: "The base type's facet is 'fixed', thus the value must not " \
17142: "differ", NULL);
17143:
17144: static void
17145: xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17146: xmlSchemaFacetPtr facet1,
17147: xmlSchemaFacetPtr facet2,
17148: int lessGreater,
17149: int orEqual,
17150: int ofBase)
17151: {
17152: xmlChar *msg = NULL;
17153:
17154: msg = xmlStrdup(BAD_CAST "'");
17155: msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17156: msg = xmlStrcat(msg, BAD_CAST "' has to be");
17157: if (lessGreater == 0)
17158: msg = xmlStrcat(msg, BAD_CAST " equal to");
17159: if (lessGreater == 1)
17160: msg = xmlStrcat(msg, BAD_CAST " greater than");
17161: else
17162: msg = xmlStrcat(msg, BAD_CAST " less than");
17163:
17164: if (orEqual)
17165: msg = xmlStrcat(msg, BAD_CAST " or equal to");
17166: msg = xmlStrcat(msg, BAD_CAST " '");
17167: msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17168: if (ofBase)
17169: msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17170: else
17171: msg = xmlStrcat(msg, BAD_CAST "'");
17172:
17173: xmlSchemaPCustomErr(pctxt,
17174: XML_SCHEMAP_INVALID_FACET_VALUE,
17175: WXS_BASIC_CAST facet1, NULL,
17176: (const char *) msg, NULL);
17177:
17178: if (msg != NULL)
17179: xmlFree(msg);
17180: }
17181:
17182: /*
17183: * xmlSchemaDeriveAndValidateFacets:
17184: *
17185: * Schema Component Constraint: Simple Type Restriction (Facets)
17186: * (st-restrict-facets)
17187: */
17188: static int
17189: xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17190: xmlSchemaTypePtr type)
17191: {
17192: xmlSchemaTypePtr base = type->baseType;
17193: xmlSchemaFacetLinkPtr link, cur, last = NULL;
17194: xmlSchemaFacetPtr facet, bfacet,
17195: flength = NULL, ftotdig = NULL, ffracdig = NULL,
17196: fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17197: fmininc = NULL, fmaxinc = NULL,
17198: fminexc = NULL, fmaxexc = NULL,
17199: bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17200: bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17201: bfmininc = NULL, bfmaxinc = NULL,
17202: bfminexc = NULL, bfmaxexc = NULL;
17203: int res; /* err = 0, fixedErr; */
17204:
17205: /*
17206: * SPEC st-restrict-facets 1:
17207: * "The {variety} of R is the same as that of B."
17208: */
17209: /*
17210: * SPEC st-restrict-facets 2:
17211: * "If {variety} is atomic, the {primitive type definition}
17212: * of R is the same as that of B."
17213: *
17214: * NOTE: we leave 1 & 2 out for now, since this will be
17215: * satisfied by the derivation process.
17216: * CONSTRUCTION TODO: Maybe needed if using a construction API.
17217: */
17218: /*
17219: * SPEC st-restrict-facets 3:
17220: * "The {facets} of R are the union of S and the {facets}
17221: * of B, eliminating duplicates. To eliminate duplicates,
17222: * when a facet of the same kind occurs in both S and the
17223: * {facets} of B, the one in the {facets} of B is not
17224: * included, with the exception of enumeration and pattern
17225: * facets, for which multiple occurrences with distinct values
17226: * are allowed."
17227: */
17228:
17229: if ((type->facetSet == NULL) && (base->facetSet == NULL))
17230: return (0);
17231:
17232: last = type->facetSet;
17233: if (last != NULL)
17234: while (last->next != NULL)
17235: last = last->next;
17236:
17237: for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17238: facet = cur->facet;
17239: switch (facet->type) {
17240: case XML_SCHEMA_FACET_LENGTH:
17241: flength = facet; break;
17242: case XML_SCHEMA_FACET_MINLENGTH:
17243: fminlen = facet; break;
17244: case XML_SCHEMA_FACET_MININCLUSIVE:
17245: fmininc = facet; break;
17246: case XML_SCHEMA_FACET_MINEXCLUSIVE:
17247: fminexc = facet; break;
17248: case XML_SCHEMA_FACET_MAXLENGTH:
17249: fmaxlen = facet; break;
17250: case XML_SCHEMA_FACET_MAXINCLUSIVE:
17251: fmaxinc = facet; break;
17252: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17253: fmaxexc = facet; break;
17254: case XML_SCHEMA_FACET_TOTALDIGITS:
17255: ftotdig = facet; break;
17256: case XML_SCHEMA_FACET_FRACTIONDIGITS:
17257: ffracdig = facet; break;
17258: default:
17259: break;
17260: }
17261: }
17262: for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17263: facet = cur->facet;
17264: switch (facet->type) {
17265: case XML_SCHEMA_FACET_LENGTH:
17266: bflength = facet; break;
17267: case XML_SCHEMA_FACET_MINLENGTH:
17268: bfminlen = facet; break;
17269: case XML_SCHEMA_FACET_MININCLUSIVE:
17270: bfmininc = facet; break;
17271: case XML_SCHEMA_FACET_MINEXCLUSIVE:
17272: bfminexc = facet; break;
17273: case XML_SCHEMA_FACET_MAXLENGTH:
17274: bfmaxlen = facet; break;
17275: case XML_SCHEMA_FACET_MAXINCLUSIVE:
17276: bfmaxinc = facet; break;
17277: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17278: bfmaxexc = facet; break;
17279: case XML_SCHEMA_FACET_TOTALDIGITS:
17280: bftotdig = facet; break;
17281: case XML_SCHEMA_FACET_FRACTIONDIGITS:
17282: bffracdig = facet; break;
17283: default:
17284: break;
17285: }
17286: }
17287: /*
17288: * length and minLength or maxLength (2.2) + (3.2)
17289: */
17290: if (flength && (fminlen || fmaxlen)) {
17291: FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17292: "either of 'minLength' or 'maxLength' to be specified on "
17293: "the same type definition")
17294: }
17295: /*
17296: * Mutual exclusions in the same derivation step.
17297: */
17298: if ((fmaxinc) && (fmaxexc)) {
17299: /*
17300: * SCC "maxInclusive and maxExclusive"
17301: */
17302: FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17303: }
17304: if ((fmininc) && (fminexc)) {
17305: /*
17306: * SCC "minInclusive and minExclusive"
17307: */
17308: FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17309: }
17310:
17311: if (flength && bflength) {
17312: /*
17313: * SCC "length valid restriction"
17314: * The values have to be equal.
17315: */
17316: res = xmlSchemaCompareValues(flength->val, bflength->val);
17317: if (res == -2)
17318: goto internal_error;
17319: if (res != 0)
17320: xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17321: if ((res != 0) && (bflength->fixed)) {
17322: FACET_RESTR_FIXED_ERR(flength)
17323: }
17324:
17325: }
17326: if (fminlen && bfminlen) {
17327: /*
17328: * SCC "minLength valid restriction"
17329: * minLength >= BASE minLength
17330: */
17331: res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17332: if (res == -2)
17333: goto internal_error;
17334: if (res == -1)
17335: xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17336: if ((res != 0) && (bfminlen->fixed)) {
17337: FACET_RESTR_FIXED_ERR(fminlen)
17338: }
17339: }
17340: if (fmaxlen && bfmaxlen) {
17341: /*
17342: * SCC "maxLength valid restriction"
17343: * maxLength <= BASE minLength
17344: */
17345: res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17346: if (res == -2)
17347: goto internal_error;
17348: if (res == 1)
17349: xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17350: if ((res != 0) && (bfmaxlen->fixed)) {
17351: FACET_RESTR_FIXED_ERR(fmaxlen)
17352: }
17353: }
17354: /*
17355: * SCC "length and minLength or maxLength"
17356: */
17357: if (! flength)
17358: flength = bflength;
17359: if (flength) {
17360: if (! fminlen)
17361: fminlen = bfminlen;
17362: if (fminlen) {
17363: /* (1.1) length >= minLength */
17364: res = xmlSchemaCompareValues(flength->val, fminlen->val);
17365: if (res == -2)
17366: goto internal_error;
17367: if (res == -1)
17368: xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17369: }
17370: if (! fmaxlen)
17371: fmaxlen = bfmaxlen;
17372: if (fmaxlen) {
17373: /* (2.1) length <= maxLength */
17374: res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17375: if (res == -2)
17376: goto internal_error;
17377: if (res == 1)
17378: xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17379: }
17380: }
17381: if (fmaxinc) {
17382: /*
17383: * "maxInclusive"
17384: */
17385: if (fmininc) {
17386: /* SCC "maxInclusive >= minInclusive" */
17387: res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17388: if (res == -2)
17389: goto internal_error;
17390: if (res == -1) {
17391: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17392: }
17393: }
17394: /*
17395: * SCC "maxInclusive valid restriction"
17396: */
17397: if (bfmaxinc) {
17398: /* maxInclusive <= BASE maxInclusive */
17399: res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17400: if (res == -2)
17401: goto internal_error;
17402: if (res == 1)
17403: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17404: if ((res != 0) && (bfmaxinc->fixed)) {
17405: FACET_RESTR_FIXED_ERR(fmaxinc)
17406: }
17407: }
17408: if (bfmaxexc) {
17409: /* maxInclusive < BASE maxExclusive */
17410: res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17411: if (res == -2)
17412: goto internal_error;
17413: if (res != -1) {
17414: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17415: }
17416: }
17417: if (bfmininc) {
17418: /* maxInclusive >= BASE minInclusive */
17419: res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17420: if (res == -2)
17421: goto internal_error;
17422: if (res == -1) {
17423: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17424: }
17425: }
17426: if (bfminexc) {
17427: /* maxInclusive > BASE minExclusive */
17428: res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17429: if (res == -2)
17430: goto internal_error;
17431: if (res != 1) {
17432: xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17433: }
17434: }
17435: }
17436: if (fmaxexc) {
17437: /*
17438: * "maxExclusive >= minExclusive"
17439: */
17440: if (fminexc) {
17441: res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17442: if (res == -2)
17443: goto internal_error;
17444: if (res == -1) {
17445: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17446: }
17447: }
17448: /*
17449: * "maxExclusive valid restriction"
17450: */
17451: if (bfmaxexc) {
17452: /* maxExclusive <= BASE maxExclusive */
17453: res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17454: if (res == -2)
17455: goto internal_error;
17456: if (res == 1) {
17457: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17458: }
17459: if ((res != 0) && (bfmaxexc->fixed)) {
17460: FACET_RESTR_FIXED_ERR(fmaxexc)
17461: }
17462: }
17463: if (bfmaxinc) {
17464: /* maxExclusive <= BASE maxInclusive */
17465: res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17466: if (res == -2)
17467: goto internal_error;
17468: if (res == 1) {
17469: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17470: }
17471: }
17472: if (bfmininc) {
17473: /* maxExclusive > BASE minInclusive */
17474: res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17475: if (res == -2)
17476: goto internal_error;
17477: if (res != 1) {
17478: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17479: }
17480: }
17481: if (bfminexc) {
17482: /* maxExclusive > BASE minExclusive */
17483: res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17484: if (res == -2)
17485: goto internal_error;
17486: if (res != 1) {
17487: xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17488: }
17489: }
17490: }
17491: if (fminexc) {
17492: /*
17493: * "minExclusive < maxInclusive"
17494: */
17495: if (fmaxinc) {
17496: res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17497: if (res == -2)
17498: goto internal_error;
17499: if (res != -1) {
17500: xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17501: }
17502: }
17503: /*
17504: * "minExclusive valid restriction"
17505: */
17506: if (bfminexc) {
17507: /* minExclusive >= BASE minExclusive */
17508: res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17509: if (res == -2)
17510: goto internal_error;
17511: if (res == -1) {
17512: xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17513: }
17514: if ((res != 0) && (bfminexc->fixed)) {
17515: FACET_RESTR_FIXED_ERR(fminexc)
17516: }
17517: }
17518: if (bfmaxinc) {
17519: /* minExclusive <= BASE maxInclusive */
17520: res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17521: if (res == -2)
17522: goto internal_error;
17523: if (res == 1) {
17524: xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17525: }
17526: }
17527: if (bfmininc) {
17528: /* minExclusive >= BASE minInclusive */
17529: res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17530: if (res == -2)
17531: goto internal_error;
17532: if (res == -1) {
17533: xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17534: }
17535: }
17536: if (bfmaxexc) {
17537: /* minExclusive < BASE maxExclusive */
17538: res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17539: if (res == -2)
17540: goto internal_error;
17541: if (res != -1) {
17542: xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17543: }
17544: }
17545: }
17546: if (fmininc) {
17547: /*
17548: * "minInclusive < maxExclusive"
17549: */
17550: if (fmaxexc) {
17551: res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17552: if (res == -2)
17553: goto internal_error;
17554: if (res != -1) {
17555: xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17556: }
17557: }
17558: /*
17559: * "minExclusive valid restriction"
17560: */
17561: if (bfmininc) {
17562: /* minInclusive >= BASE minInclusive */
17563: res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17564: if (res == -2)
17565: goto internal_error;
17566: if (res == -1) {
17567: xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17568: }
17569: if ((res != 0) && (bfmininc->fixed)) {
17570: FACET_RESTR_FIXED_ERR(fmininc)
17571: }
17572: }
17573: if (bfmaxinc) {
17574: /* minInclusive <= BASE maxInclusive */
17575: res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17576: if (res == -2)
17577: goto internal_error;
17578: if (res == 1) {
17579: xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17580: }
17581: }
17582: if (bfminexc) {
17583: /* minInclusive > BASE minExclusive */
17584: res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17585: if (res == -2)
17586: goto internal_error;
17587: if (res != 1)
17588: xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17589: }
17590: if (bfmaxexc) {
17591: /* minInclusive < BASE maxExclusive */
17592: res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17593: if (res == -2)
17594: goto internal_error;
17595: if (res != -1)
17596: xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17597: }
17598: }
17599: if (ftotdig && bftotdig) {
17600: /*
17601: * SCC " totalDigits valid restriction"
17602: * totalDigits <= BASE totalDigits
17603: */
17604: res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17605: if (res == -2)
17606: goto internal_error;
17607: if (res == 1)
17608: xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17609: -1, 1, 1);
17610: if ((res != 0) && (bftotdig->fixed)) {
17611: FACET_RESTR_FIXED_ERR(ftotdig)
17612: }
17613: }
17614: if (ffracdig && bffracdig) {
17615: /*
17616: * SCC "fractionDigits valid restriction"
17617: * fractionDigits <= BASE fractionDigits
17618: */
17619: res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17620: if (res == -2)
17621: goto internal_error;
17622: if (res == 1)
17623: xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17624: -1, 1, 1);
17625: if ((res != 0) && (bffracdig->fixed)) {
17626: FACET_RESTR_FIXED_ERR(ffracdig)
17627: }
17628: }
17629: /*
17630: * SCC "fractionDigits less than or equal to totalDigits"
17631: */
17632: if (! ftotdig)
17633: ftotdig = bftotdig;
17634: if (! ffracdig)
17635: ffracdig = bffracdig;
17636: if (ftotdig && ffracdig) {
17637: res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17638: if (res == -2)
17639: goto internal_error;
17640: if (res == 1)
17641: xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17642: -1, 1, 0);
17643: }
17644: /*
17645: * *Enumerations* won' be added here, since only the first set
17646: * of enumerations in the ancestor-or-self axis is used
17647: * for validation, plus we need to use the base type of those
17648: * enumerations for whitespace.
17649: *
17650: * *Patterns*: won't be add here, since they are ORed at
17651: * type level and ANDed at ancestor level. This will
17652: * happed during validation by walking the base axis
17653: * of the type.
17654: */
17655: for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17656: bfacet = cur->facet;
17657: /*
17658: * Special handling of enumerations and patterns.
17659: * TODO: hmm, they should not appear in the set, so remove this.
17660: */
17661: if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17662: (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17663: continue;
17664: /*
17665: * Search for a duplicate facet in the current type.
17666: */
17667: link = type->facetSet;
17668: /* err = 0; */
17669: /* fixedErr = 0; */
17670: while (link != NULL) {
17671: facet = link->facet;
17672: if (facet->type == bfacet->type) {
17673: switch (facet->type) {
17674: case XML_SCHEMA_FACET_WHITESPACE:
17675: /*
17676: * The whitespace must be stronger.
17677: */
17678: if (facet->whitespace < bfacet->whitespace) {
17679: FACET_RESTR_ERR(facet,
17680: "The 'whitespace' value has to be equal to "
17681: "or stronger than the 'whitespace' value of "
17682: "the base type")
17683: }
17684: if ((bfacet->fixed) &&
17685: (facet->whitespace != bfacet->whitespace)) {
17686: FACET_RESTR_FIXED_ERR(facet)
17687: }
17688: break;
17689: default:
17690: break;
17691: }
17692: /* Duplicate found. */
17693: break;
17694: }
17695: link = link->next;
17696: }
17697: /*
17698: * If no duplicate was found: add the base types's facet
17699: * to the set.
17700: */
17701: if (link == NULL) {
17702: link = (xmlSchemaFacetLinkPtr)
17703: xmlMalloc(sizeof(xmlSchemaFacetLink));
17704: if (link == NULL) {
17705: xmlSchemaPErrMemory(pctxt,
17706: "deriving facets, creating a facet link", NULL);
17707: return (-1);
17708: }
17709: link->facet = cur->facet;
17710: link->next = NULL;
17711: if (last == NULL)
17712: type->facetSet = link;
17713: else
17714: last->next = link;
17715: last = link;
17716: }
17717:
17718: }
17719:
17720: return (0);
17721: internal_error:
17722: PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17723: "an error occured");
17724: return (-1);
17725: }
17726:
17727: static int
17728: xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17729: xmlSchemaTypePtr type)
17730: {
17731: xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17732: /*
17733: * The actual value is then formed by replacing any union type
17734: * definition in the �explicit members� with the members of their
17735: * {member type definitions}, in order.
17736: *
17737: * TODO: There's a bug entry at
17738: * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17739: * which indicates that we'll keep the union types the future.
17740: */
17741: link = type->memberTypes;
17742: while (link != NULL) {
17743:
17744: if (WXS_IS_TYPE_NOT_FIXED(link->type))
17745: xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17746:
17747: if (WXS_IS_UNION(link->type)) {
17748: subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17749: if (subLink != NULL) {
17750: link->type = subLink->type;
17751: if (subLink->next != NULL) {
17752: lastLink = link->next;
17753: subLink = subLink->next;
17754: prevLink = link;
17755: while (subLink != NULL) {
17756: newLink = (xmlSchemaTypeLinkPtr)
17757: xmlMalloc(sizeof(xmlSchemaTypeLink));
17758: if (newLink == NULL) {
17759: xmlSchemaPErrMemory(pctxt, "allocating a type link",
17760: NULL);
17761: return (-1);
17762: }
17763: newLink->type = subLink->type;
17764: prevLink->next = newLink;
17765: prevLink = newLink;
17766: newLink->next = lastLink;
17767:
17768: subLink = subLink->next;
17769: }
17770: }
17771: }
17772: }
17773: link = link->next;
17774: }
17775: return (0);
17776: }
17777:
17778: static void
17779: xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17780: {
17781: int has = 0, needVal = 0, normVal = 0;
17782:
17783: has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17784: if (has) {
17785: needVal = (type->baseType->flags &
17786: XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17787: normVal = (type->baseType->flags &
17788: XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17789: }
17790: if (type->facets != NULL) {
17791: xmlSchemaFacetPtr fac;
17792:
17793: for (fac = type->facets; fac != NULL; fac = fac->next) {
17794: switch (fac->type) {
17795: case XML_SCHEMA_FACET_WHITESPACE:
17796: break;
17797: case XML_SCHEMA_FACET_PATTERN:
17798: normVal = 1;
17799: has = 1;
17800: break;
17801: case XML_SCHEMA_FACET_ENUMERATION:
17802: needVal = 1;
17803: normVal = 1;
17804: has = 1;
17805: break;
17806: default:
17807: has = 1;
17808: break;
17809: }
17810: }
17811: }
17812: if (normVal)
17813: type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17814: if (needVal)
17815: type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17816: if (has)
17817: type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17818:
17819: if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17820: xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17821: /*
17822: * OPTIMIZE VAL TODO: Some facets need a computed value.
17823: */
17824: if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17825: (prim->builtInType != XML_SCHEMAS_STRING)) {
17826: type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17827: }
17828: }
17829: }
17830:
17831: static int
17832: xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17833: {
17834:
17835:
17836: /*
17837: * Evaluate the whitespace-facet value.
17838: */
17839: if (WXS_IS_LIST(type)) {
17840: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17841: return (0);
17842: } else if (WXS_IS_UNION(type))
17843: return (0);
17844:
17845: if (type->facetSet != NULL) {
17846: xmlSchemaFacetLinkPtr lin;
17847:
17848: for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17849: if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17850: switch (lin->facet->whitespace) {
17851: case XML_SCHEMAS_FACET_PRESERVE:
17852: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17853: break;
17854: case XML_SCHEMAS_FACET_REPLACE:
17855: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17856: break;
17857: case XML_SCHEMAS_FACET_COLLAPSE:
17858: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17859: break;
17860: default:
17861: return (-1);
17862: }
17863: return (0);
17864: }
17865: }
17866: }
17867: /*
17868: * For all �atomic� datatypes other than string (and types �derived�
17869: * by �restriction� from it) the value of whiteSpace is fixed to
17870: * collapse
17871: */
17872: {
17873: xmlSchemaTypePtr anc;
17874:
17875: for (anc = type->baseType; anc != NULL &&
17876: anc->builtInType != XML_SCHEMAS_ANYTYPE;
17877: anc = anc->baseType) {
17878:
17879: if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17880: if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17881: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17882:
17883: } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17884: (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17885: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17886:
17887: } else
17888: type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17889: break;
17890: }
17891: }
17892: }
17893: return (0);
17894: }
17895:
17896: static int
17897: xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17898: xmlSchemaTypePtr type)
17899: {
17900: if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17901: return(0);
17902: if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17903: return(0);
17904: type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17905:
17906: if (WXS_IS_LIST(type)) {
17907: /*
17908: * Corresponds to <simpleType><list>...
17909: */
17910: if (type->subtypes == NULL) {
17911: /*
17912: * This one is really needed, so get out.
17913: */
17914: PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17915: "list type has no item-type assigned");
17916: return(-1);
17917: }
17918: } else if (WXS_IS_UNION(type)) {
17919: /*
17920: * Corresponds to <simpleType><union>...
17921: */
17922: if (type->memberTypes == NULL) {
17923: /*
17924: * This one is really needed, so get out.
17925: */
17926: PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17927: "union type has no member-types assigned");
17928: return(-1);
17929: }
17930: } else {
17931: /*
17932: * Corresponds to <simpleType><restriction>...
17933: */
17934: if (type->baseType == NULL) {
17935: PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17936: "type has no base-type assigned");
17937: return(-1);
17938: }
17939: if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17940: if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17941: return(-1);
17942: /*
17943: * Variety
17944: * If the <restriction> alternative is chosen, then the
17945: * {variety} of the {base type definition}.
17946: */
17947: if (WXS_IS_ATOMIC(type->baseType))
17948: type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17949: else if (WXS_IS_LIST(type->baseType)) {
17950: type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17951: /*
17952: * Inherit the itemType.
17953: */
17954: type->subtypes = type->baseType->subtypes;
17955: } else if (WXS_IS_UNION(type->baseType)) {
17956: type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17957: /*
17958: * NOTE that we won't assign the memberTypes of the base,
17959: * since this will make trouble when freeing them; we will
17960: * use a lookup function to access them instead.
17961: */
17962: }
17963: }
17964: return(0);
17965: }
17966:
17967: #ifdef DEBUG_TYPE
17968: static void
17969: xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17970: xmlSchemaTypePtr type)
17971: {
17972: if (type->node != NULL) {
17973: xmlGenericError(xmlGenericErrorContext,
17974: "Type of %s : %s:%d :", name,
17975: type->node->doc->URL,
17976: xmlGetLineNo(type->node));
17977: } else {
17978: xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
17979: }
17980: if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
17981: switch (type->contentType) {
17982: case XML_SCHEMA_CONTENT_SIMPLE:
17983: xmlGenericError(xmlGenericErrorContext, "simple\n");
17984: break;
17985: case XML_SCHEMA_CONTENT_ELEMENTS:
17986: xmlGenericError(xmlGenericErrorContext, "elements\n");
17987: break;
17988: case XML_SCHEMA_CONTENT_UNKNOWN:
17989: xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17990: break;
17991: case XML_SCHEMA_CONTENT_EMPTY:
17992: xmlGenericError(xmlGenericErrorContext, "empty\n");
17993: break;
17994: case XML_SCHEMA_CONTENT_MIXED:
17995: if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
17996: type->subtypes))
17997: xmlGenericError(xmlGenericErrorContext,
17998: "mixed as emptiable particle\n");
17999: else
18000: xmlGenericError(xmlGenericErrorContext, "mixed\n");
18001: break;
18002: /* Removed, since not used. */
18003: /*
18004: case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18005: xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18006: break;
18007: */
18008: case XML_SCHEMA_CONTENT_BASIC:
18009: xmlGenericError(xmlGenericErrorContext, "basic\n");
18010: break;
18011: default:
18012: xmlGenericError(xmlGenericErrorContext,
18013: "not registered !!!\n");
18014: break;
18015: }
18016: }
18017: }
18018: #endif
18019:
18020: /*
18021: * 3.14.6 Constraints on Simple Type Definition Schema Components
18022: */
18023: static int
18024: xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18025: xmlSchemaTypePtr type)
18026: {
18027: int res, olderrs = pctxt->nberrors;
18028:
18029: if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18030: return(-1);
18031:
18032: if (! WXS_IS_TYPE_NOT_FIXED(type))
18033: return(0);
18034:
18035: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18036: type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18037:
18038: if (type->baseType == NULL) {
18039: PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18040: "missing baseType");
18041: goto exit_failure;
18042: }
18043: if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18044: xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18045: /*
18046: * If a member type of a union is a union itself, we need to substitute
18047: * that member type for its member types.
18048: * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18049: * types in WXS 1.1.
18050: */
18051: if ((type->memberTypes != NULL) &&
18052: (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18053: return(-1);
18054: /*
18055: * SPEC src-simple-type 1
18056: * "The corresponding simple type definition, if any, must satisfy
18057: * the conditions set out in Constraints on Simple Type Definition
18058: * Schema Components (�3.14.6)."
18059: */
18060: /*
18061: * Schema Component Constraint: Simple Type Definition Properties Correct
18062: * (st-props-correct)
18063: */
18064: res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18065: HFAILURE HERROR
18066: /*
18067: * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18068: * (cos-st-restricts)
18069: */
18070: res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18071: HFAILURE HERROR
18072: /*
18073: * TODO: Removed the error report, since it got annoying to get an
18074: * extra error report, if anything failed until now.
18075: * Enable this if needed.
18076: *
18077: * xmlSchemaPErr(ctxt, type->node,
18078: * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18079: * "Simple type '%s' does not satisfy the constraints "
18080: * "on simple type definitions.\n",
18081: * type->name, NULL);
18082: */
18083: /*
18084: * Schema Component Constraint: Simple Type Restriction (Facets)
18085: * (st-restrict-facets)
18086: */
18087: res = xmlSchemaCheckFacetValues(type, pctxt);
18088: HFAILURE HERROR
18089: if ((type->facetSet != NULL) ||
18090: (type->baseType->facetSet != NULL)) {
18091: res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18092: HFAILURE HERROR
18093: }
18094: /*
18095: * Whitespace value.
18096: */
18097: res = xmlSchemaTypeFixupWhitespace(type);
18098: HFAILURE HERROR
18099: xmlSchemaTypeFixupOptimFacets(type);
18100:
18101: exit_error:
18102: #ifdef DEBUG_TYPE
18103: xmlSchemaDebugFixedType(pctxt, type);
18104: #endif
18105: if (olderrs != pctxt->nberrors)
18106: return(pctxt->err);
18107: return(0);
18108:
18109: exit_failure:
18110: #ifdef DEBUG_TYPE
18111: xmlSchemaDebugFixedType(pctxt, type);
18112: #endif
18113: return(-1);
18114: }
18115:
18116: static int
18117: xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18118: xmlSchemaTypePtr type)
18119: {
18120: int res = 0, olderrs = pctxt->nberrors;
18121: xmlSchemaTypePtr baseType = type->baseType;
18122:
18123: if (! WXS_IS_TYPE_NOT_FIXED(type))
18124: return(0);
18125: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18126: if (baseType == NULL) {
18127: PERROR_INT("xmlSchemaFixupComplexType",
18128: "missing baseType");
18129: goto exit_failure;
18130: }
18131: /*
18132: * Fixup the base type.
18133: */
18134: if (WXS_IS_TYPE_NOT_FIXED(baseType))
18135: xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18136: if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18137: /*
18138: * Skip fixup if the base type is invalid.
18139: * TODO: Generate a warning!
18140: */
18141: return(0);
18142: }
18143: /*
18144: * This basically checks if the base type can be derived.
18145: */
18146: res = xmlSchemaCheckSRCCT(pctxt, type);
18147: HFAILURE HERROR
18148: /*
18149: * Fixup the content type.
18150: */
18151: if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18152: /*
18153: * Corresponds to <complexType><simpleContent>...
18154: */
18155: if ((WXS_IS_COMPLEX(baseType)) &&
18156: (baseType->contentTypeDef != NULL) &&
18157: (WXS_IS_RESTRICTION(type))) {
18158: xmlSchemaTypePtr contentBase, content;
18159: #ifdef ENABLE_NAMED_LOCALS
18160: char buf[30];
18161: const xmlChar *tmpname;
18162: #endif
18163: /*
18164: * SPEC (1) If <restriction> + base type is <complexType>,
18165: * "whose own {content type} is a simple type..."
18166: */
18167: if (type->contentTypeDef != NULL) {
18168: /*
18169: * SPEC (1.1) "the simple type definition corresponding to the
18170: * <simpleType> among the [children] of <restriction> if there
18171: * is one;"
18172: * Note that this "<simpleType> among the [children]" was put
18173: * into ->contentTypeDef during parsing.
18174: */
18175: contentBase = type->contentTypeDef;
18176: type->contentTypeDef = NULL;
18177: } else {
18178: /*
18179: * (1.2) "...otherwise (<restriction> has no <simpleType>
18180: * among its [children]), the simple type definition which
18181: * is the {content type} of the ... base type."
18182: */
18183: contentBase = baseType->contentTypeDef;
18184: }
18185: /*
18186: * SPEC
18187: * "... a simple type definition which restricts the simple
18188: * type definition identified in clause 1.1 or clause 1.2
18189: * with a set of facet components"
18190: *
18191: * Create the anonymous simple type, which will be the content
18192: * type of the complex type.
18193: */
18194: #ifdef ENABLE_NAMED_LOCALS
18195: snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18196: tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18197: content = xmlSchemaAddType(pctxt, pctxt->schema,
18198: XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18199: type->node, 0);
18200: #else
18201: content = xmlSchemaAddType(pctxt, pctxt->schema,
18202: XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18203: type->node, 0);
18204: #endif
18205: if (content == NULL)
18206: goto exit_failure;
18207: /*
18208: * We will use the same node as for the <complexType>
18209: * to have it somehow anchored in the schema doc.
18210: */
18211: content->type = XML_SCHEMA_TYPE_SIMPLE;
18212: content->baseType = contentBase;
18213: /*
18214: * Move the facets, previously anchored on the
18215: * complexType during parsing.
18216: */
18217: content->facets = type->facets;
18218: type->facets = NULL;
18219: content->facetSet = type->facetSet;
18220: type->facetSet = NULL;
18221:
18222: type->contentTypeDef = content;
18223: if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18224: xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18225: /*
18226: * Fixup the newly created type. We don't need to check
18227: * for circularity here.
18228: */
18229: res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18230: HFAILURE HERROR
18231: res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18232: HFAILURE HERROR
18233:
18234: } else if ((WXS_IS_COMPLEX(baseType)) &&
18235: (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18236: (WXS_IS_RESTRICTION(type))) {
18237: /*
18238: * SPEC (2) If <restriction> + base is a mixed <complexType> with
18239: * an emptiable particle, then a simple type definition which
18240: * restricts the <restriction>'s <simpleType> child.
18241: */
18242: if ((type->contentTypeDef == NULL) ||
18243: (type->contentTypeDef->baseType == NULL)) {
18244: /*
18245: * TODO: Check if this ever happens.
18246: */
18247: xmlSchemaPCustomErr(pctxt,
18248: XML_SCHEMAP_INTERNAL,
18249: WXS_BASIC_CAST type, NULL,
18250: "Internal error: xmlSchemaTypeFixup, "
18251: "complex type '%s': the <simpleContent><restriction> "
18252: "is missing a <simpleType> child, but was not catched "
18253: "by xmlSchemaCheckSRCCT()", type->name);
18254: goto exit_failure;
18255: }
18256: } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18257: /*
18258: * SPEC (3) If <extension> + base is <complexType> with
18259: * <simpleType> content, "...then the {content type} of that
18260: * complex type definition"
18261: */
18262: if (baseType->contentTypeDef == NULL) {
18263: /*
18264: * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18265: * should have catched this already.
18266: */
18267: xmlSchemaPCustomErr(pctxt,
18268: XML_SCHEMAP_INTERNAL,
18269: WXS_BASIC_CAST type, NULL,
18270: "Internal error: xmlSchemaTypeFixup, "
18271: "complex type '%s': the <extension>ed base type is "
18272: "a complex type with no simple content type",
18273: type->name);
18274: goto exit_failure;
18275: }
18276: type->contentTypeDef = baseType->contentTypeDef;
18277: } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18278: /*
18279: * SPEC (4) <extension> + base is <simpleType>
18280: * "... then that simple type definition"
18281: */
18282: type->contentTypeDef = baseType;
18283: } else {
18284: /*
18285: * TODO: Check if this ever happens.
18286: */
18287: xmlSchemaPCustomErr(pctxt,
18288: XML_SCHEMAP_INTERNAL,
18289: WXS_BASIC_CAST type, NULL,
18290: "Internal error: xmlSchemaTypeFixup, "
18291: "complex type '%s' with <simpleContent>: unhandled "
18292: "derivation case", type->name);
18293: goto exit_failure;
18294: }
18295: } else {
18296: int dummySequence = 0;
18297: xmlSchemaParticlePtr particle =
18298: (xmlSchemaParticlePtr) type->subtypes;
18299: /*
18300: * Corresponds to <complexType><complexContent>...
18301: *
18302: * NOTE that the effective mixed was already set during parsing of
18303: * <complexType> and <complexContent>; its flag value is
18304: * XML_SCHEMAS_TYPE_MIXED.
18305: *
18306: * Compute the "effective content":
18307: * (2.1.1) + (2.1.2) + (2.1.3)
18308: */
18309: if ((particle == NULL) ||
18310: ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18311: ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18312: (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18313: ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18314: (particle->minOccurs == 0))) &&
18315: ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18316: if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18317: /*
18318: * SPEC (2.1.4) "If the �effective mixed� is true, then
18319: * a particle whose properties are as follows:..."
18320: *
18321: * Empty sequence model group with
18322: * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18323: * NOTE that we sill assign it the <complexType> node to
18324: * somehow anchor it in the doc.
18325: */
18326: if ((particle == NULL) ||
18327: (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18328: /*
18329: * Create the particle.
18330: */
18331: particle = xmlSchemaAddParticle(pctxt,
18332: type->node, 1, 1);
18333: if (particle == NULL)
18334: goto exit_failure;
18335: /*
18336: * Create the model group.
18337: */ /* URGENT TODO: avoid adding to pending items. */
18338: particle->children = (xmlSchemaTreeItemPtr)
18339: xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18340: XML_SCHEMA_TYPE_SEQUENCE, type->node);
18341: if (particle->children == NULL)
18342: goto exit_failure;
18343:
18344: type->subtypes = (xmlSchemaTypePtr) particle;
18345: }
18346: dummySequence = 1;
18347: type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18348: } else {
18349: /*
18350: * SPEC (2.1.5) "otherwise empty"
18351: */
18352: type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18353: }
18354: } else {
18355: /*
18356: * SPEC (2.2) "otherwise the particle corresponding to the
18357: * <all>, <choice>, <group> or <sequence> among the
18358: * [children]."
18359: */
18360: type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18361: }
18362: /*
18363: * Compute the "content type".
18364: */
18365: if (WXS_IS_RESTRICTION(type)) {
18366: /*
18367: * SPEC (3.1) "If <restriction>..."
18368: * (3.1.1) + (3.1.2) */
18369: if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18370: if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18371: type->contentType = XML_SCHEMA_CONTENT_MIXED;
18372: }
18373: } else {
18374: /*
18375: * SPEC (3.2) "If <extension>..."
18376: */
18377: if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18378: /*
18379: * SPEC (3.2.1)
18380: * "If the �effective content� is empty, then the
18381: * {content type} of the [...] base ..."
18382: */
18383: type->contentType = baseType->contentType;
18384: type->subtypes = baseType->subtypes;
18385: /*
18386: * Fixes bug #347316:
18387: * This is the case when the base type has a simple
18388: * type definition as content.
18389: */
18390: type->contentTypeDef = baseType->contentTypeDef;
18391: /*
18392: * NOTE that the effective mixed is ignored here.
18393: */
18394: } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18395: /*
18396: * SPEC (3.2.2)
18397: */
18398: if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18399: type->contentType = XML_SCHEMA_CONTENT_MIXED;
18400: } else {
18401: /*
18402: * SPEC (3.2.3)
18403: */
18404: if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18405: type->contentType = XML_SCHEMA_CONTENT_MIXED;
18406: /*
18407: * "A model group whose {compositor} is sequence and whose
18408: * {particles} are..."
18409: */
18410: if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18411: (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18412: ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18413: XML_SCHEMA_TYPE_ALL))
18414: {
18415: /*
18416: * SPEC cos-all-limited (1)
18417: */
18418: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18419: /* TODO: error code */
18420: XML_SCHEMAP_COS_ALL_LIMITED,
18421: WXS_ITEM_NODE(type), NULL,
18422: "The type has an 'all' model group in its "
18423: "{content type} and thus cannot be derived from "
18424: "a non-empty type, since this would produce a "
18425: "'sequence' model group containing the 'all' "
18426: "model group; 'all' model groups are not "
18427: "allowed to appear inside other model groups",
18428: NULL, NULL);
18429:
18430: } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18431: (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18432: ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18433: XML_SCHEMA_TYPE_ALL))
18434: {
18435: /*
18436: * SPEC cos-all-limited (1)
18437: */
18438: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18439: /* TODO: error code */
18440: XML_SCHEMAP_COS_ALL_LIMITED,
18441: WXS_ITEM_NODE(type), NULL,
18442: "A type cannot be derived by extension from a type "
18443: "which has an 'all' model group in its "
18444: "{content type}, since this would produce a "
18445: "'sequence' model group containing the 'all' "
18446: "model group; 'all' model groups are not "
18447: "allowed to appear inside other model groups",
18448: NULL, NULL);
18449:
18450: } else if (! dummySequence) {
18451: xmlSchemaTreeItemPtr effectiveContent =
18452: (xmlSchemaTreeItemPtr) type->subtypes;
18453: /*
18454: * Create the particle.
18455: */
18456: particle = xmlSchemaAddParticle(pctxt,
18457: type->node, 1, 1);
18458: if (particle == NULL)
18459: goto exit_failure;
18460: /*
18461: * Create the "sequence" model group.
18462: */
18463: particle->children = (xmlSchemaTreeItemPtr)
18464: xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18465: XML_SCHEMA_TYPE_SEQUENCE, type->node);
18466: if (particle->children == NULL)
18467: goto exit_failure;
18468: WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18469: /*
18470: * SPEC "the particle of the {content type} of
18471: * the ... base ..."
18472: * Create a duplicate of the base type's particle
18473: * and assign its "term" to it.
18474: */
18475: particle->children->children =
18476: (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18477: type->node,
18478: ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18479: ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18480: if (particle->children->children == NULL)
18481: goto exit_failure;
18482: particle = (xmlSchemaParticlePtr)
18483: particle->children->children;
18484: particle->children =
18485: ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18486: /*
18487: * SPEC "followed by the �effective content�."
18488: */
18489: particle->next = effectiveContent;
18490: /*
18491: * This all will result in:
18492: * new-particle
18493: * --> new-sequence(
18494: * new-particle
18495: * --> base-model,
18496: * this-particle
18497: * --> this-model
18498: * )
18499: */
18500: } else {
18501: /*
18502: * This is the case when there is already an empty
18503: * <sequence> with minOccurs==maxOccurs==1.
18504: * Just add the base types's content type.
18505: * NOTE that, although we miss to add an intermediate
18506: * <sequence>, this should produce no difference to
18507: * neither the regex compilation of the content model,
18508: * nor to the complex type contraints.
18509: */
18510: particle->children->children =
18511: (xmlSchemaTreeItemPtr) baseType->subtypes;
18512: }
18513: }
18514: }
18515: }
18516: /*
18517: * Now fixup attribute uses:
18518: * - expand attr. group references
18519: * - intersect attribute wildcards
18520: * - inherit attribute uses of the base type
18521: * - inherit or union attr. wildcards if extending
18522: * - apply attr. use prohibitions if restricting
18523: */
18524: res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18525: HFAILURE HERROR
18526: /*
18527: * Apply the complex type component constraints; this will not
18528: * check attributes, since this is done in
18529: * xmlSchemaFixupTypeAttributeUses().
18530: */
18531: res = xmlSchemaCheckCTComponent(pctxt, type);
18532: HFAILURE HERROR
18533:
18534: #ifdef DEBUG_TYPE
18535: xmlSchemaDebugFixedType(pctxt, type);
18536: #endif
18537: if (olderrs != pctxt->nberrors)
18538: return(pctxt->err);
18539: else
18540: return(0);
18541:
18542: exit_error:
18543: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18544: #ifdef DEBUG_TYPE
18545: xmlSchemaDebugFixedType(pctxt, type);
18546: #endif
18547: return(pctxt->err);
18548:
18549: exit_failure:
18550: type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18551: #ifdef DEBUG_TYPE
18552: xmlSchemaDebugFixedType(pctxt, type);
18553: #endif
18554: return(-1);
18555: }
18556:
18557:
18558: /**
18559: * xmlSchemaTypeFixup:
18560: * @typeDecl: the schema type definition
18561: * @ctxt: the schema parser context
18562: *
18563: * Fixes the content model of the type.
18564: * URGENT TODO: We need an int result!
18565: */
18566: static int
18567: xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18568: xmlSchemaAbstractCtxtPtr actxt)
18569: {
18570: if (type == NULL)
18571: return(0);
18572: if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18573: AERROR_INT("xmlSchemaTypeFixup",
18574: "this function needs a parser context");
18575: return(-1);
18576: }
18577: if (! WXS_IS_TYPE_NOT_FIXED(type))
18578: return(0);
18579: if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18580: return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18581: else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18582: return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18583: return(0);
18584: }
18585:
18586: /**
18587: * xmlSchemaCheckFacet:
18588: * @facet: the facet
18589: * @typeDecl: the schema type definition
18590: * @pctxt: the schema parser context or NULL
18591: * @name: the optional name of the type
18592: *
18593: * Checks and computes the values of facets.
18594: *
18595: * Returns 0 if valid, a positive error code if not valid and
18596: * -1 in case of an internal or API error.
18597: */
18598: int
18599: xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18600: xmlSchemaTypePtr typeDecl,
18601: xmlSchemaParserCtxtPtr pctxt,
18602: const xmlChar * name ATTRIBUTE_UNUSED)
18603: {
18604: int ret = 0, ctxtGiven;
18605:
18606: if ((facet == NULL) || (typeDecl == NULL))
18607: return(-1);
18608: /*
18609: * TODO: will the parser context be given if used from
18610: * the relaxNG module?
18611: */
18612: if (pctxt == NULL)
18613: ctxtGiven = 0;
18614: else
18615: ctxtGiven = 1;
18616:
18617: switch (facet->type) {
18618: case XML_SCHEMA_FACET_MININCLUSIVE:
18619: case XML_SCHEMA_FACET_MINEXCLUSIVE:
18620: case XML_SCHEMA_FACET_MAXINCLUSIVE:
18621: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18622: case XML_SCHEMA_FACET_ENUMERATION: {
18623: /*
18624: * Okay we need to validate the value
18625: * at that point.
18626: */
18627: xmlSchemaTypePtr base;
18628:
18629: /* 4.3.5.5 Constraints on enumeration Schema Components
18630: * Schema Component Constraint: enumeration valid restriction
18631: * It is an �error� if any member of {value} is not in the
18632: * �value space� of {base type definition}.
18633: *
18634: * minInclusive, maxInclusive, minExclusive, maxExclusive:
18635: * The value �must� be in the
18636: * �value space� of the �base type�.
18637: */
18638: /*
18639: * This function is intended to deliver a compiled value
18640: * on the facet. In this implementation of XML Schemata the
18641: * type holding a facet, won't be a built-in type.
18642: * Thus to ensure that other API
18643: * calls (relaxng) do work, if the given type is a built-in
18644: * type, we will assume that the given built-in type *is
18645: * already* the base type.
18646: */
18647: if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18648: base = typeDecl->baseType;
18649: if (base == NULL) {
18650: PERROR_INT("xmlSchemaCheckFacet",
18651: "a type user derived type has no base type");
18652: return (-1);
18653: }
18654: } else
18655: base = typeDecl;
18656:
18657: if (! ctxtGiven) {
18658: /*
18659: * A context is needed if called from RelaxNG.
18660: */
18661: pctxt = xmlSchemaNewParserCtxt("*");
18662: if (pctxt == NULL)
18663: return (-1);
18664: }
18665: /*
18666: * NOTE: This call does not check the content nodes,
18667: * since they are not available:
18668: * facet->node is just the node holding the facet
18669: * definition, *not* the attribute holding the *value*
18670: * of the facet.
18671: */
18672: ret = xmlSchemaVCheckCVCSimpleType(
18673: ACTXT_CAST pctxt, facet->node, base,
18674: facet->value, &(facet->val), 1, 1, 0);
18675: if (ret != 0) {
18676: if (ret < 0) {
18677: /* No error message for RelaxNG. */
18678: if (ctxtGiven) {
18679: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18680: XML_SCHEMAP_INTERNAL, facet->node, NULL,
18681: "Internal error: xmlSchemaCheckFacet, "
18682: "failed to validate the value '%s' of the "
18683: "facet '%s' against the base type",
18684: facet->value, xmlSchemaFacetTypeToString(facet->type));
18685: }
18686: goto internal_error;
18687: }
18688: ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18689: /* No error message for RelaxNG. */
18690: if (ctxtGiven) {
18691: xmlChar *str = NULL;
18692:
18693: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18694: ret, facet->node, WXS_BASIC_CAST facet,
18695: "The value '%s' of the facet does not validate "
18696: "against the base type '%s'",
18697: facet->value,
18698: xmlSchemaFormatQName(&str,
18699: base->targetNamespace, base->name));
18700: FREE_AND_NULL(str);
18701: }
18702: goto exit;
18703: } else if (facet->val == NULL) {
18704: if (ctxtGiven) {
18705: PERROR_INT("xmlSchemaCheckFacet",
18706: "value was not computed");
18707: }
18708: TODO
18709: }
18710: break;
18711: }
18712: case XML_SCHEMA_FACET_PATTERN:
18713: facet->regexp = xmlRegexpCompile(facet->value);
18714: if (facet->regexp == NULL) {
18715: ret = XML_SCHEMAP_REGEXP_INVALID;
18716: /* No error message for RelaxNG. */
18717: if (ctxtGiven) {
18718: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18719: ret, facet->node, WXS_BASIC_CAST typeDecl,
18720: "The value '%s' of the facet 'pattern' is not a "
18721: "valid regular expression",
18722: facet->value, NULL);
18723: }
18724: }
18725: break;
18726: case XML_SCHEMA_FACET_TOTALDIGITS:
18727: case XML_SCHEMA_FACET_FRACTIONDIGITS:
18728: case XML_SCHEMA_FACET_LENGTH:
18729: case XML_SCHEMA_FACET_MAXLENGTH:
18730: case XML_SCHEMA_FACET_MINLENGTH:
18731:
18732: if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18733: ret = xmlSchemaValidatePredefinedType(
18734: xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18735: facet->value, &(facet->val));
18736: } else {
18737: ret = xmlSchemaValidatePredefinedType(
18738: xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18739: facet->value, &(facet->val));
18740: }
18741: if (ret != 0) {
18742: if (ret < 0) {
18743: /* No error message for RelaxNG. */
18744: if (ctxtGiven) {
18745: PERROR_INT("xmlSchemaCheckFacet",
18746: "validating facet value");
18747: }
18748: goto internal_error;
18749: }
18750: ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18751: /* No error message for RelaxNG. */
18752: if (ctxtGiven) {
18753: /* error code */
18754: xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18755: ret, facet->node, WXS_BASIC_CAST typeDecl,
18756: "The value '%s' of the facet '%s' is not a valid '%s'",
18757: facet->value,
18758: xmlSchemaFacetTypeToString(facet->type),
18759: (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18760: BAD_CAST "nonNegativeInteger" :
18761: BAD_CAST "positiveInteger",
18762: NULL);
18763: }
18764: }
18765: break;
18766:
18767: case XML_SCHEMA_FACET_WHITESPACE:{
18768: if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18769: facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18770: } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18771: facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18772: } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18773: facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18774: } else {
18775: ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18776: /* No error message for RelaxNG. */
18777: if (ctxtGiven) {
18778: /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18779: xmlSchemaCustomErr(ACTXT_CAST pctxt,
18780: ret, facet->node, WXS_BASIC_CAST typeDecl,
18781: "The value '%s' of the facet 'whitespace' is not "
18782: "valid", facet->value, NULL);
18783: }
18784: }
18785: }
18786: default:
18787: break;
18788: }
18789: exit:
18790: if ((! ctxtGiven) && (pctxt != NULL))
18791: xmlSchemaFreeParserCtxt(pctxt);
18792: return (ret);
18793: internal_error:
18794: if ((! ctxtGiven) && (pctxt != NULL))
18795: xmlSchemaFreeParserCtxt(pctxt);
18796: return (-1);
18797: }
18798:
18799: /**
18800: * xmlSchemaCheckFacetValues:
18801: * @typeDecl: the schema type definition
18802: * @ctxt: the schema parser context
18803: *
18804: * Checks the default values types, especially for facets
18805: */
18806: static int
18807: xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18808: xmlSchemaParserCtxtPtr pctxt)
18809: {
18810: int res, olderrs = pctxt->nberrors;
18811: const xmlChar *name = typeDecl->name;
18812: /*
18813: * NOTE: It is intended to use the facets list, instead
18814: * of facetSet.
18815: */
18816: if (typeDecl->facets != NULL) {
18817: xmlSchemaFacetPtr facet = typeDecl->facets;
18818:
18819: /*
18820: * Temporarily assign the "schema" to the validation context
18821: * of the parser context. This is needed for NOTATION validation.
18822: */
18823: if (pctxt->vctxt == NULL) {
18824: if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18825: return(-1);
18826: }
18827: pctxt->vctxt->schema = pctxt->schema;
18828: while (facet != NULL) {
18829: res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18830: HFAILURE
18831: facet = facet->next;
18832: }
18833: pctxt->vctxt->schema = NULL;
18834: }
18835: if (olderrs != pctxt->nberrors)
18836: return(pctxt->err);
18837: return(0);
18838: exit_failure:
18839: return(-1);
18840: }
18841:
18842: /**
18843: * xmlSchemaGetCircModelGrDefRef:
18844: * @ctxtMGroup: the searched model group
18845: * @selfMGroup: the second searched model group
18846: * @particle: the first particle
18847: *
18848: * This one is intended to be used by
18849: * xmlSchemaCheckGroupDefCircular only.
18850: *
18851: * Returns the particle with the circular model group definition reference,
18852: * otherwise NULL.
18853: */
18854: static xmlSchemaTreeItemPtr
18855: xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18856: xmlSchemaTreeItemPtr particle)
18857: {
18858: xmlSchemaTreeItemPtr circ = NULL;
18859: xmlSchemaTreeItemPtr term;
18860: xmlSchemaModelGroupDefPtr gdef;
18861:
18862: for (; particle != NULL; particle = particle->next) {
18863: term = particle->children;
18864: if (term == NULL)
18865: continue;
18866: switch (term->type) {
18867: case XML_SCHEMA_TYPE_GROUP:
18868: gdef = (xmlSchemaModelGroupDefPtr) term;
18869: if (gdef == groupDef)
18870: return (particle);
18871: /*
18872: * Mark this model group definition to avoid infinite
18873: * recursion on circular references not yet examined.
18874: */
18875: if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18876: continue;
18877: if (gdef->children != NULL) {
18878: gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18879: circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18880: gdef->children->children);
18881: gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18882: if (circ != NULL)
18883: return (circ);
18884: }
18885: break;
18886: case XML_SCHEMA_TYPE_SEQUENCE:
18887: case XML_SCHEMA_TYPE_CHOICE:
18888: case XML_SCHEMA_TYPE_ALL:
18889: circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18890: if (circ != NULL)
18891: return (circ);
18892: break;
18893: default:
18894: break;
18895: }
18896: }
18897: return (NULL);
18898: }
18899:
18900: /**
18901: * xmlSchemaCheckGroupDefCircular:
18902: * @item: the model group definition
18903: * @ctxt: the parser context
18904: * @name: the name
18905: *
18906: * Checks for circular references to model group definitions.
18907: */
18908: static void
18909: xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18910: xmlSchemaParserCtxtPtr ctxt)
18911: {
18912: /*
18913: * Schema Component Constraint: Model Group Correct
18914: * 2 Circular groups are disallowed. That is, within the {particles}
18915: * of a group there must not be at any depth a particle whose {term}
18916: * is the group itself.
18917: */
18918: if ((item == NULL) ||
18919: (item->type != XML_SCHEMA_TYPE_GROUP) ||
18920: (item->children == NULL))
18921: return;
18922: {
18923: xmlSchemaTreeItemPtr circ;
18924:
18925: circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18926: if (circ != NULL) {
18927: xmlChar *str = NULL;
18928: /*
18929: * TODO: The error report is not adequate: this constraint
18930: * is defined for model groups but not definitions, but since
18931: * there cannot be any circular model groups without a model group
18932: * definition (if not using a construction API), we check those
18933: * defintions only.
18934: */
18935: xmlSchemaPCustomErr(ctxt,
18936: XML_SCHEMAP_MG_PROPS_CORRECT_2,
18937: NULL, WXS_ITEM_NODE(circ),
18938: "Circular reference to the model group definition '%s' "
18939: "defined", xmlSchemaFormatQName(&str,
18940: item->targetNamespace, item->name));
18941: FREE_AND_NULL(str)
18942: /*
18943: * NOTE: We will cut the reference to avoid further
18944: * confusion of the processor. This is a fatal error.
18945: */
18946: circ->children = NULL;
18947: }
18948: }
18949: }
18950:
18951: /**
18952: * xmlSchemaModelGroupToModelGroupDefFixup:
18953: * @ctxt: the parser context
18954: * @mg: the model group
18955: *
18956: * Assigns the model group of model group definitions to the "term"
18957: * of the referencing particle.
18958: * In xmlSchemaResolveModelGroupParticleReferences the model group
18959: * definitions were assigned to the "term", since needed for the
18960: * circularity check.
18961: *
18962: * Schema Component Constraint:
18963: * All Group Limited (cos-all-limited) (1.2)
18964: */
18965: static void
18966: xmlSchemaModelGroupToModelGroupDefFixup(
18967: xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18968: xmlSchemaModelGroupPtr mg)
18969: {
18970: xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18971:
18972: while (particle != NULL) {
18973: if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18974: ((WXS_PARTICLE_TERM(particle))->type !=
18975: XML_SCHEMA_TYPE_GROUP))
18976: {
18977: particle = WXS_PTC_CAST particle->next;
18978: continue;
18979: }
18980: if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18981: /*
18982: * TODO: Remove the particle.
18983: */
18984: WXS_PARTICLE_TERM(particle) = NULL;
18985: particle = WXS_PTC_CAST particle->next;
18986: continue;
18987: }
18988: /*
18989: * Assign the model group to the {term} of the particle.
18990: */
18991: WXS_PARTICLE_TERM(particle) =
18992: WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18993:
18994: particle = WXS_PTC_CAST particle->next;
18995: }
18996: }
18997:
18998: /**
18999: * xmlSchemaCheckAttrGroupCircularRecur:
19000: * @ctxtGr: the searched attribute group
19001: * @attr: the current attribute list to be processed
19002: *
19003: * This one is intended to be used by
19004: * xmlSchemaCheckAttrGroupCircular only.
19005: *
19006: * Returns the circular attribute grou reference, otherwise NULL.
19007: */
19008: static xmlSchemaQNameRefPtr
19009: xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19010: xmlSchemaItemListPtr list)
19011: {
19012: xmlSchemaAttributeGroupPtr gr;
19013: xmlSchemaQNameRefPtr ref, circ;
19014: int i;
19015: /*
19016: * We will search for an attribute group reference which
19017: * references the context attribute group.
19018: */
19019: for (i = 0; i < list->nbItems; i++) {
19020: ref = list->items[i];
19021: if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19022: (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19023: (ref->item != NULL))
19024: {
19025: gr = WXS_ATTR_GROUP_CAST ref->item;
19026: if (gr == ctxtGr)
19027: return(ref);
19028: if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19029: continue;
19030: /*
19031: * Mark as visited to avoid infinite recursion on
19032: * circular references not yet examined.
19033: */
19034: if ((gr->attrUses) &&
19035: (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19036: {
19037: gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19038: circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19039: (xmlSchemaItemListPtr) gr->attrUses);
19040: gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19041: if (circ != NULL)
19042: return (circ);
19043: }
19044:
19045: }
19046: }
19047: return (NULL);
19048: }
19049:
19050: /**
19051: * xmlSchemaCheckAttrGroupCircular:
19052: * attrGr: the attribute group definition
19053: * @ctxt: the parser context
19054: * @name: the name
19055: *
19056: * Checks for circular references of attribute groups.
19057: */
19058: static int
19059: xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19060: xmlSchemaParserCtxtPtr ctxt)
19061: {
19062: /*
19063: * Schema Representation Constraint:
19064: * Attribute Group Definition Representation OK
19065: * 3 Circular group reference is disallowed outside <redefine>.
19066: * That is, unless this element information item's parent is
19067: * <redefine>, then among the [children], if any, there must
19068: * not be an <attributeGroup> with ref [attribute] which resolves
19069: * to the component corresponding to this <attributeGroup>. Indirect
19070: * circularity is also ruled out. That is, when QName resolution
19071: * (Schema Document) (�3.15.3) is applied to a �QName� arising from
19072: * any <attributeGroup>s with a ref [attribute] among the [children],
19073: * it must not be the case that a �QName� is encountered at any depth
19074: * which resolves to the component corresponding to this <attributeGroup>.
19075: */
19076: if (attrGr->attrUses == NULL)
19077: return(0);
19078: else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19079: return(0);
19080: else {
19081: xmlSchemaQNameRefPtr circ;
19082:
19083: circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19084: (xmlSchemaItemListPtr) attrGr->attrUses);
19085: if (circ != NULL) {
19086: xmlChar *str = NULL;
19087: /*
19088: * TODO: Report the referenced attr group as QName.
19089: */
19090: xmlSchemaPCustomErr(ctxt,
19091: XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19092: NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19093: "Circular reference to the attribute group '%s' "
19094: "defined", xmlSchemaGetComponentQName(&str, attrGr));
19095: FREE_AND_NULL(str);
19096: /*
19097: * NOTE: We will cut the reference to avoid further
19098: * confusion of the processor.
19099: * BADSPEC TODO: The spec should define how to process in this case.
19100: */
19101: circ->item = NULL;
19102: return(ctxt->err);
19103: }
19104: }
19105: return(0);
19106: }
19107:
19108: static int
19109: xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19110: xmlSchemaAttributeGroupPtr attrGr);
19111:
19112: /**
19113: * xmlSchemaExpandAttributeGroupRefs:
19114: * @pctxt: the parser context
19115: * @node: the node of the component holding the attribute uses
19116: * @completeWild: the intersected wildcard to be returned
19117: * @list: the attribute uses
19118: *
19119: * Substitutes contained attribute group references
19120: * for their attribute uses. Wilcards are intersected.
19121: * Attribute use prohibitions are removed from the list
19122: * and returned via the @prohibs list.
19123: * Pointlessness of attr. prohibs, if a matching attr. decl
19124: * is existent a well, are checked.
19125: */
19126: static int
19127: xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19128: xmlSchemaBasicItemPtr item,
19129: xmlSchemaWildcardPtr *completeWild,
19130: xmlSchemaItemListPtr list,
19131: xmlSchemaItemListPtr prohibs)
19132: {
19133: xmlSchemaAttributeGroupPtr gr;
19134: xmlSchemaAttributeUsePtr use;
19135: xmlSchemaItemListPtr sublist;
19136: int i, j;
19137: int created = (*completeWild == NULL) ? 0 : 1;
19138:
19139: if (prohibs)
19140: prohibs->nbItems = 0;
19141:
19142: for (i = 0; i < list->nbItems; i++) {
19143: use = list->items[i];
19144:
19145: if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19146: if (prohibs == NULL) {
19147: PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19148: "unexpected attr prohibition found");
19149: return(-1);
19150: }
19151: /*
19152: * Remove from attribute uses.
19153: */
19154: if (xmlSchemaItemListRemove(list, i) == -1)
19155: return(-1);
19156: i--;
19157: /*
19158: * Note that duplicate prohibitions were already
19159: * handled at parsing time.
19160: */
19161: /*
19162: * Add to list of prohibitions.
19163: */
19164: xmlSchemaItemListAddSize(prohibs, 2, use);
19165: continue;
19166: }
19167: if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19168: ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19169: {
19170: if ((WXS_QNAME_CAST use)->item == NULL)
19171: return(-1);
19172: gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19173: /*
19174: * Expand the referenced attr. group.
19175: * TODO: remove this, this is done in a previous step, so
19176: * already done here.
19177: */
19178: if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19179: if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19180: return(-1);
19181: }
19182: /*
19183: * Build the 'complete' wildcard; i.e. intersect multiple
19184: * wildcards.
19185: */
19186: if (gr->attributeWildcard != NULL) {
19187: if (*completeWild == NULL) {
19188: *completeWild = gr->attributeWildcard;
19189: } else {
19190: if (! created) {
19191: xmlSchemaWildcardPtr tmpWild;
19192:
19193: /*
19194: * Copy the first encountered wildcard as context,
19195: * except for the annotation.
19196: *
19197: * Although the complete wildcard might not correspond
19198: * to any node in the schema, we will anchor it on
19199: * the node of the owner component.
19200: */
19201: tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19202: XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19203: WXS_ITEM_NODE(item));
19204: if (tmpWild == NULL)
19205: return(-1);
19206: if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19207: tmpWild, *completeWild) == -1)
19208: return (-1);
19209: tmpWild->processContents = (*completeWild)->processContents;
19210: *completeWild = tmpWild;
19211: created = 1;
19212: }
19213:
19214: if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19215: gr->attributeWildcard) == -1)
19216: return(-1);
19217: }
19218: }
19219: /*
19220: * Just remove the reference if the referenced group does not
19221: * contain any attribute uses.
19222: */
19223: sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19224: if ((sublist == NULL) || sublist->nbItems == 0) {
19225: if (xmlSchemaItemListRemove(list, i) == -1)
19226: return(-1);
19227: i--;
19228: continue;
19229: }
19230: /*
19231: * Add the attribute uses.
19232: */
19233: list->items[i] = sublist->items[0];
19234: if (sublist->nbItems != 1) {
19235: for (j = 1; j < sublist->nbItems; j++) {
19236: i++;
19237: if (xmlSchemaItemListInsert(list,
19238: sublist->items[j], i) == -1)
19239: return(-1);
19240: }
19241: }
19242: }
19243:
19244: }
19245: /*
19246: * Handle pointless prohibitions of declared attributes.
19247: */
19248: if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19249: xmlSchemaAttributeUseProhibPtr prohib;
19250:
19251: for (i = prohibs->nbItems -1; i >= 0; i--) {
19252: prohib = prohibs->items[i];
19253: for (j = 0; j < list->nbItems; j++) {
19254: use = list->items[j];
19255:
19256: if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19257: (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19258: {
19259: xmlChar *str = NULL;
19260:
19261: xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19262: XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19263: prohib->node, NULL,
19264: "Skipping pointless attribute use prohibition "
19265: "'%s', since a corresponding attribute use "
19266: "exists already in the type definition",
19267: xmlSchemaFormatQName(&str,
19268: prohib->targetNamespace, prohib->name),
19269: NULL, NULL);
19270: FREE_AND_NULL(str);
19271: /*
19272: * Remove the prohibition.
19273: */
19274: if (xmlSchemaItemListRemove(prohibs, i) == -1)
19275: return(-1);
19276: break;
19277: }
19278: }
19279: }
19280: }
19281: return(0);
19282: }
19283:
19284: /**
19285: * xmlSchemaAttributeGroupExpandRefs:
19286: * @pctxt: the parser context
19287: * @attrGr: the attribute group definition
19288: *
19289: * Computation of:
19290: * {attribute uses} property
19291: * {attribute wildcard} property
19292: *
19293: * Substitutes contained attribute group references
19294: * for their attribute uses. Wilcards are intersected.
19295: */
19296: static int
19297: xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19298: xmlSchemaAttributeGroupPtr attrGr)
19299: {
19300: if ((attrGr->attrUses == NULL) ||
19301: (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19302: return(0);
19303:
19304: attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19305: if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19306: &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19307: return(-1);
19308: return(0);
19309: }
19310:
19311: /**
19312: * xmlSchemaAttributeGroupExpandRefs:
19313: * @pctxt: the parser context
19314: * @attrGr: the attribute group definition
19315: *
19316: * Substitutes contained attribute group references
19317: * for their attribute uses. Wilcards are intersected.
19318: *
19319: * Schema Component Constraint:
19320: * Attribute Group Definition Properties Correct (ag-props-correct)
19321: */
19322: static int
19323: xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19324: xmlSchemaAttributeGroupPtr attrGr)
19325: {
19326: /*
19327: * SPEC ag-props-correct
19328: * (1) "The values of the properties of an attribute group definition
19329: * must be as described in the property tableau in The Attribute
19330: * Group Definition Schema Component (�3.6.1), modulo the impact of
19331: * Missing Sub-components (�5.3);"
19332: */
19333:
19334: if ((attrGr->attrUses != NULL) &&
19335: (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19336: {
19337: xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19338: xmlSchemaAttributeUsePtr use, tmp;
19339: int i, j, hasId = 0;
19340:
19341: for (i = uses->nbItems -1; i >= 0; i--) {
19342: use = uses->items[i];
19343: /*
19344: * SPEC ag-props-correct
19345: * (2) "Two distinct members of the {attribute uses} must not have
19346: * {attribute declaration}s both of whose {name}s match and whose
19347: * {target namespace}s are identical."
19348: */
19349: if (i > 0) {
19350: for (j = i -1; j >= 0; j--) {
19351: tmp = uses->items[j];
19352: if ((WXS_ATTRUSE_DECL_NAME(use) ==
19353: WXS_ATTRUSE_DECL_NAME(tmp)) &&
19354: (WXS_ATTRUSE_DECL_TNS(use) ==
19355: WXS_ATTRUSE_DECL_TNS(tmp)))
19356: {
19357: xmlChar *str = NULL;
19358:
19359: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19360: XML_SCHEMAP_AG_PROPS_CORRECT,
19361: attrGr->node, WXS_BASIC_CAST attrGr,
19362: "Duplicate %s",
19363: xmlSchemaGetComponentDesignation(&str, use),
19364: NULL);
19365: FREE_AND_NULL(str);
19366: /*
19367: * Remove the duplicate.
19368: */
19369: if (xmlSchemaItemListRemove(uses, i) == -1)
19370: return(-1);
19371: goto next_use;
19372: }
19373: }
19374: }
19375: /*
19376: * SPEC ag-props-correct
19377: * (3) "Two distinct members of the {attribute uses} must not have
19378: * {attribute declaration}s both of whose {type definition}s are or
19379: * are derived from ID."
19380: * TODO: Does 'derived' include member-types of unions?
19381: */
19382: if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19383: if (xmlSchemaIsDerivedFromBuiltInType(
19384: WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19385: {
19386: if (hasId) {
19387: xmlChar *str = NULL;
19388:
19389: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19390: XML_SCHEMAP_AG_PROPS_CORRECT,
19391: attrGr->node, WXS_BASIC_CAST attrGr,
19392: "There must not exist more than one attribute "
19393: "declaration of type 'xs:ID' "
19394: "(or derived from 'xs:ID'). The %s violates this "
19395: "constraint",
19396: xmlSchemaGetComponentDesignation(&str, use),
19397: NULL);
19398: FREE_AND_NULL(str);
19399: if (xmlSchemaItemListRemove(uses, i) == -1)
19400: return(-1);
19401: }
19402: hasId = 1;
19403: }
19404: }
19405: next_use: {}
19406: }
19407: }
19408: return(0);
19409: }
19410:
19411: /**
19412: * xmlSchemaResolveAttrGroupReferences:
19413: * @attrgrpDecl: the schema attribute definition
19414: * @ctxt: the schema parser context
19415: * @name: the attribute name
19416: *
19417: * Resolves references to attribute group definitions.
19418: */
19419: static int
19420: xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19421: xmlSchemaParserCtxtPtr ctxt)
19422: {
19423: xmlSchemaAttributeGroupPtr group;
19424:
19425: if (ref->item != NULL)
19426: return(0);
19427: group = xmlSchemaGetAttributeGroup(ctxt->schema,
19428: ref->name,
19429: ref->targetNamespace);
19430: if (group == NULL) {
19431: xmlSchemaPResCompAttrErr(ctxt,
19432: XML_SCHEMAP_SRC_RESOLVE,
19433: NULL, ref->node,
19434: "ref", ref->name, ref->targetNamespace,
19435: ref->itemType, NULL);
19436: return(ctxt->err);
19437: }
19438: ref->item = WXS_BASIC_CAST group;
19439: return(0);
19440: }
19441:
19442: /**
19443: * xmlSchemaCheckAttrPropsCorrect:
19444: * @item: an schema attribute declaration/use
19445: * @ctxt: a schema parser context
19446: * @name: the name of the attribute
19447: *
19448: *
19449: * Schema Component Constraint:
19450: * Attribute Declaration Properties Correct (a-props-correct)
19451: *
19452: * Validates the value constraints of an attribute declaration/use.
19453: * NOTE that this needs the simle type definitions to be already
19454: * builded and checked.
19455: */
19456: static int
19457: xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19458: xmlSchemaAttributePtr attr)
19459: {
19460:
19461: /*
19462: * SPEC a-props-correct (1)
19463: * "The values of the properties of an attribute declaration must
19464: * be as described in the property tableau in The Attribute
19465: * Declaration Schema Component (�3.2.1), modulo the impact of
19466: * Missing Sub-components (�5.3)."
19467: */
19468:
19469: if (WXS_ATTR_TYPEDEF(attr) == NULL)
19470: return(0);
19471:
19472: if (attr->defValue != NULL) {
19473: int ret;
19474:
19475: /*
19476: * SPEC a-props-correct (3)
19477: * "If the {type definition} is or is derived from ID then there
19478: * must not be a {value constraint}."
19479: */
19480: if (xmlSchemaIsDerivedFromBuiltInType(
19481: WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19482: {
19483: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19484: XML_SCHEMAP_A_PROPS_CORRECT_3,
19485: NULL, WXS_BASIC_CAST attr,
19486: "Value constraints are not allowed if the type definition "
19487: "is or is derived from xs:ID",
19488: NULL, NULL);
19489: return(pctxt->err);
19490: }
19491: /*
19492: * SPEC a-props-correct (2)
19493: * "if there is a {value constraint}, the canonical lexical
19494: * representation of its value must be �valid� with respect
19495: * to the {type definition} as defined in String Valid (�3.14.4)."
19496: * TODO: Don't care about the *cononical* stuff here, this requirement
19497: * will be removed in WXS 1.1 anyway.
19498: */
19499: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19500: attr->node, WXS_ATTR_TYPEDEF(attr),
19501: attr->defValue, &(attr->defVal),
19502: 1, 1, 0);
19503: if (ret != 0) {
19504: if (ret < 0) {
19505: PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19506: "calling xmlSchemaVCheckCVCSimpleType()");
19507: return(-1);
19508: }
19509: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19510: XML_SCHEMAP_A_PROPS_CORRECT_2,
19511: NULL, WXS_BASIC_CAST attr,
19512: "The value of the value constraint is not valid",
19513: NULL, NULL);
19514: return(pctxt->err);
19515: }
19516: }
19517:
19518: return(0);
19519: }
19520:
19521: static xmlSchemaElementPtr
19522: xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19523: xmlSchemaElementPtr ancestor)
19524: {
19525: xmlSchemaElementPtr ret;
19526:
19527: if (WXS_SUBST_HEAD(ancestor) == NULL)
19528: return (NULL);
19529: if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19530: return (ancestor);
19531:
19532: if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19533: return (NULL);
19534: WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19535: ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19536: WXS_SUBST_HEAD(ancestor));
19537: WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19538:
19539: return (ret);
19540: }
19541:
19542: /**
19543: * xmlSchemaCheckElemPropsCorrect:
19544: * @ctxt: a schema parser context
19545: * @decl: the element declaration
19546: * @name: the name of the attribute
19547: *
19548: * Schema Component Constraint:
19549: * Element Declaration Properties Correct (e-props-correct)
19550: *
19551: * STATUS:
19552: * missing: (6)
19553: */
19554: static int
19555: xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19556: xmlSchemaElementPtr elemDecl)
19557: {
19558: int ret = 0;
19559: xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19560: /*
19561: * SPEC (1) "The values of the properties of an element declaration
19562: * must be as described in the property tableau in The Element
19563: * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19564: * Sub-components (�5.3)."
19565: */
19566: if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19567: xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19568:
19569: xmlSchemaCheckElementDeclComponent(head, pctxt);
19570: /*
19571: * SPEC (3) "If there is a non-�absent� {substitution group
19572: * affiliation}, then {scope} must be global."
19573: */
19574: if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19575: xmlSchemaPCustomErr(pctxt,
19576: XML_SCHEMAP_E_PROPS_CORRECT_3,
19577: WXS_BASIC_CAST elemDecl, NULL,
19578: "Only global element declarations can have a "
19579: "substitution group affiliation", NULL);
19580: ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19581: }
19582: /*
19583: * TODO: SPEC (6) "Circular substitution groups are disallowed.
19584: * That is, it must not be possible to return to an element declaration
19585: * by repeatedly following the {substitution group affiliation}
19586: * property."
19587: */
19588: if (head == elemDecl)
19589: circ = head;
19590: else if (WXS_SUBST_HEAD(head) != NULL)
19591: circ = xmlSchemaCheckSubstGroupCircular(head, head);
19592: else
19593: circ = NULL;
19594: if (circ != NULL) {
19595: xmlChar *strA = NULL, *strB = NULL;
19596:
19597: xmlSchemaPCustomErrExt(pctxt,
19598: XML_SCHEMAP_E_PROPS_CORRECT_6,
19599: WXS_BASIC_CAST circ, NULL,
19600: "The element declaration '%s' defines a circular "
19601: "substitution group to element declaration '%s'",
19602: xmlSchemaGetComponentQName(&strA, circ),
19603: xmlSchemaGetComponentQName(&strB, head),
19604: NULL);
19605: FREE_AND_NULL(strA)
19606: FREE_AND_NULL(strB)
19607: ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19608: }
19609: /*
19610: * SPEC (4) "If there is a {substitution group affiliation},
19611: * the {type definition}
19612: * of the element declaration must be validly derived from the {type
19613: * definition} of the {substitution group affiliation}, given the value
19614: * of the {substitution group exclusions} of the {substitution group
19615: * affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19616: * (if the {type definition} is complex) or as defined in
19617: * Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19618: * simple)."
19619: *
19620: * NOTE: {substitution group exclusions} means the values of the
19621: * attribute "final".
19622: */
19623:
19624: if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19625: int set = 0;
19626:
19627: if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19628: set |= SUBSET_EXTENSION;
19629: if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19630: set |= SUBSET_RESTRICTION;
19631:
19632: if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19633: WXS_ELEM_TYPEDEF(head), set) != 0) {
19634: xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19635:
19636: ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19637: xmlSchemaPCustomErrExt(pctxt,
19638: XML_SCHEMAP_E_PROPS_CORRECT_4,
19639: WXS_BASIC_CAST elemDecl, NULL,
19640: "The type definition '%s' was "
19641: "either rejected by the substitution group "
19642: "affiliation '%s', or not validly derived from its type "
19643: "definition '%s'",
19644: xmlSchemaGetComponentQName(&strA, typeDef),
19645: xmlSchemaGetComponentQName(&strB, head),
19646: xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19647: FREE_AND_NULL(strA)
19648: FREE_AND_NULL(strB)
19649: FREE_AND_NULL(strC)
19650: }
19651: }
19652: }
19653: /*
19654: * SPEC (5) "If the {type definition} or {type definition}'s
19655: * {content type}
19656: * is or is derived from ID then there must not be a {value constraint}.
19657: * Note: The use of ID as a type definition for elements goes beyond
19658: * XML 1.0, and should be avoided if backwards compatibility is desired"
19659: */
19660: if ((elemDecl->value != NULL) &&
19661: ((WXS_IS_SIMPLE(typeDef) &&
19662: xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19663: (WXS_IS_COMPLEX(typeDef) &&
19664: WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19665: xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19666: XML_SCHEMAS_ID)))) {
19667:
19668: ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19669: xmlSchemaPCustomErr(pctxt,
19670: XML_SCHEMAP_E_PROPS_CORRECT_5,
19671: WXS_BASIC_CAST elemDecl, NULL,
19672: "The type definition (or type definition's content type) is or "
19673: "is derived from ID; value constraints are not allowed in "
19674: "conjunction with such a type definition", NULL);
19675: } else if (elemDecl->value != NULL) {
19676: int vcret;
19677: xmlNodePtr node = NULL;
19678:
19679: /*
19680: * SPEC (2) "If there is a {value constraint}, the canonical lexical
19681: * representation of its value must be �valid� with respect to the
19682: * {type definition} as defined in Element Default Valid (Immediate)
19683: * (�3.3.6)."
19684: */
19685: if (typeDef == NULL) {
19686: xmlSchemaPErr(pctxt, elemDecl->node,
19687: XML_SCHEMAP_INTERNAL,
19688: "Internal error: xmlSchemaCheckElemPropsCorrect, "
19689: "type is missing... skipping validation of "
19690: "the value constraint", NULL, NULL);
19691: return (-1);
19692: }
19693: if (elemDecl->node != NULL) {
19694: if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19695: node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19696: BAD_CAST "fixed");
19697: else
19698: node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19699: BAD_CAST "default");
19700: }
19701: vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19702: typeDef, elemDecl->value, &(elemDecl->defVal));
19703: if (vcret != 0) {
19704: if (vcret < 0) {
19705: PERROR_INT("xmlSchemaElemCheckValConstr",
19706: "failed to validate the value constraint of an "
19707: "element declaration");
19708: return (-1);
19709: }
19710: return (vcret);
19711: }
19712: }
19713:
19714: return (ret);
19715: }
19716:
19717: /**
19718: * xmlSchemaCheckElemSubstGroup:
19719: * @ctxt: a schema parser context
19720: * @decl: the element declaration
19721: * @name: the name of the attribute
19722: *
19723: * Schema Component Constraint:
19724: * Substitution Group (cos-equiv-class)
19725: *
19726: * In Libxml2 the subst. groups will be precomputed, in terms of that
19727: * a list will be built for each subst. group head, holding all direct
19728: * referents to this head.
19729: * NOTE that this function needs:
19730: * 1. circular subst. groups to be checked beforehand
19731: * 2. the declaration's type to be derived from the head's type
19732: *
19733: * STATUS:
19734: *
19735: */
19736: static void
19737: xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19738: xmlSchemaElementPtr elemDecl)
19739: {
19740: if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19741: /* SPEC (1) "Its {abstract} is false." */
19742: (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19743: return;
19744: {
19745: xmlSchemaElementPtr head;
19746: xmlSchemaTypePtr headType, type;
19747: int set, methSet;
19748: /*
19749: * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19750: * {disallowed substitutions} as the blocking constraint, as defined in
19751: * Substitution Group OK (Transitive) (�3.3.6)."
19752: */
19753: for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19754: head = WXS_SUBST_HEAD(head)) {
19755: set = 0;
19756: methSet = 0;
19757: /*
19758: * The blocking constraints.
19759: */
19760: if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19761: continue;
19762: headType = head->subtypes;
19763: type = elemDecl->subtypes;
19764: if (headType == type)
19765: goto add_member;
19766: if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19767: set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19768: if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19769: set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19770: /*
19771: * SPEC: Substitution Group OK (Transitive) (2.3)
19772: * "The set of all {derivation method}s involved in the
19773: * derivation of D's {type definition} from C's {type definition}
19774: * does not intersect with the union of the blocking constraint,
19775: * C's {prohibited substitutions} (if C is complex, otherwise the
19776: * empty set) and the {prohibited substitutions} (respectively the
19777: * empty set) of any intermediate {type definition}s in the
19778: * derivation of D's {type definition} from C's {type definition}."
19779: */
19780: /*
19781: * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19782: * subst.head axis, the methSet does not need to be computed for
19783: * the full depth over and over.
19784: */
19785: /*
19786: * The set of all {derivation method}s involved in the derivation
19787: */
19788: while ((type != NULL) && (type != headType)) {
19789: if ((WXS_IS_EXTENSION(type)) &&
19790: ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19791: methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19792:
19793: if (WXS_IS_RESTRICTION(type) &&
19794: ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19795: methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19796:
19797: type = type->baseType;
19798: }
19799: /*
19800: * The {prohibited substitutions} of all intermediate types +
19801: * the head's type.
19802: */
19803: type = elemDecl->subtypes->baseType;
19804: while (type != NULL) {
19805: if (WXS_IS_COMPLEX(type)) {
19806: if ((type->flags &
19807: XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19808: ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19809: set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19810: if ((type->flags &
19811: XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19812: ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19813: set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19814: } else
19815: break;
19816: if (type == headType)
19817: break;
19818: type = type->baseType;
19819: }
19820: if ((set != 0) &&
19821: (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19822: (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19823: ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19824: (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19825: continue;
19826: }
19827: add_member:
19828: xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19829: if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19830: head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19831: }
19832: }
19833: }
19834:
19835: #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19836: /**
19837: * xmlSchemaCheckElementDeclComponent
19838: * @pctxt: the schema parser context
19839: * @ctxtComponent: the context component (an element declaration)
19840: * @ctxtParticle: the first particle of the context component
19841: * @searchParticle: the element declaration particle to be analysed
19842: *
19843: * Schema Component Constraint: Element Declarations Consistent
19844: */
19845: static int
19846: xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19847: xmlSchemaBasicItemPtr ctxtComponent,
19848: xmlSchemaParticlePtr ctxtParticle,
19849: xmlSchemaParticlePtr searchParticle,
19850: xmlSchemaParticlePtr curParticle,
19851: int search)
19852: {
19853: return(0);
19854:
19855: int ret = 0;
19856: xmlSchemaParticlePtr cur = curParticle;
19857: if (curParticle == NULL) {
19858: return(0);
19859: }
19860: if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19861: /*
19862: * Just return in this case. A missing "term" of the particle
19863: * might arise due to an invalid "term" component.
19864: */
19865: return(0);
19866: }
19867: while (cur != NULL) {
19868: switch (WXS_PARTICLE_TERM(cur)->type) {
19869: case XML_SCHEMA_TYPE_ANY:
19870: break;
19871: case XML_SCHEMA_TYPE_ELEMENT:
19872: if (search == 0) {
19873: ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19874: ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19875: if (ret != 0)
19876: return(ret);
19877: } else {
19878: xmlSchemaElementPtr elem =
19879: WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19880: /*
19881: * SPEC Element Declarations Consistent:
19882: * "If the {particles} contains, either directly,
19883: * indirectly (that is, within the {particles} of a
19884: * contained model group, recursively) or �implicitly�
19885: * two or more element declaration particles with
19886: * the same {name} and {target namespace}, then
19887: * all their type definitions must be the same
19888: * top-level definition [...]"
19889: */
19890: if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19891: WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19892: xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19893: WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19894: {
19895: xmlChar *strA = NULL, *strB = NULL;
19896:
19897: xmlSchemaCustomErr(ACTXT_CAST pctxt,
19898: /* TODO: error code */
19899: XML_SCHEMAP_COS_NONAMBIG,
19900: WXS_ITEM_NODE(cur), NULL,
19901: "In the content model of %s, there are multiple "
19902: "element declarations for '%s' with different "
19903: "type definitions",
19904: xmlSchemaGetComponentDesignation(&strA,
19905: ctxtComponent),
19906: xmlSchemaFormatQName(&strB,
19907: WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19908: WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19909: FREE_AND_NULL(strA);
19910: FREE_AND_NULL(strB);
19911: return(XML_SCHEMAP_COS_NONAMBIG);
19912: }
19913: }
19914: break;
19915: case XML_SCHEMA_TYPE_SEQUENCE: {
19916: break;
19917: }
19918: case XML_SCHEMA_TYPE_CHOICE:{
19919: /*
19920: xmlSchemaTreeItemPtr sub;
19921:
19922: sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
19923: while (sub != NULL) {
19924: ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19925: ctxtParticle, ctxtElem);
19926: if (ret != 0)
19927: return(ret);
19928: sub = sub->next;
19929: }
19930: */
19931: break;
19932: }
19933: case XML_SCHEMA_TYPE_ALL:
19934: break;
19935: case XML_SCHEMA_TYPE_GROUP:
19936: break;
19937: default:
19938: xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19939: "xmlSchemaCheckElementDeclConsistent",
19940: "found unexpected term of type '%s' in content model",
19941: WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19942: return(-1);
19943: }
19944: cur = (xmlSchemaParticlePtr) cur->next;
19945: }
19946:
19947: exit:
19948: return(ret);
19949: }
19950: #endif
19951:
19952: /**
19953: * xmlSchemaCheckElementDeclComponent
19954: * @item: an schema element declaration/particle
19955: * @ctxt: a schema parser context
19956: * @name: the name of the attribute
19957: *
19958: * Validates the value constraints of an element declaration.
19959: * Adds substitution group members.
19960: */
19961: static void
19962: xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19963: xmlSchemaParserCtxtPtr ctxt)
19964: {
19965: if (elemDecl == NULL)
19966: return;
19967: if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19968: return;
19969: elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19970: if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19971: /*
19972: * Adds substitution group members.
19973: */
19974: xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19975: }
19976: }
19977:
19978: /**
19979: * xmlSchemaResolveModelGroupParticleReferences:
19980: * @particle: a particle component
19981: * @ctxt: a parser context
19982: *
19983: * Resolves references of a model group's {particles} to
19984: * model group definitions and to element declarations.
19985: */
19986: static void
19987: xmlSchemaResolveModelGroupParticleReferences(
19988: xmlSchemaParserCtxtPtr ctxt,
19989: xmlSchemaModelGroupPtr mg)
19990: {
19991: xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19992: xmlSchemaQNameRefPtr ref;
19993: xmlSchemaBasicItemPtr refItem;
19994:
19995: /*
19996: * URGENT TODO: Test this.
19997: */
19998: while (particle != NULL) {
19999: if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20000: ((WXS_PARTICLE_TERM(particle))->type !=
20001: XML_SCHEMA_EXTRA_QNAMEREF))
20002: {
20003: goto next_particle;
20004: }
20005: ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20006: /*
20007: * Resolve the reference.
20008: * NULL the {term} by default.
20009: */
20010: particle->children = NULL;
20011:
20012: refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20013: ref->itemType, ref->name, ref->targetNamespace);
20014: if (refItem == NULL) {
20015: xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20016: NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20017: ref->targetNamespace, ref->itemType, NULL);
20018: /* TODO: remove the particle. */
20019: goto next_particle;
20020: }
20021: if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20022: if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20023: /* TODO: remove the particle. */
20024: goto next_particle;
20025: /*
20026: * NOTE that we will assign the model group definition
20027: * itself to the "term" of the particle. This will ease
20028: * the check for circular model group definitions. After
20029: * that the "term" will be assigned the model group of the
20030: * model group definition.
20031: */
20032: if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20033: XML_SCHEMA_TYPE_ALL) {
20034: /*
20035: * SPEC cos-all-limited (1)
20036: * SPEC cos-all-limited (1.2)
20037: * "It appears only as the value of one or both of the
20038: * following properties:"
20039: * (1.1) "the {model group} property of a model group
20040: * definition."
20041: * (1.2) "the {term} property of a particle [... of] the "
20042: * {content type} of a complex type definition."
20043: */
20044: xmlSchemaCustomErr(ACTXT_CAST ctxt,
20045: /* TODO: error code */
20046: XML_SCHEMAP_COS_ALL_LIMITED,
20047: WXS_ITEM_NODE(particle), NULL,
20048: "A model group definition is referenced, but "
20049: "it contains an 'all' model group, which "
20050: "cannot be contained by model groups",
20051: NULL, NULL);
20052: /* TODO: remove the particle. */
20053: goto next_particle;
20054: }
20055: particle->children = (xmlSchemaTreeItemPtr) refItem;
20056: } else {
20057: /*
20058: * TODO: Are referenced element declarations the only
20059: * other components we expect here?
20060: */
20061: particle->children = (xmlSchemaTreeItemPtr) refItem;
20062: }
20063: next_particle:
20064: particle = WXS_PTC_CAST particle->next;
20065: }
20066: }
20067:
20068: static int
20069: xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20070: xmlSchemaValPtr y)
20071: {
20072: xmlSchemaTypePtr tx, ty, ptx, pty;
20073: int ret;
20074:
20075: while (x != NULL) {
20076: /* Same types. */
20077: tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20078: ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20079: ptx = xmlSchemaGetPrimitiveType(tx);
20080: pty = xmlSchemaGetPrimitiveType(ty);
20081: /*
20082: * (1) if a datatype T' is �derived� by �restriction� from an
20083: * atomic datatype T then the �value space� of T' is a subset of
20084: * the �value space� of T. */
20085: /*
20086: * (2) if datatypes T' and T'' are �derived� by �restriction�
20087: * from a common atomic ancestor T then the �value space�s of T'
20088: * and T'' may overlap.
20089: */
20090: if (ptx != pty)
20091: return(0);
20092: /*
20093: * We assume computed values to be normalized, so do a fast
20094: * string comparison for string based types.
20095: */
20096: if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20097: WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20098: if (! xmlStrEqual(
20099: xmlSchemaValueGetAsString(x),
20100: xmlSchemaValueGetAsString(y)))
20101: return (0);
20102: } else {
20103: ret = xmlSchemaCompareValuesWhtsp(
20104: x, XML_SCHEMA_WHITESPACE_PRESERVE,
20105: y, XML_SCHEMA_WHITESPACE_PRESERVE);
20106: if (ret == -2)
20107: return(-1);
20108: if (ret != 0)
20109: return(0);
20110: }
20111: /*
20112: * Lists.
20113: */
20114: x = xmlSchemaValueGetNext(x);
20115: if (x != NULL) {
20116: y = xmlSchemaValueGetNext(y);
20117: if (y == NULL)
20118: return (0);
20119: } else if (xmlSchemaValueGetNext(y) != NULL)
20120: return (0);
20121: else
20122: return (1);
20123: }
20124: return (0);
20125: }
20126:
20127: /**
20128: * xmlSchemaResolveAttrUseReferences:
20129: * @item: an attribute use
20130: * @ctxt: a parser context
20131: *
20132: * Resolves the referenced attribute declaration.
20133: */
20134: static int
20135: xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20136: xmlSchemaParserCtxtPtr ctxt)
20137: {
20138: if ((ctxt == NULL) || (ause == NULL))
20139: return(-1);
20140: if ((ause->attrDecl == NULL) ||
20141: (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20142: return(0);
20143:
20144: {
20145: xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20146:
20147: /*
20148: * TODO: Evaluate, what errors could occur if the declaration is not
20149: * found.
20150: */
20151: ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20152: ref->name, ref->targetNamespace);
20153: if (ause->attrDecl == NULL) {
20154: xmlSchemaPResCompAttrErr(ctxt,
20155: XML_SCHEMAP_SRC_RESOLVE,
20156: WXS_BASIC_CAST ause, ause->node,
20157: "ref", ref->name, ref->targetNamespace,
20158: XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20159: return(ctxt->err);;
20160: }
20161: }
20162: return(0);
20163: }
20164:
20165: /**
20166: * xmlSchemaCheckAttrUsePropsCorrect:
20167: * @ctxt: a parser context
20168: * @use: an attribute use
20169: *
20170: * Schema Component Constraint:
20171: * Attribute Use Correct (au-props-correct)
20172: *
20173: */
20174: static int
20175: xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20176: xmlSchemaAttributeUsePtr use)
20177: {
20178: if ((ctxt == NULL) || (use == NULL))
20179: return(-1);
20180: if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20181: ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20182: return(0);
20183:
20184: /*
20185: * SPEC au-props-correct (1)
20186: * "The values of the properties of an attribute use must be as
20187: * described in the property tableau in The Attribute Use Schema
20188: * Component (�3.5.1), modulo the impact of Missing
20189: * Sub-components (�5.3)."
20190: */
20191:
20192: if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20193: ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20194: ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20195: {
20196: xmlSchemaPCustomErr(ctxt,
20197: XML_SCHEMAP_AU_PROPS_CORRECT_2,
20198: WXS_BASIC_CAST use, NULL,
20199: "The attribute declaration has a 'fixed' value constraint "
20200: ", thus the attribute use must also have a 'fixed' value "
20201: "constraint",
20202: NULL);
20203: return(ctxt->err);
20204: }
20205: /*
20206: * Compute and check the value constraint's value.
20207: */
20208: if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20209: int ret;
20210: /*
20211: * TODO: The spec seems to be missing a check of the
20212: * value constraint of the attribute use. We will do it here.
20213: */
20214: /*
20215: * SPEC a-props-correct (3)
20216: */
20217: if (xmlSchemaIsDerivedFromBuiltInType(
20218: WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20219: {
20220: xmlSchemaCustomErr(ACTXT_CAST ctxt,
20221: XML_SCHEMAP_AU_PROPS_CORRECT,
20222: NULL, WXS_BASIC_CAST use,
20223: "Value constraints are not allowed if the type definition "
20224: "is or is derived from xs:ID",
20225: NULL, NULL);
20226: return(ctxt->err);
20227: }
20228:
20229: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20230: use->node, WXS_ATTRUSE_TYPEDEF(use),
20231: use->defValue, &(use->defVal),
20232: 1, 1, 0);
20233: if (ret != 0) {
20234: if (ret < 0) {
20235: PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20236: "calling xmlSchemaVCheckCVCSimpleType()");
20237: return(-1);
20238: }
20239: xmlSchemaCustomErr(ACTXT_CAST ctxt,
20240: XML_SCHEMAP_AU_PROPS_CORRECT,
20241: NULL, WXS_BASIC_CAST use,
20242: "The value of the value constraint is not valid",
20243: NULL, NULL);
20244: return(ctxt->err);
20245: }
20246: }
20247: /*
20248: * SPEC au-props-correct (2)
20249: * "If the {attribute declaration} has a fixed
20250: * {value constraint}, then if the attribute use itself has a
20251: * {value constraint}, it must also be fixed and its value must match
20252: * that of the {attribute declaration}'s {value constraint}."
20253: */
20254: if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20255: (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20256: {
20257: if (! xmlSchemaAreValuesEqual(use->defVal,
20258: (WXS_ATTRUSE_DECL(use))->defVal))
20259: {
20260: xmlSchemaPCustomErr(ctxt,
20261: XML_SCHEMAP_AU_PROPS_CORRECT_2,
20262: WXS_BASIC_CAST use, NULL,
20263: "The 'fixed' value constraint of the attribute use "
20264: "must match the attribute declaration's value "
20265: "constraint '%s'",
20266: (WXS_ATTRUSE_DECL(use))->defValue);
20267: }
20268: return(ctxt->err);
20269: }
20270: return(0);
20271: }
20272:
20273:
20274:
20275:
20276: /**
20277: * xmlSchemaResolveAttrTypeReferences:
20278: * @item: an attribute declaration
20279: * @ctxt: a parser context
20280: *
20281: * Resolves the referenced type definition component.
20282: */
20283: static int
20284: xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20285: xmlSchemaParserCtxtPtr ctxt)
20286: {
20287: /*
20288: * The simple type definition corresponding to the <simpleType> element
20289: * information item in the [children], if present, otherwise the simple
20290: * type definition �resolved� to by the �actual value� of the type
20291: * [attribute], if present, otherwise the �simple ur-type definition�.
20292: */
20293: if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20294: return(0);
20295: item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20296: if (item->subtypes != NULL)
20297: return(0);
20298: if (item->typeName != NULL) {
20299: xmlSchemaTypePtr type;
20300:
20301: type = xmlSchemaGetType(ctxt->schema, item->typeName,
20302: item->typeNs);
20303: if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20304: xmlSchemaPResCompAttrErr(ctxt,
20305: XML_SCHEMAP_SRC_RESOLVE,
20306: WXS_BASIC_CAST item, item->node,
20307: "type", item->typeName, item->typeNs,
20308: XML_SCHEMA_TYPE_SIMPLE, NULL);
20309: return(ctxt->err);
20310: } else
20311: item->subtypes = type;
20312:
20313: } else {
20314: /*
20315: * The type defaults to the xs:anySimpleType.
20316: */
20317: item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20318: }
20319: return(0);
20320: }
20321:
20322: /**
20323: * xmlSchemaResolveIDCKeyReferences:
20324: * @idc: the identity-constraint definition
20325: * @ctxt: the schema parser context
20326: * @name: the attribute name
20327: *
20328: * Resolve keyRef references to key/unique IDCs.
20329: * Schema Component Constraint:
20330: * Identity-constraint Definition Properties Correct (c-props-correct)
20331: */
20332: static int
20333: xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20334: xmlSchemaParserCtxtPtr pctxt)
20335: {
20336: if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20337: return(0);
20338: if (idc->ref->name != NULL) {
20339: idc->ref->item = (xmlSchemaBasicItemPtr)
20340: xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20341: idc->ref->targetNamespace);
20342: if (idc->ref->item == NULL) {
20343: /*
20344: * TODO: It is actually not an error to fail to resolve
20345: * at this stage. BUT we need to be that strict!
20346: */
20347: xmlSchemaPResCompAttrErr(pctxt,
20348: XML_SCHEMAP_SRC_RESOLVE,
20349: WXS_BASIC_CAST idc, idc->node,
20350: "refer", idc->ref->name,
20351: idc->ref->targetNamespace,
20352: XML_SCHEMA_TYPE_IDC_KEY, NULL);
20353: return(pctxt->err);
20354: } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20355: /*
20356: * SPEC c-props-correct (1)
20357: */
20358: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20359: XML_SCHEMAP_C_PROPS_CORRECT,
20360: NULL, WXS_BASIC_CAST idc,
20361: "The keyref references a keyref",
20362: NULL, NULL);
20363: idc->ref->item = NULL;
20364: return(pctxt->err);
20365: } else {
20366: if (idc->nbFields !=
20367: ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20368: xmlChar *str = NULL;
20369: xmlSchemaIDCPtr refer;
20370:
20371: refer = (xmlSchemaIDCPtr) idc->ref->item;
20372: /*
20373: * SPEC c-props-correct(2)
20374: * "If the {identity-constraint category} is keyref,
20375: * the cardinality of the {fields} must equal that of
20376: * the {fields} of the {referenced key}.
20377: */
20378: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20379: XML_SCHEMAP_C_PROPS_CORRECT,
20380: NULL, WXS_BASIC_CAST idc,
20381: "The cardinality of the keyref differs from the "
20382: "cardinality of the referenced key/unique '%s'",
20383: xmlSchemaFormatQName(&str, refer->targetNamespace,
20384: refer->name),
20385: NULL);
20386: FREE_AND_NULL(str)
20387: return(pctxt->err);
20388: }
20389: }
20390: }
20391: return(0);
20392: }
20393:
20394: static int
20395: xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20396: xmlSchemaParserCtxtPtr pctxt)
20397: {
20398: if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20399: prohib->targetNamespace) == NULL) {
20400:
20401: xmlSchemaPResCompAttrErr(pctxt,
20402: XML_SCHEMAP_SRC_RESOLVE,
20403: NULL, prohib->node,
20404: "ref", prohib->name, prohib->targetNamespace,
20405: XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20406: return(XML_SCHEMAP_SRC_RESOLVE);
20407: }
20408: return(0);
20409: }
20410:
20411: #define WXS_REDEFINED_TYPE(c) \
20412: (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20413:
20414: #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20415: (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20416:
20417: #define WXS_REDEFINED_ATTR_GROUP(c) \
20418: (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20419:
20420: static int
20421: xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20422: {
20423: int err = 0;
20424: xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20425: xmlSchemaBasicItemPtr prev, item;
20426: int wasRedefined;
20427:
20428: if (redef == NULL)
20429: return(0);
20430:
20431: do {
20432: item = redef->item;
20433: /*
20434: * First try to locate the redefined component in the
20435: * schema graph starting with the redefined schema.
20436: * NOTE: According to this schema bug entry:
20437: * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20438: * it's not clear if the referenced component needs to originate
20439: * from the <redefine>d schema _document_ or the schema; the latter
20440: * would include all imported and included sub-schemas of the
20441: * <redefine>d schema. Currenlty we latter approach is used.
20442: * SUPPLEMENT: It seems that the WG moves towards the latter
20443: * approach, so we are doing it right.
20444: *
20445: */
20446: prev = xmlSchemaFindRedefCompInGraph(
20447: redef->targetBucket, item->type,
20448: redef->refName, redef->refTargetNs);
20449: if (prev == NULL) {
20450: xmlChar *str = NULL;
20451: xmlNodePtr node;
20452:
20453: /*
20454: * SPEC src-redefine:
20455: * (6.2.1) "The �actual value� of its own name attribute plus
20456: * target namespace must successfully �resolve� to a model
20457: * group definition in I."
20458: * (7.2.1) "The �actual value� of its own name attribute plus
20459: * target namespace must successfully �resolve� to an attribute
20460: * group definition in I."
20461:
20462: *
20463: * Note that, if we are redefining with the use of references
20464: * to components, the spec assumes the src-resolve to be used;
20465: * but this won't assure that we search only *inside* the
20466: * redefined schema.
20467: */
20468: if (redef->reference)
20469: node = WXS_ITEM_NODE(redef->reference);
20470: else
20471: node = WXS_ITEM_NODE(item);
20472: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20473: /*
20474: * TODO: error code.
20475: * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20476: * reference kind.
20477: */
20478: XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20479: "The %s '%s' to be redefined could not be found in "
20480: "the redefined schema",
20481: WXS_ITEM_TYPE_NAME(item),
20482: xmlSchemaFormatQName(&str, redef->refTargetNs,
20483: redef->refName));
20484: FREE_AND_NULL(str);
20485: err = pctxt->err;
20486: redef = redef->next;
20487: continue;
20488: }
20489: /*
20490: * TODO: Obtaining and setting the redefinition state is really
20491: * clumsy.
20492: */
20493: wasRedefined = 0;
20494: switch (item->type) {
20495: case XML_SCHEMA_TYPE_COMPLEX:
20496: case XML_SCHEMA_TYPE_SIMPLE:
20497: if ((WXS_TYPE_CAST prev)->flags &
20498: XML_SCHEMAS_TYPE_REDEFINED)
20499: {
20500: wasRedefined = 1;
20501: break;
20502: }
20503: /* Mark it as redefined. */
20504: (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20505: /*
20506: * Assign the redefined type to the
20507: * base type of the redefining type.
20508: * TODO: How
20509: */
20510: ((xmlSchemaTypePtr) item)->baseType =
20511: (xmlSchemaTypePtr) prev;
20512: break;
20513: case XML_SCHEMA_TYPE_GROUP:
20514: if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20515: XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20516: {
20517: wasRedefined = 1;
20518: break;
20519: }
20520: /* Mark it as redefined. */
20521: (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20522: XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20523: if (redef->reference != NULL) {
20524: /*
20525: * Overwrite the QName-reference with the
20526: * referenced model group def.
20527: */
20528: (WXS_PTC_CAST redef->reference)->children =
20529: WXS_TREE_CAST prev;
20530: }
20531: redef->target = prev;
20532: break;
20533: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20534: if ((WXS_ATTR_GROUP_CAST prev)->flags &
20535: XML_SCHEMAS_ATTRGROUP_REDEFINED)
20536: {
20537: wasRedefined = 1;
20538: break;
20539: }
20540: (WXS_ATTR_GROUP_CAST prev)->flags |=
20541: XML_SCHEMAS_ATTRGROUP_REDEFINED;
20542: if (redef->reference != NULL) {
20543: /*
20544: * Assign the redefined attribute group to the
20545: * QName-reference component.
20546: * This is the easy case, since we will just
20547: * expand the redefined group.
20548: */
20549: (WXS_QNAME_CAST redef->reference)->item = prev;
20550: redef->target = NULL;
20551: } else {
20552: /*
20553: * This is the complicated case: we need
20554: * to apply src-redefine (7.2.2) at a later
20555: * stage, i.e. when attribute group references
20556: * have beed expanded and simple types have
20557: * beed fixed.
20558: */
20559: redef->target = prev;
20560: }
20561: break;
20562: default:
20563: PERROR_INT("xmlSchemaResolveRedefReferences",
20564: "Unexpected redefined component type");
20565: return(-1);
20566: }
20567: if (wasRedefined) {
20568: xmlChar *str = NULL;
20569: xmlNodePtr node;
20570:
20571: if (redef->reference)
20572: node = WXS_ITEM_NODE(redef->reference);
20573: else
20574: node = WXS_ITEM_NODE(redef->item);
20575:
20576: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20577: /* TODO: error code. */
20578: XML_SCHEMAP_SRC_REDEFINE,
20579: node, NULL,
20580: "The referenced %s was already redefined. Multiple "
20581: "redefinition of the same component is not supported",
20582: xmlSchemaGetComponentDesignation(&str, prev),
20583: NULL);
20584: FREE_AND_NULL(str)
20585: err = pctxt->err;
20586: redef = redef->next;
20587: continue;
20588: }
20589: redef = redef->next;
20590: } while (redef != NULL);
20591:
20592: return(err);
20593: }
20594:
20595: static int
20596: xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20597: {
20598: int err = 0;
20599: xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20600: xmlSchemaBasicItemPtr item;
20601:
20602: if (redef == NULL)
20603: return(0);
20604:
20605: do {
20606: if (redef->target == NULL) {
20607: redef = redef->next;
20608: continue;
20609: }
20610: item = redef->item;
20611:
20612: switch (item->type) {
20613: case XML_SCHEMA_TYPE_SIMPLE:
20614: case XML_SCHEMA_TYPE_COMPLEX:
20615: /*
20616: * Since the spec wants the {name} of the redefined
20617: * type to be 'absent', we'll NULL it.
20618: */
20619: (WXS_TYPE_CAST redef->target)->name = NULL;
20620:
20621: /*
20622: * TODO: Seems like there's nothing more to do. The normal
20623: * inheritance mechanism is used. But not 100% sure.
20624: */
20625: break;
20626: case XML_SCHEMA_TYPE_GROUP:
20627: /*
20628: * URGENT TODO:
20629: * SPEC src-redefine:
20630: * (6.2.2) "The {model group} of the model group definition
20631: * which corresponds to it per XML Representation of Model
20632: * Group Definition Schema Components (�3.7.2) must be a
20633: * �valid restriction� of the {model group} of that model
20634: * group definition in I, as defined in Particle Valid
20635: * (Restriction) (�3.9.6)."
20636: */
20637: break;
20638: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20639: /*
20640: * SPEC src-redefine:
20641: * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20642: * the attribute group definition which corresponds to it
20643: * per XML Representation of Attribute Group Definition Schema
20644: * Components (�3.6.2) must be �valid restrictions� of the
20645: * {attribute uses} and {attribute wildcard} of that attribute
20646: * group definition in I, as defined in clause 2, clause 3 and
20647: * clause 4 of Derivation Valid (Restriction, Complex)
20648: * (�3.4.6) (where references to the base type definition are
20649: * understood as references to the attribute group definition
20650: * in I)."
20651: */
20652: err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20653: XML_SCHEMA_ACTION_REDEFINE,
20654: item, redef->target,
20655: (WXS_ATTR_GROUP_CAST item)->attrUses,
20656: (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20657: (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20658: (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20659: if (err == -1)
20660: return(-1);
20661: break;
20662: default:
20663: break;
20664: }
20665: redef = redef->next;
20666: } while (redef != NULL);
20667: return(0);
20668: }
20669:
20670:
20671: static int
20672: xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20673: xmlSchemaBucketPtr bucket)
20674: {
20675: xmlSchemaBasicItemPtr item;
20676: int err;
20677: xmlHashTablePtr *table;
20678: const xmlChar *name;
20679: int i;
20680:
20681: #define WXS_GET_GLOBAL_HASH(c, slot) { \
20682: if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20683: table = &(WXS_IMPBUCKET((c))->schema->slot); \
20684: else \
20685: table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20686:
20687: /*
20688: * Add global components to the schema's hash tables.
20689: * This is the place where duplicate components will be
20690: * detected.
20691: * TODO: I think normally we should support imports of the
20692: * same namespace from multiple locations. We don't do currently,
20693: * but if we do then according to:
20694: * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20695: * we would need, if imported directly, to import redefined
20696: * components as well to be able to catch clashing components.
20697: * (I hope I'll still know what this means after some months :-()
20698: */
20699: if (bucket == NULL)
20700: return(-1);
20701: if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20702: return(0);
20703: bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20704:
20705: for (i = 0; i < bucket->globals->nbItems; i++) {
20706: item = bucket->globals->items[i];
20707: table = NULL;
20708: switch (item->type) {
20709: case XML_SCHEMA_TYPE_COMPLEX:
20710: case XML_SCHEMA_TYPE_SIMPLE:
20711: if (WXS_REDEFINED_TYPE(item))
20712: continue;
20713: name = (WXS_TYPE_CAST item)->name;
20714: WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20715: break;
20716: case XML_SCHEMA_TYPE_ELEMENT:
20717: name = (WXS_ELEM_CAST item)->name;
20718: WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20719: break;
20720: case XML_SCHEMA_TYPE_ATTRIBUTE:
20721: name = (WXS_ATTR_CAST item)->name;
20722: WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20723: break;
20724: case XML_SCHEMA_TYPE_GROUP:
20725: if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20726: continue;
20727: name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20728: WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20729: break;
20730: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20731: if (WXS_REDEFINED_ATTR_GROUP(item))
20732: continue;
20733: name = (WXS_ATTR_GROUP_CAST item)->name;
20734: WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20735: break;
20736: case XML_SCHEMA_TYPE_IDC_KEY:
20737: case XML_SCHEMA_TYPE_IDC_UNIQUE:
20738: case XML_SCHEMA_TYPE_IDC_KEYREF:
20739: name = (WXS_IDC_CAST item)->name;
20740: WXS_GET_GLOBAL_HASH(bucket, idcDef)
20741: break;
20742: case XML_SCHEMA_TYPE_NOTATION:
20743: name = ((xmlSchemaNotationPtr) item)->name;
20744: WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20745: break;
20746: default:
20747: PERROR_INT("xmlSchemaAddComponents",
20748: "Unexpected global component type");
20749: continue;
20750: }
20751: if (*table == NULL) {
20752: *table = xmlHashCreateDict(10, pctxt->dict);
20753: if (*table == NULL) {
20754: PERROR_INT("xmlSchemaAddComponents",
20755: "failed to create a component hash table");
20756: return(-1);
20757: }
20758: }
20759: err = xmlHashAddEntry(*table, name, item);
20760: if (err != 0) {
20761: xmlChar *str = NULL;
20762:
20763: xmlSchemaCustomErr(ACTXT_CAST pctxt,
20764: XML_SCHEMAP_REDEFINED_TYPE,
20765: WXS_ITEM_NODE(item),
20766: WXS_BASIC_CAST item,
20767: "A global %s '%s' does already exist",
20768: WXS_ITEM_TYPE_NAME(item),
20769: xmlSchemaGetComponentQName(&str, item));
20770: FREE_AND_NULL(str);
20771: }
20772: }
20773: /*
20774: * Process imported/included schemas.
20775: */
20776: if (bucket->relations != NULL) {
20777: xmlSchemaSchemaRelationPtr rel = bucket->relations;
20778: do {
20779: if ((rel->bucket != NULL) &&
20780: ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20781: if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20782: return(-1);
20783: }
20784: rel = rel->next;
20785: } while (rel != NULL);
20786: }
20787: return(0);
20788: }
20789:
20790: static int
20791: xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20792: xmlSchemaBucketPtr rootBucket)
20793: {
20794: xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20795: xmlSchemaTreeItemPtr item, *items;
20796: int nbItems, i, ret = 0;
20797: xmlSchemaBucketPtr oldbucket = con->bucket;
20798: xmlSchemaElementPtr elemDecl;
20799:
20800: #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20801:
20802: if ((con->pending == NULL) ||
20803: (con->pending->nbItems == 0))
20804: return(0);
20805:
20806: /*
20807: * Since xmlSchemaFixupComplexType() will create new particles
20808: * (local components), and those particle components need a bucket
20809: * on the constructor, we'll assure here that the constructor has
20810: * a bucket.
20811: * TODO: Think about storing locals _only_ on the main bucket.
20812: */
20813: if (con->bucket == NULL)
20814: con->bucket = rootBucket;
20815:
20816: /* TODO:
20817: * SPEC (src-redefine):
20818: * (6.2) "If it has no such self-reference, then all of the
20819: * following must be true:"
20820:
20821: * (6.2.2) The {model group} of the model group definition which
20822: * corresponds to it per XML Representation of Model Group
20823: * Definition Schema Components (�3.7.2) must be a �valid
20824: * restriction� of the {model group} of that model group definition
20825: * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20826: */
20827: xmlSchemaCheckSRCRedefineFirst(pctxt);
20828:
20829: /*
20830: * Add global components to the schemata's hash tables.
20831: */
20832: xmlSchemaAddComponents(pctxt, rootBucket);
20833:
20834: pctxt->ctxtType = NULL;
20835: items = (xmlSchemaTreeItemPtr *) con->pending->items;
20836: nbItems = con->pending->nbItems;
20837: /*
20838: * Now that we have parsed *all* the schema document(s) and converted
20839: * them to schema components, we can resolve references, apply component
20840: * constraints, create the FSA from the content model, etc.
20841: */
20842: /*
20843: * Resolve references of..
20844: *
20845: * 1. element declarations:
20846: * - the type definition
20847: * - the substitution group affiliation
20848: * 2. simple/complex types:
20849: * - the base type definition
20850: * - the memberTypes of union types
20851: * - the itemType of list types
20852: * 3. attributes declarations and attribute uses:
20853: * - the type definition
20854: * - if an attribute use, then the attribute declaration
20855: * 4. attribute group references:
20856: * - the attribute group definition
20857: * 5. particles:
20858: * - the term of the particle (e.g. a model group)
20859: * 6. IDC key-references:
20860: * - the referenced IDC 'key' or 'unique' definition
20861: * 7. Attribute prohibitions which had a "ref" attribute.
20862: */
20863: for (i = 0; i < nbItems; i++) {
20864: item = items[i];
20865: switch (item->type) {
20866: case XML_SCHEMA_TYPE_ELEMENT:
20867: xmlSchemaResolveElementReferences(
20868: (xmlSchemaElementPtr) item, pctxt);
20869: FIXHFAILURE;
20870: break;
20871: case XML_SCHEMA_TYPE_COMPLEX:
20872: case XML_SCHEMA_TYPE_SIMPLE:
20873: xmlSchemaResolveTypeReferences(
20874: (xmlSchemaTypePtr) item, pctxt);
20875: FIXHFAILURE;
20876: break;
20877: case XML_SCHEMA_TYPE_ATTRIBUTE:
20878: xmlSchemaResolveAttrTypeReferences(
20879: (xmlSchemaAttributePtr) item, pctxt);
20880: FIXHFAILURE;
20881: break;
20882: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20883: xmlSchemaResolveAttrUseReferences(
20884: (xmlSchemaAttributeUsePtr) item, pctxt);
20885: FIXHFAILURE;
20886: break;
20887: case XML_SCHEMA_EXTRA_QNAMEREF:
20888: if ((WXS_QNAME_CAST item)->itemType ==
20889: XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20890: {
20891: xmlSchemaResolveAttrGroupReferences(
20892: WXS_QNAME_CAST item, pctxt);
20893: }
20894: FIXHFAILURE;
20895: break;
20896: case XML_SCHEMA_TYPE_SEQUENCE:
20897: case XML_SCHEMA_TYPE_CHOICE:
20898: case XML_SCHEMA_TYPE_ALL:
20899: xmlSchemaResolveModelGroupParticleReferences(pctxt,
20900: WXS_MODEL_GROUP_CAST item);
20901: FIXHFAILURE;
20902: break;
20903: case XML_SCHEMA_TYPE_IDC_KEY:
20904: case XML_SCHEMA_TYPE_IDC_UNIQUE:
20905: case XML_SCHEMA_TYPE_IDC_KEYREF:
20906: xmlSchemaResolveIDCKeyReferences(
20907: (xmlSchemaIDCPtr) item, pctxt);
20908: FIXHFAILURE;
20909: break;
20910: case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20911: /*
20912: * Handle attribue prohibition which had a
20913: * "ref" attribute.
20914: */
20915: xmlSchemaResolveAttrUseProhibReferences(
20916: WXS_ATTR_PROHIB_CAST item, pctxt);
20917: FIXHFAILURE;
20918: break;
20919: default:
20920: break;
20921: }
20922: }
20923: if (pctxt->nberrors != 0)
20924: goto exit_error;
20925:
20926: /*
20927: * Now that all references are resolved we
20928: * can check for circularity of...
20929: * 1. the base axis of type definitions
20930: * 2. nested model group definitions
20931: * 3. nested attribute group definitions
20932: * TODO: check for circual substitution groups.
20933: */
20934: for (i = 0; i < nbItems; i++) {
20935: item = items[i];
20936: /*
20937: * Let's better stop on the first error here.
20938: */
20939: switch (item->type) {
20940: case XML_SCHEMA_TYPE_COMPLEX:
20941: case XML_SCHEMA_TYPE_SIMPLE:
20942: xmlSchemaCheckTypeDefCircular(
20943: (xmlSchemaTypePtr) item, pctxt);
20944: FIXHFAILURE;
20945: if (pctxt->nberrors != 0)
20946: goto exit_error;
20947: break;
20948: case XML_SCHEMA_TYPE_GROUP:
20949: xmlSchemaCheckGroupDefCircular(
20950: (xmlSchemaModelGroupDefPtr) item, pctxt);
20951: FIXHFAILURE;
20952: if (pctxt->nberrors != 0)
20953: goto exit_error;
20954: break;
20955: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20956: xmlSchemaCheckAttrGroupCircular(
20957: (xmlSchemaAttributeGroupPtr) item, pctxt);
20958: FIXHFAILURE;
20959: if (pctxt->nberrors != 0)
20960: goto exit_error;
20961: break;
20962: default:
20963: break;
20964: }
20965: }
20966: if (pctxt->nberrors != 0)
20967: goto exit_error;
20968: /*
20969: * Model group definition references:
20970: * Such a reference is reflected by a particle at the component
20971: * level. Until now the 'term' of such particles pointed
20972: * to the model group definition; this was done, in order to
20973: * ease circularity checks. Now we need to set the 'term' of
20974: * such particles to the model group of the model group definition.
20975: */
20976: for (i = 0; i < nbItems; i++) {
20977: item = items[i];
20978: switch (item->type) {
20979: case XML_SCHEMA_TYPE_SEQUENCE:
20980: case XML_SCHEMA_TYPE_CHOICE:
20981: xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20982: WXS_MODEL_GROUP_CAST item);
20983: break;
20984: default:
20985: break;
20986: }
20987: }
20988: if (pctxt->nberrors != 0)
20989: goto exit_error;
20990: /*
20991: * Expand attribute group references of attribute group definitions.
20992: */
20993: for (i = 0; i < nbItems; i++) {
20994: item = items[i];
20995: switch (item->type) {
20996: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20997: if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20998: WXS_ATTR_GROUP_HAS_REFS(item))
20999: {
21000: xmlSchemaAttributeGroupExpandRefs(pctxt,
21001: WXS_ATTR_GROUP_CAST item);
21002: FIXHFAILURE;
21003: }
21004: break;
21005: default:
21006: break;
21007: }
21008: }
21009: if (pctxt->nberrors != 0)
21010: goto exit_error;
21011: /*
21012: * First compute the variety of simple types. This is needed as
21013: * a seperate step, since otherwise we won't be able to detect
21014: * circular union types in all cases.
21015: */
21016: for (i = 0; i < nbItems; i++) {
21017: item = items[i];
21018: switch (item->type) {
21019: case XML_SCHEMA_TYPE_SIMPLE:
21020: if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21021: xmlSchemaFixupSimpleTypeStageOne(pctxt,
21022: (xmlSchemaTypePtr) item);
21023: FIXHFAILURE;
21024: }
21025: break;
21026: default:
21027: break;
21028: }
21029: }
21030: if (pctxt->nberrors != 0)
21031: goto exit_error;
21032: /*
21033: * Detect circular union types. Note that this needs the variety to
21034: * be already computed.
21035: */
21036: for (i = 0; i < nbItems; i++) {
21037: item = items[i];
21038: switch (item->type) {
21039: case XML_SCHEMA_TYPE_SIMPLE:
21040: if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21041: xmlSchemaCheckUnionTypeDefCircular(pctxt,
21042: (xmlSchemaTypePtr) item);
21043: FIXHFAILURE;
21044: }
21045: break;
21046: default:
21047: break;
21048: }
21049: }
21050: if (pctxt->nberrors != 0)
21051: goto exit_error;
21052:
21053: /*
21054: * Do the complete type fixup for simple types.
21055: */
21056: for (i = 0; i < nbItems; i++) {
21057: item = items[i];
21058: switch (item->type) {
21059: case XML_SCHEMA_TYPE_SIMPLE:
21060: if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21061: xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21062: FIXHFAILURE;
21063: }
21064: break;
21065: default:
21066: break;
21067: }
21068: }
21069: if (pctxt->nberrors != 0)
21070: goto exit_error;
21071: /*
21072: * At this point we need build and check all simple types.
21073: */
21074: /*
21075: * Apply contraints for attribute declarations.
21076: */
21077: for (i = 0; i < nbItems; i++) {
21078: item = items[i];
21079: switch (item->type) {
21080: case XML_SCHEMA_TYPE_ATTRIBUTE:
21081: xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21082: FIXHFAILURE;
21083: break;
21084: default:
21085: break;
21086: }
21087: }
21088: if (pctxt->nberrors != 0)
21089: goto exit_error;
21090: /*
21091: * Apply constraints for attribute uses.
21092: */
21093: for (i = 0; i < nbItems; i++) {
21094: item = items[i];
21095: switch (item->type) {
21096: case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21097: if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21098: xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21099: WXS_ATTR_USE_CAST item);
21100: FIXHFAILURE;
21101: }
21102: break;
21103: default:
21104: break;
21105: }
21106: }
21107: if (pctxt->nberrors != 0)
21108: goto exit_error;
21109:
21110: /*
21111: * Apply constraints for attribute group definitions.
21112: */
21113: for (i = 0; i < nbItems; i++) {
21114: item = items[i];
21115: switch (item->type) {
21116: case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21117: if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21118: ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21119: {
21120: xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21121: FIXHFAILURE;
21122: }
21123: break;
21124: default:
21125: break;
21126: }
21127: }
21128: if (pctxt->nberrors != 0)
21129: goto exit_error;
21130:
21131: /*
21132: * Apply constraints for redefinitions.
21133: */
21134: if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21135: xmlSchemaCheckSRCRedefineSecond(pctxt);
21136: if (pctxt->nberrors != 0)
21137: goto exit_error;
21138:
21139: /*
21140: * Complex types are builded and checked.
21141: */
21142: for (i = 0; i < nbItems; i++) {
21143: item = con->pending->items[i];
21144: switch (item->type) {
21145: case XML_SCHEMA_TYPE_COMPLEX:
21146: if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21147: xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21148: FIXHFAILURE;
21149: }
21150: break;
21151: default:
21152: break;
21153: }
21154: }
21155: if (pctxt->nberrors != 0)
21156: goto exit_error;
21157:
21158: /*
21159: * The list could have changed, since xmlSchemaFixupComplexType()
21160: * will create particles and model groups in some cases.
21161: */
21162: items = (xmlSchemaTreeItemPtr *) con->pending->items;
21163: nbItems = con->pending->nbItems;
21164:
21165: /*
21166: * Apply some constraints for element declarations.
21167: */
21168: for (i = 0; i < nbItems; i++) {
21169: item = items[i];
21170: switch (item->type) {
21171: case XML_SCHEMA_TYPE_ELEMENT:
21172: elemDecl = (xmlSchemaElementPtr) item;
21173:
21174: if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21175: {
21176: xmlSchemaCheckElementDeclComponent(
21177: (xmlSchemaElementPtr) elemDecl, pctxt);
21178: FIXHFAILURE;
21179: }
21180:
21181: #ifdef WXS_ELEM_DECL_CONS_ENABLED
21182: /*
21183: * Schema Component Constraint: Element Declarations Consistent
21184: * Apply this constraint to local types of element declarations.
21185: */
21186: if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21187: (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21188: (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21189: {
21190: xmlSchemaCheckElementDeclConsistent(pctxt,
21191: WXS_BASIC_CAST elemDecl,
21192: WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21193: NULL, NULL, 0);
21194: }
21195: #endif
21196: break;
21197: default:
21198: break;
21199: }
21200: }
21201: if (pctxt->nberrors != 0)
21202: goto exit_error;
21203:
21204: /*
21205: * Finally we can build the automaton from the content model of
21206: * complex types.
21207: */
21208:
21209: for (i = 0; i < nbItems; i++) {
21210: item = items[i];
21211: switch (item->type) {
21212: case XML_SCHEMA_TYPE_COMPLEX:
21213: xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21214: /* FIXHFAILURE; */
21215: break;
21216: default:
21217: break;
21218: }
21219: }
21220: if (pctxt->nberrors != 0)
21221: goto exit_error;
21222: /*
21223: * URGENT TODO: cos-element-consistent
21224: */
21225: goto exit;
21226:
21227: exit_error:
21228: ret = pctxt->err;
21229: goto exit;
21230:
21231: exit_failure:
21232: ret = -1;
21233:
21234: exit:
21235: /*
21236: * Reset the constructor. This is needed for XSI acquisition, since
21237: * those items will be processed over and over again for every XSI
21238: * if not cleared here.
21239: */
21240: con->bucket = oldbucket;
21241: con->pending->nbItems = 0;
21242: if (con->substGroups != NULL) {
21243: xmlHashFree(con->substGroups,
21244: (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21245: con->substGroups = NULL;
21246: }
21247: if (con->redefs != NULL) {
21248: xmlSchemaRedefListFree(con->redefs);
21249: con->redefs = NULL;
21250: }
21251: return(ret);
21252: }
21253: /**
21254: * xmlSchemaParse:
21255: * @ctxt: a schema validation context
21256: *
21257: * parse a schema definition resource and build an internal
21258: * XML Shema struture which can be used to validate instances.
21259: *
21260: * Returns the internal XML Schema structure built from the resource or
21261: * NULL in case of error
21262: */
21263: xmlSchemaPtr
21264: xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21265: {
21266: xmlSchemaPtr mainSchema = NULL;
21267: xmlSchemaBucketPtr bucket = NULL;
21268: int res;
21269:
21270: /*
21271: * This one is used if the schema to be parsed was specified via
21272: * the API; i.e. not automatically by the validated instance document.
21273: */
21274:
21275: xmlSchemaInitTypes();
21276:
21277: if (ctxt == NULL)
21278: return (NULL);
21279:
21280: /* TODO: Init the context. Is this all we need?*/
21281: ctxt->nberrors = 0;
21282: ctxt->err = 0;
21283: ctxt->counter = 0;
21284:
21285: /* Create the *main* schema. */
21286: mainSchema = xmlSchemaNewSchema(ctxt);
21287: if (mainSchema == NULL)
21288: goto exit_failure;
21289: /*
21290: * Create the schema constructor.
21291: */
21292: if (ctxt->constructor == NULL) {
21293: ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21294: if (ctxt->constructor == NULL)
21295: return(NULL);
21296: /* Take ownership of the constructor to be able to free it. */
21297: ctxt->ownsConstructor = 1;
21298: }
21299: ctxt->constructor->mainSchema = mainSchema;
21300: /*
21301: * Locate and add the schema document.
21302: */
21303: res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21304: ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21305: NULL, NULL, &bucket);
21306: if (res == -1)
21307: goto exit_failure;
21308: if (res != 0)
21309: goto exit;
21310:
21311: if (bucket == NULL) {
21312: /* TODO: Error code, actually we failed to *locate* the schema. */
21313: if (ctxt->URL)
21314: xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21315: NULL, NULL,
21316: "Failed to locate the main schema resource at '%s'",
21317: ctxt->URL, NULL);
21318: else
21319: xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21320: NULL, NULL,
21321: "Failed to locate the main schema resource",
21322: NULL, NULL);
21323: goto exit;
21324: }
21325: /* Then do the parsing for good. */
21326: if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21327: goto exit_failure;
21328: if (ctxt->nberrors != 0)
21329: goto exit;
21330:
21331: mainSchema->doc = bucket->doc;
21332: mainSchema->preserve = ctxt->preserve;
21333:
21334: ctxt->schema = mainSchema;
21335:
21336: if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21337: goto exit_failure;
21338:
21339: /*
21340: * TODO: This is not nice, since we cannot distinguish from the
21341: * result if there was an internal error or not.
21342: */
21343: exit:
21344: if (ctxt->nberrors != 0) {
21345: if (mainSchema) {
21346: xmlSchemaFree(mainSchema);
21347: mainSchema = NULL;
21348: }
21349: if (ctxt->constructor) {
21350: xmlSchemaConstructionCtxtFree(ctxt->constructor);
21351: ctxt->constructor = NULL;
21352: ctxt->ownsConstructor = 0;
21353: }
21354: }
21355: ctxt->schema = NULL;
21356: return(mainSchema);
21357: exit_failure:
21358: /*
21359: * Quite verbose, but should catch internal errors, which were
21360: * not communitated.
21361: */
21362: if (mainSchema) {
21363: xmlSchemaFree(mainSchema);
21364: mainSchema = NULL;
21365: }
21366: if (ctxt->constructor) {
21367: xmlSchemaConstructionCtxtFree(ctxt->constructor);
21368: ctxt->constructor = NULL;
21369: ctxt->ownsConstructor = 0;
21370: }
21371: PERROR_INT2("xmlSchemaParse",
21372: "An internal error occured");
21373: ctxt->schema = NULL;
21374: return(NULL);
21375: }
21376:
21377: /**
21378: * xmlSchemaSetParserErrors:
21379: * @ctxt: a schema validation context
21380: * @err: the error callback
21381: * @warn: the warning callback
21382: * @ctx: contextual data for the callbacks
21383: *
21384: * Set the callback functions used to handle errors for a validation context
21385: */
21386: void
21387: xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21388: xmlSchemaValidityErrorFunc err,
21389: xmlSchemaValidityWarningFunc warn, void *ctx)
21390: {
21391: if (ctxt == NULL)
21392: return;
21393: ctxt->error = err;
21394: ctxt->warning = warn;
21395: ctxt->errCtxt = ctx;
21396: if (ctxt->vctxt != NULL)
21397: xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21398: }
21399:
21400: /**
21401: * xmlSchemaSetParserStructuredErrors:
21402: * @ctxt: a schema parser context
21403: * @serror: the structured error function
21404: * @ctx: the functions context
21405: *
21406: * Set the structured error callback
21407: */
21408: void
21409: xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21410: xmlStructuredErrorFunc serror,
21411: void *ctx)
21412: {
21413: if (ctxt == NULL)
21414: return;
21415: ctxt->serror = serror;
21416: ctxt->errCtxt = ctx;
21417: if (ctxt->vctxt != NULL)
21418: xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21419: }
21420:
21421: /**
21422: * xmlSchemaGetParserErrors:
21423: * @ctxt: a XMl-Schema parser context
21424: * @err: the error callback result
21425: * @warn: the warning callback result
21426: * @ctx: contextual data for the callbacks result
21427: *
21428: * Get the callback information used to handle errors for a parser context
21429: *
21430: * Returns -1 in case of failure, 0 otherwise
21431: */
21432: int
21433: xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21434: xmlSchemaValidityErrorFunc * err,
21435: xmlSchemaValidityWarningFunc * warn, void **ctx)
21436: {
21437: if (ctxt == NULL)
21438: return(-1);
21439: if (err != NULL)
21440: *err = ctxt->error;
21441: if (warn != NULL)
21442: *warn = ctxt->warning;
21443: if (ctx != NULL)
21444: *ctx = ctxt->errCtxt;
21445: return(0);
21446: }
21447:
21448: /**
21449: * xmlSchemaFacetTypeToString:
21450: * @type: the facet type
21451: *
21452: * Convert the xmlSchemaTypeType to a char string.
21453: *
21454: * Returns the char string representation of the facet type if the
21455: * type is a facet and an "Internal Error" string otherwise.
21456: */
21457: static const xmlChar *
21458: xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21459: {
21460: switch (type) {
21461: case XML_SCHEMA_FACET_PATTERN:
21462: return (BAD_CAST "pattern");
21463: case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21464: return (BAD_CAST "maxExclusive");
21465: case XML_SCHEMA_FACET_MAXINCLUSIVE:
21466: return (BAD_CAST "maxInclusive");
21467: case XML_SCHEMA_FACET_MINEXCLUSIVE:
21468: return (BAD_CAST "minExclusive");
21469: case XML_SCHEMA_FACET_MININCLUSIVE:
21470: return (BAD_CAST "minInclusive");
21471: case XML_SCHEMA_FACET_WHITESPACE:
21472: return (BAD_CAST "whiteSpace");
21473: case XML_SCHEMA_FACET_ENUMERATION:
21474: return (BAD_CAST "enumeration");
21475: case XML_SCHEMA_FACET_LENGTH:
21476: return (BAD_CAST "length");
21477: case XML_SCHEMA_FACET_MAXLENGTH:
21478: return (BAD_CAST "maxLength");
21479: case XML_SCHEMA_FACET_MINLENGTH:
21480: return (BAD_CAST "minLength");
21481: case XML_SCHEMA_FACET_TOTALDIGITS:
21482: return (BAD_CAST "totalDigits");
21483: case XML_SCHEMA_FACET_FRACTIONDIGITS:
21484: return (BAD_CAST "fractionDigits");
21485: default:
21486: break;
21487: }
21488: return (BAD_CAST "Internal Error");
21489: }
21490:
21491: static xmlSchemaWhitespaceValueType
21492: xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21493: {
21494: /*
21495: * The normalization type can be changed only for types which are derived
21496: * from xsd:string.
21497: */
21498: if (type->type == XML_SCHEMA_TYPE_BASIC) {
21499: /*
21500: * Note that we assume a whitespace of preserve for anySimpleType.
21501: */
21502: if ((type->builtInType == XML_SCHEMAS_STRING) ||
21503: (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21504: return(XML_SCHEMA_WHITESPACE_PRESERVE);
21505: else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21506: return(XML_SCHEMA_WHITESPACE_REPLACE);
21507: else {
21508: /*
21509: * For all �atomic� datatypes other than string (and types �derived�
21510: * by �restriction� from it) the value of whiteSpace is fixed to
21511: * collapse
21512: * Note that this includes built-in list datatypes.
21513: */
21514: return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21515: }
21516: } else if (WXS_IS_LIST(type)) {
21517: /*
21518: * For list types the facet "whiteSpace" is fixed to "collapse".
21519: */
21520: return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21521: } else if (WXS_IS_UNION(type)) {
21522: return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21523: } else if (WXS_IS_ATOMIC(type)) {
21524: if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21525: return (XML_SCHEMA_WHITESPACE_PRESERVE);
21526: else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21527: return (XML_SCHEMA_WHITESPACE_REPLACE);
21528: else
21529: return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21530: }
21531: return (-1);
21532: }
21533:
21534: /************************************************************************
21535: * *
21536: * Simple type validation *
21537: * *
21538: ************************************************************************/
21539:
21540:
21541: /************************************************************************
21542: * *
21543: * DOM Validation code *
21544: * *
21545: ************************************************************************/
21546:
21547: /**
21548: * xmlSchemaAssembleByLocation:
21549: * @pctxt: a schema parser context
21550: * @vctxt: a schema validation context
21551: * @schema: the existing schema
21552: * @node: the node that fired the assembling
21553: * @nsName: the namespace name of the new schema
21554: * @location: the location of the schema
21555: *
21556: * Expands an existing schema by an additional schema.
21557: *
21558: * Returns 0 if the new schema is correct, a positive error code
21559: * number otherwise and -1 in case of an internal or API error.
21560: */
21561: static int
21562: xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21563: xmlSchemaPtr schema,
21564: xmlNodePtr node,
21565: const xmlChar *nsName,
21566: const xmlChar *location)
21567: {
21568: int ret = 0;
21569: xmlSchemaParserCtxtPtr pctxt;
21570: xmlSchemaBucketPtr bucket = NULL;
21571:
21572: if ((vctxt == NULL) || (schema == NULL))
21573: return (-1);
21574:
21575: if (vctxt->pctxt == NULL) {
21576: VERROR_INT("xmlSchemaAssembleByLocation",
21577: "no parser context available");
21578: return(-1);
21579: }
21580: pctxt = vctxt->pctxt;
21581: if (pctxt->constructor == NULL) {
21582: PERROR_INT("xmlSchemaAssembleByLocation",
21583: "no constructor");
21584: return(-1);
21585: }
21586: /*
21587: * Acquire the schema document.
21588: */
21589: location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21590: location, node);
21591: /*
21592: * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21593: * the process will automatically change this to
21594: * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21595: */
21596: ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21597: location, NULL, NULL, 0, node, NULL, nsName,
21598: &bucket);
21599: if (ret != 0)
21600: return(ret);
21601: if (bucket == NULL) {
21602: /*
21603: * Generate a warning that the document could not be located.
21604: */
21605: xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21606: node, NULL,
21607: "The document at location '%s' could not be acquired",
21608: location, NULL, NULL);
21609: return(ret);
21610: }
21611: /*
21612: * The first located schema will be handled as if all other
21613: * schemas imported by XSI were imported by this first schema.
21614: */
21615: if ((bucket != NULL) &&
21616: (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21617: WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21618: /*
21619: * TODO: Is this handled like an import? I.e. is it not an error
21620: * if the schema cannot be located?
21621: */
21622: if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21623: return(0);
21624: /*
21625: * We will reuse the parser context for every schema imported
21626: * directly via XSI. So reset the context.
21627: */
21628: pctxt->nberrors = 0;
21629: pctxt->err = 0;
21630: pctxt->doc = bucket->doc;
21631:
21632: ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21633: if (ret == -1) {
21634: pctxt->doc = NULL;
21635: goto exit_failure;
21636: }
21637: /* Paranoid error channelling. */
21638: if ((ret == 0) && (pctxt->nberrors != 0))
21639: ret = pctxt->err;
21640: if (pctxt->nberrors == 0) {
21641: /*
21642: * Only bother to fixup pending components, if there was
21643: * no error yet.
21644: * For every XSI acquired schema (and its sub-schemata) we will
21645: * fixup the components.
21646: */
21647: xmlSchemaFixupComponents(pctxt, bucket);
21648: ret = pctxt->err;
21649: /*
21650: * Not nice, but we need somehow to channel the schema parser
21651: * error to the validation context.
21652: */
21653: if ((ret != 0) && (vctxt->err == 0))
21654: vctxt->err = ret;
21655: vctxt->nberrors += pctxt->nberrors;
21656: } else {
21657: /* Add to validation error sum. */
21658: vctxt->nberrors += pctxt->nberrors;
21659: }
21660: pctxt->doc = NULL;
21661: return(ret);
21662: exit_failure:
21663: pctxt->doc = NULL;
21664: return (-1);
21665: }
21666:
21667: static xmlSchemaAttrInfoPtr
21668: xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21669: int metaType)
21670: {
21671: if (vctxt->nbAttrInfos == 0)
21672: return (NULL);
21673: {
21674: int i;
21675: xmlSchemaAttrInfoPtr iattr;
21676:
21677: for (i = 0; i < vctxt->nbAttrInfos; i++) {
21678: iattr = vctxt->attrInfos[i];
21679: if (iattr->metaType == metaType)
21680: return (iattr);
21681: }
21682:
21683: }
21684: return (NULL);
21685: }
21686:
21687: /**
21688: * xmlSchemaAssembleByXSI:
21689: * @vctxt: a schema validation context
21690: *
21691: * Expands an existing schema by an additional schema using
21692: * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21693: * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21694: * must be set to 1.
21695: *
21696: * Returns 0 if the new schema is correct, a positive error code
21697: * number otherwise and -1 in case of an internal or API error.
21698: */
21699: static int
21700: xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21701: {
21702: const xmlChar *cur, *end;
21703: const xmlChar *nsname = NULL, *location;
21704: int count = 0;
21705: int ret = 0;
21706: xmlSchemaAttrInfoPtr iattr;
21707:
21708: /*
21709: * Parse the value; we will assume an even number of values
21710: * to be given (this is how Xerces and XSV work).
21711: *
21712: * URGENT TODO: !! This needs to work for both
21713: * @noNamespaceSchemaLocation AND @schemaLocation on the same
21714: * element !!
21715: */
21716: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21717: XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21718: if (iattr == NULL)
21719: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21720: XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21721: if (iattr == NULL)
21722: return (0);
21723: cur = iattr->value;
21724: do {
21725: /*
21726: * TODO: Move the string parsing mechanism away from here.
21727: */
21728: if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21729: /*
21730: * Get the namespace name.
21731: */
21732: while (IS_BLANK_CH(*cur))
21733: cur++;
21734: end = cur;
21735: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21736: end++;
21737: if (end == cur)
21738: break;
21739: count++; /* TODO: Don't use the schema's dict. */
21740: nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21741: cur = end;
21742: }
21743: /*
21744: * Get the URI.
21745: */
21746: while (IS_BLANK_CH(*cur))
21747: cur++;
21748: end = cur;
21749: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21750: end++;
21751: if (end == cur) {
21752: if (iattr->metaType ==
21753: XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21754: {
21755: /*
21756: * If using @schemaLocation then tuples are expected.
21757: * I.e. the namespace name *and* the document's URI.
21758: */
21759: xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21760: iattr->node, NULL,
21761: "The value must consist of tuples: the target namespace "
21762: "name and the document's URI", NULL, NULL, NULL);
21763: }
21764: break;
21765: }
21766: count++; /* TODO: Don't use the schema's dict. */
21767: location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21768: cur = end;
21769: ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21770: iattr->node, nsname, location);
21771: if (ret == -1) {
21772: VERROR_INT("xmlSchemaAssembleByXSI",
21773: "assembling schemata");
21774: return (-1);
21775: }
21776: } while (*cur != 0);
21777: return (ret);
21778: }
21779:
21780: static const xmlChar *
21781: xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21782: const xmlChar *prefix)
21783: {
21784: if (vctxt->sax != NULL) {
21785: int i, j;
21786: xmlSchemaNodeInfoPtr inode;
21787:
21788: for (i = vctxt->depth; i >= 0; i--) {
21789: if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21790: inode = vctxt->elemInfos[i];
21791: for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21792: if (((prefix == NULL) &&
21793: (inode->nsBindings[j] == NULL)) ||
21794: ((prefix != NULL) && xmlStrEqual(prefix,
21795: inode->nsBindings[j]))) {
21796:
21797: /*
21798: * Note that the namespace bindings are already
21799: * in a string dict.
21800: */
21801: return (inode->nsBindings[j+1]);
21802: }
21803: }
21804: }
21805: }
21806: return (NULL);
21807: #ifdef LIBXML_READER_ENABLED
21808: } else if (vctxt->reader != NULL) {
21809: xmlChar *nsName;
21810:
21811: nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21812: if (nsName != NULL) {
21813: const xmlChar *ret;
21814:
21815: ret = xmlDictLookup(vctxt->dict, nsName, -1);
21816: xmlFree(nsName);
21817: return (ret);
21818: } else
21819: return (NULL);
21820: #endif
21821: } else {
21822: xmlNsPtr ns;
21823:
21824: if ((vctxt->inode->node == NULL) ||
21825: (vctxt->inode->node->doc == NULL)) {
21826: VERROR_INT("xmlSchemaLookupNamespace",
21827: "no node or node's doc avaliable");
21828: return (NULL);
21829: }
21830: ns = xmlSearchNs(vctxt->inode->node->doc,
21831: vctxt->inode->node, prefix);
21832: if (ns != NULL)
21833: return (ns->href);
21834: return (NULL);
21835: }
21836: }
21837:
21838: /*
21839: * This one works on the schema of the validation context.
21840: */
21841: static int
21842: xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21843: xmlSchemaPtr schema,
21844: xmlNodePtr node,
21845: const xmlChar *value,
21846: xmlSchemaValPtr *val,
21847: int valNeeded)
21848: {
21849: int ret;
21850:
21851: if (vctxt && (vctxt->schema == NULL)) {
21852: VERROR_INT("xmlSchemaValidateNotation",
21853: "a schema is needed on the validation context");
21854: return (-1);
21855: }
21856: ret = xmlValidateQName(value, 1);
21857: if (ret != 0)
21858: return (ret);
21859: {
21860: xmlChar *localName = NULL;
21861: xmlChar *prefix = NULL;
21862:
21863: localName = xmlSplitQName2(value, &prefix);
21864: if (prefix != NULL) {
21865: const xmlChar *nsName = NULL;
21866:
21867: if (vctxt != NULL)
21868: nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21869: else if (node != NULL) {
21870: xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21871: if (ns != NULL)
21872: nsName = ns->href;
21873: } else {
21874: xmlFree(prefix);
21875: xmlFree(localName);
21876: return (1);
21877: }
21878: if (nsName == NULL) {
21879: xmlFree(prefix);
21880: xmlFree(localName);
21881: return (1);
21882: }
21883: if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21884: if ((valNeeded) && (val != NULL)) {
21885: (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21886: xmlStrdup(nsName));
21887: if (*val == NULL)
21888: ret = -1;
21889: }
21890: } else
21891: ret = 1;
21892: xmlFree(prefix);
21893: xmlFree(localName);
21894: } else {
21895: if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21896: if (valNeeded && (val != NULL)) {
21897: (*val) = xmlSchemaNewNOTATIONValue(
21898: BAD_CAST xmlStrdup(value), NULL);
21899: if (*val == NULL)
21900: ret = -1;
21901: }
21902: } else
21903: return (1);
21904: }
21905: }
21906: return (ret);
21907: }
21908:
21909: static int
21910: xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21911: const xmlChar* lname,
21912: const xmlChar* nsname)
21913: {
21914: int i;
21915:
21916: lname = xmlDictLookup(vctxt->dict, lname, -1);
21917: if (lname == NULL)
21918: return(-1);
21919: if (nsname != NULL) {
21920: nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21921: if (nsname == NULL)
21922: return(-1);
21923: }
21924: for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21925: if ((vctxt->nodeQNames->items [i] == lname) &&
21926: (vctxt->nodeQNames->items[i +1] == nsname))
21927: /* Already there */
21928: return(i);
21929: }
21930: /* Add new entry. */
21931: i = vctxt->nodeQNames->nbItems;
21932: xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21933: xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21934: return(i);
21935: }
21936:
21937: /************************************************************************
21938: * *
21939: * Validation of identity-constraints (IDC) *
21940: * *
21941: ************************************************************************/
21942:
21943: /**
21944: * xmlSchemaAugmentIDC:
21945: * @idcDef: the IDC definition
21946: *
21947: * Creates an augmented IDC definition item.
21948: *
21949: * Returns the item, or NULL on internal errors.
21950: */
21951: static void
21952: xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21953: xmlSchemaValidCtxtPtr vctxt)
21954: {
21955: xmlSchemaIDCAugPtr aidc;
21956:
21957: aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21958: if (aidc == NULL) {
21959: xmlSchemaVErrMemory(vctxt,
21960: "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21961: NULL);
21962: return;
21963: }
21964: aidc->keyrefDepth = -1;
21965: aidc->def = idcDef;
21966: aidc->next = NULL;
21967: if (vctxt->aidcs == NULL)
21968: vctxt->aidcs = aidc;
21969: else {
21970: aidc->next = vctxt->aidcs;
21971: vctxt->aidcs = aidc;
21972: }
21973: /*
21974: * Save if we have keyrefs at all.
21975: */
21976: if ((vctxt->hasKeyrefs == 0) &&
21977: (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21978: vctxt->hasKeyrefs = 1;
21979: }
21980:
21981: /**
21982: * xmlSchemaAugmentImportedIDC:
21983: * @imported: the imported schema
21984: *
21985: * Creates an augmented IDC definition for the imported schema.
21986: */
21987: static void
21988: xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
21989: if (imported->schema->idcDef != NULL) {
21990: xmlHashScan(imported->schema->idcDef ,
21991: (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
21992: }
21993: }
21994:
21995: /**
21996: * xmlSchemaIDCNewBinding:
21997: * @idcDef: the IDC definition of this binding
21998: *
21999: * Creates a new IDC binding.
22000: *
22001: * Returns the new IDC binding, NULL on internal errors.
22002: */
22003: static xmlSchemaPSVIIDCBindingPtr
22004: xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22005: {
22006: xmlSchemaPSVIIDCBindingPtr ret;
22007:
22008: ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22009: sizeof(xmlSchemaPSVIIDCBinding));
22010: if (ret == NULL) {
22011: xmlSchemaVErrMemory(NULL,
22012: "allocating a PSVI IDC binding item", NULL);
22013: return (NULL);
22014: }
22015: memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22016: ret->definition = idcDef;
22017: return (ret);
22018: }
22019:
22020: /**
22021: * xmlSchemaIDCStoreNodeTableItem:
22022: * @vctxt: the WXS validation context
22023: * @item: the IDC node table item
22024: *
22025: * The validation context is used to store IDC node table items.
22026: * They are stored to avoid copying them if IDC node-tables are merged
22027: * with corresponding parent IDC node-tables (bubbling).
22028: *
22029: * Returns 0 if succeeded, -1 on internal errors.
22030: */
22031: static int
22032: xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22033: xmlSchemaPSVIIDCNodePtr item)
22034: {
22035: /*
22036: * Add to gobal list.
22037: */
22038: if (vctxt->idcNodes == NULL) {
22039: vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22040: xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22041: if (vctxt->idcNodes == NULL) {
22042: xmlSchemaVErrMemory(vctxt,
22043: "allocating the IDC node table item list", NULL);
22044: return (-1);
22045: }
22046: vctxt->sizeIdcNodes = 20;
22047: } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22048: vctxt->sizeIdcNodes *= 2;
22049: vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22050: xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22051: sizeof(xmlSchemaPSVIIDCNodePtr));
22052: if (vctxt->idcNodes == NULL) {
22053: xmlSchemaVErrMemory(vctxt,
22054: "re-allocating the IDC node table item list", NULL);
22055: return (-1);
22056: }
22057: }
22058: vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22059:
22060: return (0);
22061: }
22062:
22063: /**
22064: * xmlSchemaIDCStoreKey:
22065: * @vctxt: the WXS validation context
22066: * @item: the IDC key
22067: *
22068: * The validation context is used to store an IDC key.
22069: *
22070: * Returns 0 if succeeded, -1 on internal errors.
22071: */
22072: static int
22073: xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22074: xmlSchemaPSVIIDCKeyPtr key)
22075: {
22076: /*
22077: * Add to gobal list.
22078: */
22079: if (vctxt->idcKeys == NULL) {
22080: vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22081: xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22082: if (vctxt->idcKeys == NULL) {
22083: xmlSchemaVErrMemory(vctxt,
22084: "allocating the IDC key storage list", NULL);
22085: return (-1);
22086: }
22087: vctxt->sizeIdcKeys = 40;
22088: } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22089: vctxt->sizeIdcKeys *= 2;
22090: vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22091: xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22092: sizeof(xmlSchemaPSVIIDCKeyPtr));
22093: if (vctxt->idcKeys == NULL) {
22094: xmlSchemaVErrMemory(vctxt,
22095: "re-allocating the IDC key storage list", NULL);
22096: return (-1);
22097: }
22098: }
22099: vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22100:
22101: return (0);
22102: }
22103:
22104: /**
22105: * xmlSchemaIDCAppendNodeTableItem:
22106: * @bind: the IDC binding
22107: * @ntItem: the node-table item
22108: *
22109: * Appends the IDC node-table item to the binding.
22110: *
22111: * Returns 0 on success and -1 on internal errors.
22112: */
22113: static int
22114: xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22115: xmlSchemaPSVIIDCNodePtr ntItem)
22116: {
22117: if (bind->nodeTable == NULL) {
22118: bind->sizeNodes = 10;
22119: bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22120: xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22121: if (bind->nodeTable == NULL) {
22122: xmlSchemaVErrMemory(NULL,
22123: "allocating an array of IDC node-table items", NULL);
22124: return(-1);
22125: }
22126: } else if (bind->sizeNodes <= bind->nbNodes) {
22127: bind->sizeNodes *= 2;
22128: bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22129: xmlRealloc(bind->nodeTable, bind->sizeNodes *
22130: sizeof(xmlSchemaPSVIIDCNodePtr));
22131: if (bind->nodeTable == NULL) {
22132: xmlSchemaVErrMemory(NULL,
22133: "re-allocating an array of IDC node-table items", NULL);
22134: return(-1);
22135: }
22136: }
22137: bind->nodeTable[bind->nbNodes++] = ntItem;
22138: return(0);
22139: }
22140:
22141: /**
22142: * xmlSchemaIDCAcquireBinding:
22143: * @vctxt: the WXS validation context
22144: * @matcher: the IDC matcher
22145: *
22146: * Looks up an PSVI IDC binding, for the IDC definition and
22147: * of the given matcher. If none found, a new one is created
22148: * and added to the IDC table.
22149: *
22150: * Returns an IDC binding or NULL on internal errors.
22151: */
22152: static xmlSchemaPSVIIDCBindingPtr
22153: xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22154: xmlSchemaIDCMatcherPtr matcher)
22155: {
22156: xmlSchemaNodeInfoPtr ielem;
22157:
22158: ielem = vctxt->elemInfos[matcher->depth];
22159:
22160: if (ielem->idcTable == NULL) {
22161: ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22162: if (ielem->idcTable == NULL)
22163: return (NULL);
22164: return(ielem->idcTable);
22165: } else {
22166: xmlSchemaPSVIIDCBindingPtr bind = NULL;
22167:
22168: bind = ielem->idcTable;
22169: do {
22170: if (bind->definition == matcher->aidc->def)
22171: return(bind);
22172: if (bind->next == NULL) {
22173: bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22174: if (bind->next == NULL)
22175: return (NULL);
22176: return(bind->next);
22177: }
22178: bind = bind->next;
22179: } while (bind != NULL);
22180: }
22181: return (NULL);
22182: }
22183:
22184: static xmlSchemaItemListPtr
22185: xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22186: xmlSchemaIDCMatcherPtr matcher)
22187: {
22188: if (matcher->targets == NULL)
22189: matcher->targets = xmlSchemaItemListCreate();
22190: return(matcher->targets);
22191: }
22192:
22193: /**
22194: * xmlSchemaIDCFreeKey:
22195: * @key: the IDC key
22196: *
22197: * Frees an IDC key together with its compiled value.
22198: */
22199: static void
22200: xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22201: {
22202: if (key->val != NULL)
22203: xmlSchemaFreeValue(key->val);
22204: xmlFree(key);
22205: }
22206:
22207: /**
22208: * xmlSchemaIDCFreeBinding:
22209: *
22210: * Frees an IDC binding. Note that the node table-items
22211: * are not freed.
22212: */
22213: static void
22214: xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22215: {
22216: if (bind->nodeTable != NULL)
22217: xmlFree(bind->nodeTable);
22218: if (bind->dupls != NULL)
22219: xmlSchemaItemListFree(bind->dupls);
22220: xmlFree(bind);
22221: }
22222:
22223: /**
22224: * xmlSchemaIDCFreeIDCTable:
22225: * @bind: the first IDC binding in the list
22226: *
22227: * Frees an IDC table, i.e. all the IDC bindings in the list.
22228: */
22229: static void
22230: xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22231: {
22232: xmlSchemaPSVIIDCBindingPtr prev;
22233:
22234: while (bind != NULL) {
22235: prev = bind;
22236: bind = bind->next;
22237: xmlSchemaIDCFreeBinding(prev);
22238: }
22239: }
22240:
22241: /**
22242: * xmlSchemaIDCFreeMatcherList:
22243: * @matcher: the first IDC matcher in the list
22244: *
22245: * Frees a list of IDC matchers.
22246: */
22247: static void
22248: xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22249: {
22250: xmlSchemaIDCMatcherPtr next;
22251:
22252: while (matcher != NULL) {
22253: next = matcher->next;
22254: if (matcher->keySeqs != NULL) {
22255: int i;
22256: for (i = 0; i < matcher->sizeKeySeqs; i++)
22257: if (matcher->keySeqs[i] != NULL)
22258: xmlFree(matcher->keySeqs[i]);
22259: xmlFree(matcher->keySeqs);
22260: }
22261: if (matcher->targets != NULL) {
22262: if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22263: int i;
22264: xmlSchemaPSVIIDCNodePtr idcNode;
22265: /*
22266: * Node-table items for keyrefs are not stored globally
22267: * to the validation context, since they are not bubbled.
22268: * We need to free them here.
22269: */
22270: for (i = 0; i < matcher->targets->nbItems; i++) {
22271: idcNode =
22272: (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22273: xmlFree(idcNode->keys);
22274: xmlFree(idcNode);
22275: }
22276: }
22277: xmlSchemaItemListFree(matcher->targets);
22278: }
22279: xmlFree(matcher);
22280: matcher = next;
22281: }
22282: }
22283:
22284: /**
22285: * xmlSchemaIDCReleaseMatcherList:
22286: * @vctxt: the WXS validation context
22287: * @matcher: the first IDC matcher in the list
22288: *
22289: * Caches a list of IDC matchers for reuse.
22290: */
22291: static void
22292: xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22293: xmlSchemaIDCMatcherPtr matcher)
22294: {
22295: xmlSchemaIDCMatcherPtr next;
22296:
22297: while (matcher != NULL) {
22298: next = matcher->next;
22299: if (matcher->keySeqs != NULL) {
22300: int i;
22301: /*
22302: * Don't free the array, but only the content.
22303: */
22304: for (i = 0; i < matcher->sizeKeySeqs; i++)
22305: if (matcher->keySeqs[i] != NULL) {
22306: xmlFree(matcher->keySeqs[i]);
22307: matcher->keySeqs[i] = NULL;
22308: }
22309: }
22310: if (matcher->targets) {
22311: if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22312: int i;
22313: xmlSchemaPSVIIDCNodePtr idcNode;
22314: /*
22315: * Node-table items for keyrefs are not stored globally
22316: * to the validation context, since they are not bubbled.
22317: * We need to free them here.
22318: */
22319: for (i = 0; i < matcher->targets->nbItems; i++) {
22320: idcNode =
22321: (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22322: xmlFree(idcNode->keys);
22323: xmlFree(idcNode);
22324: }
22325: }
22326: xmlSchemaItemListFree(matcher->targets);
22327: matcher->targets = NULL;
22328: }
22329: matcher->next = NULL;
22330: /*
22331: * Cache the matcher.
22332: */
22333: if (vctxt->idcMatcherCache != NULL)
22334: matcher->nextCached = vctxt->idcMatcherCache;
22335: vctxt->idcMatcherCache = matcher;
22336:
22337: matcher = next;
22338: }
22339: }
22340:
22341: /**
22342: * xmlSchemaIDCAddStateObject:
22343: * @vctxt: the WXS validation context
22344: * @matcher: the IDC matcher
22345: * @sel: the XPath information
22346: * @parent: the parent "selector" state object if any
22347: * @type: "selector" or "field"
22348: *
22349: * Creates/reuses and activates state objects for the given
22350: * XPath information; if the XPath expression consists of unions,
22351: * multiple state objects are created for every unioned expression.
22352: *
22353: * Returns 0 on success and -1 on internal errors.
22354: */
22355: static int
22356: xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22357: xmlSchemaIDCMatcherPtr matcher,
22358: xmlSchemaIDCSelectPtr sel,
22359: int type)
22360: {
22361: xmlSchemaIDCStateObjPtr sto;
22362:
22363: /*
22364: * Reuse the state objects from the pool.
22365: */
22366: if (vctxt->xpathStatePool != NULL) {
22367: sto = vctxt->xpathStatePool;
22368: vctxt->xpathStatePool = sto->next;
22369: sto->next = NULL;
22370: } else {
22371: /*
22372: * Create a new state object.
22373: */
22374: sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22375: if (sto == NULL) {
22376: xmlSchemaVErrMemory(NULL,
22377: "allocating an IDC state object", NULL);
22378: return (-1);
22379: }
22380: memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22381: }
22382: /*
22383: * Add to global list.
22384: */
22385: if (vctxt->xpathStates != NULL)
22386: sto->next = vctxt->xpathStates;
22387: vctxt->xpathStates = sto;
22388:
22389: /*
22390: * Free the old xpath validation context.
22391: */
22392: if (sto->xpathCtxt != NULL)
22393: xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22394:
22395: /*
22396: * Create a new XPath (pattern) validation context.
22397: */
22398: sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22399: (xmlPatternPtr) sel->xpathComp);
22400: if (sto->xpathCtxt == NULL) {
22401: VERROR_INT("xmlSchemaIDCAddStateObject",
22402: "failed to create an XPath validation context");
22403: return (-1);
22404: }
22405: sto->type = type;
22406: sto->depth = vctxt->depth;
22407: sto->matcher = matcher;
22408: sto->sel = sel;
22409: sto->nbHistory = 0;
22410:
22411: #ifdef DEBUG_IDC
22412: xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22413: sto->sel->xpath);
22414: #endif
22415: return (0);
22416: }
22417:
22418: /**
22419: * xmlSchemaXPathEvaluate:
22420: * @vctxt: the WXS validation context
22421: * @nodeType: the nodeType of the current node
22422: *
22423: * Evaluates all active XPath state objects.
22424: *
22425: * Returns the number of IC "field" state objects which resolved to
22426: * this node, 0 if none resolved and -1 on internal errors.
22427: */
22428: static int
22429: xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22430: xmlElementType nodeType)
22431: {
22432: xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22433: int res, resolved = 0, depth = vctxt->depth;
22434:
22435: if (vctxt->xpathStates == NULL)
22436: return (0);
22437:
22438: if (nodeType == XML_ATTRIBUTE_NODE)
22439: depth++;
22440: #ifdef DEBUG_IDC
22441: {
22442: xmlChar *str = NULL;
22443: xmlGenericError(xmlGenericErrorContext,
22444: "IDC: EVAL on %s, depth %d, type %d\n",
22445: xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22446: vctxt->inode->localName), depth, nodeType);
22447: FREE_AND_NULL(str)
22448: }
22449: #endif
22450: /*
22451: * Process all active XPath state objects.
22452: */
22453: first = vctxt->xpathStates;
22454: sto = first;
22455: while (sto != head) {
22456: #ifdef DEBUG_IDC
22457: if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22458: xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22459: sto->matcher->aidc->def->name, sto->sel->xpath);
22460: else
22461: xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22462: sto->matcher->aidc->def->name, sto->sel->xpath);
22463: #endif
22464: if (nodeType == XML_ELEMENT_NODE)
22465: res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22466: vctxt->inode->localName, vctxt->inode->nsName);
22467: else
22468: res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22469: vctxt->inode->localName, vctxt->inode->nsName);
22470:
22471: if (res == -1) {
22472: VERROR_INT("xmlSchemaXPathEvaluate",
22473: "calling xmlStreamPush()");
22474: return (-1);
22475: }
22476: if (res == 0)
22477: goto next_sto;
22478: /*
22479: * Full match.
22480: */
22481: #ifdef DEBUG_IDC
22482: xmlGenericError(xmlGenericErrorContext, "IDC: "
22483: "MATCH\n");
22484: #endif
22485: /*
22486: * Register a match in the state object history.
22487: */
22488: if (sto->history == NULL) {
22489: sto->history = (int *) xmlMalloc(5 * sizeof(int));
22490: if (sto->history == NULL) {
22491: xmlSchemaVErrMemory(NULL,
22492: "allocating the state object history", NULL);
22493: return(-1);
22494: }
22495: sto->sizeHistory = 5;
22496: } else if (sto->sizeHistory <= sto->nbHistory) {
22497: sto->sizeHistory *= 2;
22498: sto->history = (int *) xmlRealloc(sto->history,
22499: sto->sizeHistory * sizeof(int));
22500: if (sto->history == NULL) {
22501: xmlSchemaVErrMemory(NULL,
22502: "re-allocating the state object history", NULL);
22503: return(-1);
22504: }
22505: }
22506: sto->history[sto->nbHistory++] = depth;
22507:
22508: #ifdef DEBUG_IDC
22509: xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22510: vctxt->depth);
22511: #endif
22512:
22513: if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22514: xmlSchemaIDCSelectPtr sel;
22515: /*
22516: * Activate state objects for the IDC fields of
22517: * the IDC selector.
22518: */
22519: #ifdef DEBUG_IDC
22520: xmlGenericError(xmlGenericErrorContext, "IDC: "
22521: "activating field states\n");
22522: #endif
22523: sel = sto->matcher->aidc->def->fields;
22524: while (sel != NULL) {
22525: if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22526: sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22527: return (-1);
22528: sel = sel->next;
22529: }
22530: } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22531: /*
22532: * An IDC key node was found by the IDC field.
22533: */
22534: #ifdef DEBUG_IDC
22535: xmlGenericError(xmlGenericErrorContext,
22536: "IDC: key found\n");
22537: #endif
22538: /*
22539: * Notify that the character value of this node is
22540: * needed.
22541: */
22542: if (resolved == 0) {
22543: if ((vctxt->inode->flags &
22544: XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22545: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22546: }
22547: resolved++;
22548: }
22549: next_sto:
22550: if (sto->next == NULL) {
22551: /*
22552: * Evaluate field state objects created on this node as well.
22553: */
22554: head = first;
22555: sto = vctxt->xpathStates;
22556: } else
22557: sto = sto->next;
22558: }
22559: return (resolved);
22560: }
22561:
22562: static const xmlChar *
22563: xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22564: xmlChar **buf,
22565: xmlSchemaPSVIIDCKeyPtr *seq,
22566: int count)
22567: {
22568: int i, res;
22569: xmlChar *value = NULL;
22570:
22571: *buf = xmlStrdup(BAD_CAST "[");
22572: for (i = 0; i < count; i++) {
22573: *buf = xmlStrcat(*buf, BAD_CAST "'");
22574: res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22575: xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22576: &value);
22577: if (res == 0)
22578: *buf = xmlStrcat(*buf, BAD_CAST value);
22579: else {
22580: VERROR_INT("xmlSchemaFormatIDCKeySequence",
22581: "failed to compute a canonical value");
22582: *buf = xmlStrcat(*buf, BAD_CAST "???");
22583: }
22584: if (i < count -1)
22585: *buf = xmlStrcat(*buf, BAD_CAST "', ");
22586: else
22587: *buf = xmlStrcat(*buf, BAD_CAST "'");
22588: if (value != NULL) {
22589: xmlFree(value);
22590: value = NULL;
22591: }
22592: }
22593: *buf = xmlStrcat(*buf, BAD_CAST "]");
22594:
22595: return (BAD_CAST *buf);
22596: }
22597:
22598: /**
22599: * xmlSchemaXPathPop:
22600: * @vctxt: the WXS validation context
22601: *
22602: * Pops all XPath states.
22603: *
22604: * Returns 0 on success and -1 on internal errors.
22605: */
22606: static int
22607: xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22608: {
22609: xmlSchemaIDCStateObjPtr sto;
22610: int res;
22611:
22612: if (vctxt->xpathStates == NULL)
22613: return(0);
22614: sto = vctxt->xpathStates;
22615: do {
22616: res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22617: if (res == -1)
22618: return (-1);
22619: sto = sto->next;
22620: } while (sto != NULL);
22621: return(0);
22622: }
22623:
22624: /**
22625: * xmlSchemaXPathProcessHistory:
22626: * @vctxt: the WXS validation context
22627: * @type: the simple/complex type of the current node if any at all
22628: * @val: the precompiled value
22629: *
22630: * Processes and pops the history items of the IDC state objects.
22631: * IDC key-sequences are validated/created on IDC bindings.
22632: *
22633: * Returns 0 on success and -1 on internal errors.
22634: */
22635: static int
22636: xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22637: int depth)
22638: {
22639: xmlSchemaIDCStateObjPtr sto, nextsto;
22640: int res, matchDepth;
22641: xmlSchemaPSVIIDCKeyPtr key = NULL;
22642: xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22643:
22644: if (vctxt->xpathStates == NULL)
22645: return (0);
22646: sto = vctxt->xpathStates;
22647:
22648: #ifdef DEBUG_IDC
22649: {
22650: xmlChar *str = NULL;
22651: xmlGenericError(xmlGenericErrorContext,
22652: "IDC: BACK on %s, depth %d\n",
22653: xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22654: vctxt->inode->localName), vctxt->depth);
22655: FREE_AND_NULL(str)
22656: }
22657: #endif
22658: /*
22659: * Evaluate the state objects.
22660: */
22661: while (sto != NULL) {
22662: res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22663: if (res == -1) {
22664: VERROR_INT("xmlSchemaXPathProcessHistory",
22665: "calling xmlStreamPop()");
22666: return (-1);
22667: }
22668: #ifdef DEBUG_IDC
22669: xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22670: sto->sel->xpath);
22671: #endif
22672: if (sto->nbHistory == 0)
22673: goto deregister_check;
22674:
22675: matchDepth = sto->history[sto->nbHistory -1];
22676:
22677: /*
22678: * Only matches at the current depth are of interest.
22679: */
22680: if (matchDepth != depth) {
22681: sto = sto->next;
22682: continue;
22683: }
22684: if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22685: /*
22686: * NOTE: According to
22687: * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22688: * ... the simple-content of complex types is also allowed.
22689: */
22690:
22691: if (WXS_IS_COMPLEX(type)) {
22692: if (WXS_HAS_SIMPLE_CONTENT(type)) {
22693: /*
22694: * Sanity check for complex types with simple content.
22695: */
22696: simpleType = type->contentTypeDef;
22697: if (simpleType == NULL) {
22698: VERROR_INT("xmlSchemaXPathProcessHistory",
22699: "field resolves to a CT with simple content "
22700: "but the CT is missing the ST definition");
22701: return (-1);
22702: }
22703: } else
22704: simpleType = NULL;
22705: } else
22706: simpleType = type;
22707: if (simpleType == NULL) {
22708: xmlChar *str = NULL;
22709:
22710: /*
22711: * Not qualified if the field resolves to a node of non
22712: * simple type.
22713: */
22714: xmlSchemaCustomErr(ACTXT_CAST vctxt,
22715: XML_SCHEMAV_CVC_IDC, NULL,
22716: WXS_BASIC_CAST sto->matcher->aidc->def,
22717: "The XPath '%s' of a field of %s does evaluate to a node of "
22718: "non-simple type",
22719: sto->sel->xpath,
22720: xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22721: FREE_AND_NULL(str);
22722: sto->nbHistory--;
22723: goto deregister_check;
22724: }
22725:
22726: if ((key == NULL) && (vctxt->inode->val == NULL)) {
22727: /*
22728: * Failed to provide the normalized value; maybe
22729: * the value was invalid.
22730: */
22731: VERROR(XML_SCHEMAV_CVC_IDC,
22732: WXS_BASIC_CAST sto->matcher->aidc->def,
22733: "Warning: No precomputed value available, the value "
22734: "was either invalid or something strange happend");
22735: sto->nbHistory--;
22736: goto deregister_check;
22737: } else {
22738: xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22739: xmlSchemaPSVIIDCKeyPtr *keySeq;
22740: int pos, idx;
22741:
22742: /*
22743: * The key will be anchored on the matcher's list of
22744: * key-sequences. The position in this list is determined
22745: * by the target node's depth relative to the matcher's
22746: * depth of creation (i.e. the depth of the scope element).
22747: *
22748: * Element Depth Pos List-entries
22749: * <scope> 0 NULL
22750: * <bar> 1 NULL
22751: * <target/> 2 2 target
22752: * <bar>
22753: * </scope>
22754: *
22755: * The size of the list is only dependant on the depth of
22756: * the tree.
22757: * An entry will be NULLed in selector_leave, i.e. when
22758: * we hit the target's
22759: */
22760: pos = sto->depth - matcher->depth;
22761: idx = sto->sel->index;
22762:
22763: /*
22764: * Create/grow the array of key-sequences.
22765: */
22766: if (matcher->keySeqs == NULL) {
22767: if (pos > 9)
22768: matcher->sizeKeySeqs = pos * 2;
22769: else
22770: matcher->sizeKeySeqs = 10;
22771: matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22772: xmlMalloc(matcher->sizeKeySeqs *
22773: sizeof(xmlSchemaPSVIIDCKeyPtr *));
22774: if (matcher->keySeqs == NULL) {
22775: xmlSchemaVErrMemory(NULL,
22776: "allocating an array of key-sequences",
22777: NULL);
22778: return(-1);
22779: }
22780: memset(matcher->keySeqs, 0,
22781: matcher->sizeKeySeqs *
22782: sizeof(xmlSchemaPSVIIDCKeyPtr *));
22783: } else if (pos >= matcher->sizeKeySeqs) {
22784: int i = matcher->sizeKeySeqs;
22785:
22786: matcher->sizeKeySeqs *= 2;
22787: matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22788: xmlRealloc(matcher->keySeqs,
22789: matcher->sizeKeySeqs *
22790: sizeof(xmlSchemaPSVIIDCKeyPtr *));
22791: if (matcher->keySeqs == NULL) {
22792: xmlSchemaVErrMemory(NULL,
22793: "reallocating an array of key-sequences",
22794: NULL);
22795: return (-1);
22796: }
22797: /*
22798: * The array needs to be NULLed.
22799: * TODO: Use memset?
22800: */
22801: for (; i < matcher->sizeKeySeqs; i++)
22802: matcher->keySeqs[i] = NULL;
22803: }
22804:
22805: /*
22806: * Get/create the key-sequence.
22807: */
22808: keySeq = matcher->keySeqs[pos];
22809: if (keySeq == NULL) {
22810: goto create_sequence;
22811: } else if (keySeq[idx] != NULL) {
22812: xmlChar *str = NULL;
22813: /*
22814: * cvc-identity-constraint:
22815: * 3 For each node in the �target node set� all
22816: * of the {fields}, with that node as the context
22817: * node, evaluate to either an empty node-set or
22818: * a node-set with exactly one member, which must
22819: * have a simple type.
22820: *
22821: * The key was already set; report an error.
22822: */
22823: xmlSchemaCustomErr(ACTXT_CAST vctxt,
22824: XML_SCHEMAV_CVC_IDC, NULL,
22825: WXS_BASIC_CAST matcher->aidc->def,
22826: "The XPath '%s' of a field of %s evaluates to a "
22827: "node-set with more than one member",
22828: sto->sel->xpath,
22829: xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22830: FREE_AND_NULL(str);
22831: sto->nbHistory--;
22832: goto deregister_check;
22833: } else
22834: goto create_key;
22835:
22836: create_sequence:
22837: /*
22838: * Create a key-sequence.
22839: */
22840: keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22841: matcher->aidc->def->nbFields *
22842: sizeof(xmlSchemaPSVIIDCKeyPtr));
22843: if (keySeq == NULL) {
22844: xmlSchemaVErrMemory(NULL,
22845: "allocating an IDC key-sequence", NULL);
22846: return(-1);
22847: }
22848: memset(keySeq, 0, matcher->aidc->def->nbFields *
22849: sizeof(xmlSchemaPSVIIDCKeyPtr));
22850: matcher->keySeqs[pos] = keySeq;
22851: create_key:
22852: /*
22853: * Create a key once per node only.
22854: */
22855: if (key == NULL) {
22856: key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22857: sizeof(xmlSchemaPSVIIDCKey));
22858: if (key == NULL) {
22859: xmlSchemaVErrMemory(NULL,
22860: "allocating a IDC key", NULL);
22861: xmlFree(keySeq);
22862: matcher->keySeqs[pos] = NULL;
22863: return(-1);
22864: }
22865: /*
22866: * Consume the compiled value.
22867: */
22868: key->type = simpleType;
22869: key->val = vctxt->inode->val;
22870: vctxt->inode->val = NULL;
22871: /*
22872: * Store the key in a global list.
22873: */
22874: if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22875: xmlSchemaIDCFreeKey(key);
22876: return (-1);
22877: }
22878: }
22879: keySeq[idx] = key;
22880: }
22881: } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22882:
22883: xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22884: /* xmlSchemaPSVIIDCBindingPtr bind; */
22885: xmlSchemaPSVIIDCNodePtr ntItem;
22886: xmlSchemaIDCMatcherPtr matcher;
22887: xmlSchemaIDCPtr idc;
22888: xmlSchemaItemListPtr targets;
22889: int pos, i, j, nbKeys;
22890: /*
22891: * Here we have the following scenario:
22892: * An IDC 'selector' state object resolved to a target node,
22893: * during the time this target node was in the
22894: * ancestor-or-self axis, the 'field' state object(s) looked
22895: * out for matching nodes to create a key-sequence for this
22896: * target node. Now we are back to this target node and need
22897: * to put the key-sequence, together with the target node
22898: * itself, into the node-table of the corresponding IDC
22899: * binding.
22900: */
22901: matcher = sto->matcher;
22902: idc = matcher->aidc->def;
22903: nbKeys = idc->nbFields;
22904: pos = depth - matcher->depth;
22905: /*
22906: * Check if the matcher has any key-sequences at all, plus
22907: * if it has a key-sequence for the current target node.
22908: */
22909: if ((matcher->keySeqs == NULL) ||
22910: (matcher->sizeKeySeqs <= pos)) {
22911: if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22912: goto selector_key_error;
22913: else
22914: goto selector_leave;
22915: }
22916:
22917: keySeq = &(matcher->keySeqs[pos]);
22918: if (*keySeq == NULL) {
22919: if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22920: goto selector_key_error;
22921: else
22922: goto selector_leave;
22923: }
22924:
22925: for (i = 0; i < nbKeys; i++) {
22926: if ((*keySeq)[i] == NULL) {
22927: /*
22928: * Not qualified, if not all fields did resolve.
22929: */
22930: if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22931: /*
22932: * All fields of a "key" IDC must resolve.
22933: */
22934: goto selector_key_error;
22935: }
22936: goto selector_leave;
22937: }
22938: }
22939: /*
22940: * All fields did resolve.
22941: */
22942:
22943: /*
22944: * 4.1 If the {identity-constraint category} is unique(/key),
22945: * then no two members of the �qualified node set� have
22946: * �key-sequences� whose members are pairwise equal, as
22947: * defined by Equal in [XML Schemas: Datatypes].
22948: *
22949: * Get the IDC binding from the matcher and check for
22950: * duplicate key-sequences.
22951: */
22952: #if 0
22953: bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22954: #endif
22955: targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22956: if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22957: (targets->nbItems != 0)) {
22958: xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22959:
22960: i = 0;
22961: res = 0;
22962: /*
22963: * Compare the key-sequences, key by key.
22964: */
22965: do {
22966: bkeySeq =
22967: ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22968: for (j = 0; j < nbKeys; j++) {
22969: ckey = (*keySeq)[j];
22970: bkey = bkeySeq[j];
22971: res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22972: if (res == -1) {
22973: return (-1);
22974: } else if (res == 0) {
22975: /*
22976: * One of the keys differs, so the key-sequence
22977: * won't be equal; get out.
22978: */
22979: break;
22980: }
22981: }
22982: if (res == 1) {
22983: /*
22984: * Duplicate key-sequence found.
22985: */
22986: break;
22987: }
22988: i++;
22989: } while (i < targets->nbItems);
22990: if (i != targets->nbItems) {
22991: xmlChar *str = NULL, *strB = NULL;
22992: /*
22993: * TODO: Try to report the key-sequence.
22994: */
22995: xmlSchemaCustomErr(ACTXT_CAST vctxt,
22996: XML_SCHEMAV_CVC_IDC, NULL,
22997: WXS_BASIC_CAST idc,
22998: "Duplicate key-sequence %s in %s",
22999: xmlSchemaFormatIDCKeySequence(vctxt, &str,
23000: (*keySeq), nbKeys),
23001: xmlSchemaGetIDCDesignation(&strB, idc));
23002: FREE_AND_NULL(str);
23003: FREE_AND_NULL(strB);
23004: goto selector_leave;
23005: }
23006: }
23007: /*
23008: * Add a node-table item to the IDC binding.
23009: */
23010: ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23011: sizeof(xmlSchemaPSVIIDCNode));
23012: if (ntItem == NULL) {
23013: xmlSchemaVErrMemory(NULL,
23014: "allocating an IDC node-table item", NULL);
23015: xmlFree(*keySeq);
23016: *keySeq = NULL;
23017: return(-1);
23018: }
23019: memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23020:
23021: /*
23022: * Store the node-table item in a global list.
23023: */
23024: if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23025: if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23026: xmlFree(ntItem);
23027: xmlFree(*keySeq);
23028: *keySeq = NULL;
23029: return (-1);
23030: }
23031: ntItem->nodeQNameID = -1;
23032: } else {
23033: /*
23034: * Save a cached QName for this node on the IDC node, to be
23035: * able to report it, even if the node is not saved.
23036: */
23037: ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23038: vctxt->inode->localName, vctxt->inode->nsName);
23039: if (ntItem->nodeQNameID == -1) {
23040: xmlFree(ntItem);
23041: xmlFree(*keySeq);
23042: *keySeq = NULL;
23043: return (-1);
23044: }
23045: }
23046: /*
23047: * Init the node-table item: Save the node, position and
23048: * consume the key-sequence.
23049: */
23050: ntItem->node = vctxt->node;
23051: ntItem->nodeLine = vctxt->inode->nodeLine;
23052: ntItem->keys = *keySeq;
23053: *keySeq = NULL;
23054: #if 0
23055: if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23056: #endif
23057: if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23058: if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23059: /*
23060: * Free the item, since keyref items won't be
23061: * put on a global list.
23062: */
23063: xmlFree(ntItem->keys);
23064: xmlFree(ntItem);
23065: }
23066: return (-1);
23067: }
23068:
23069: goto selector_leave;
23070: selector_key_error:
23071: {
23072: xmlChar *str = NULL;
23073: /*
23074: * 4.2.1 (KEY) The �target node set� and the
23075: * �qualified node set� are equal, that is, every
23076: * member of the �target node set� is also a member
23077: * of the �qualified node set� and vice versa.
23078: */
23079: xmlSchemaCustomErr(ACTXT_CAST vctxt,
23080: XML_SCHEMAV_CVC_IDC, NULL,
23081: WXS_BASIC_CAST idc,
23082: "Not all fields of %s evaluate to a node",
23083: xmlSchemaGetIDCDesignation(&str, idc), NULL);
23084: FREE_AND_NULL(str);
23085: }
23086: selector_leave:
23087: /*
23088: * Free the key-sequence if not added to the IDC table.
23089: */
23090: if ((keySeq != NULL) && (*keySeq != NULL)) {
23091: xmlFree(*keySeq);
23092: *keySeq = NULL;
23093: }
23094: } /* if selector */
23095:
23096: sto->nbHistory--;
23097:
23098: deregister_check:
23099: /*
23100: * Deregister state objects if they reach the depth of creation.
23101: */
23102: if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23103: #ifdef DEBUG_IDC
23104: xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
23105: sto->sel->xpath);
23106: #endif
23107: if (vctxt->xpathStates != sto) {
23108: VERROR_INT("xmlSchemaXPathProcessHistory",
23109: "The state object to be removed is not the first "
23110: "in the list");
23111: }
23112: nextsto = sto->next;
23113: /*
23114: * Unlink from the list of active XPath state objects.
23115: */
23116: vctxt->xpathStates = sto->next;
23117: sto->next = vctxt->xpathStatePool;
23118: /*
23119: * Link it to the pool of reusable state objects.
23120: */
23121: vctxt->xpathStatePool = sto;
23122: sto = nextsto;
23123: } else
23124: sto = sto->next;
23125: } /* while (sto != NULL) */
23126: return (0);
23127: }
23128:
23129: /**
23130: * xmlSchemaIDCRegisterMatchers:
23131: * @vctxt: the WXS validation context
23132: * @elemDecl: the element declaration
23133: *
23134: * Creates helper objects to evaluate IDC selectors/fields
23135: * successively.
23136: *
23137: * Returns 0 if OK and -1 on internal errors.
23138: */
23139: static int
23140: xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23141: xmlSchemaElementPtr elemDecl)
23142: {
23143: xmlSchemaIDCMatcherPtr matcher, last = NULL;
23144: xmlSchemaIDCPtr idc, refIdc;
23145: xmlSchemaIDCAugPtr aidc;
23146:
23147: idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23148: if (idc == NULL)
23149: return (0);
23150:
23151: #ifdef DEBUG_IDC
23152: {
23153: xmlChar *str = NULL;
23154: xmlGenericError(xmlGenericErrorContext,
23155: "IDC: REGISTER on %s, depth %d\n",
23156: (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23157: vctxt->inode->localName), vctxt->depth);
23158: FREE_AND_NULL(str)
23159: }
23160: #endif
23161: if (vctxt->inode->idcMatchers != NULL) {
23162: VERROR_INT("xmlSchemaIDCRegisterMatchers",
23163: "The chain of IDC matchers is expected to be empty");
23164: return (-1);
23165: }
23166: do {
23167: if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23168: /*
23169: * Since IDCs bubbles are expensive we need to know the
23170: * depth at which the bubbles should stop; this will be
23171: * the depth of the top-most keyref IDC. If no keyref
23172: * references a key/unique IDC, the keyrefDepth will
23173: * be -1, indicating that no bubbles are needed.
23174: */
23175: refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23176: if (refIdc != NULL) {
23177: /*
23178: * Remember that we have keyrefs on this node.
23179: */
23180: vctxt->inode->hasKeyrefs = 1;
23181: /*
23182: * Lookup the referenced augmented IDC info.
23183: */
23184: aidc = vctxt->aidcs;
23185: while (aidc != NULL) {
23186: if (aidc->def == refIdc)
23187: break;
23188: aidc = aidc->next;
23189: }
23190: if (aidc == NULL) {
23191: VERROR_INT("xmlSchemaIDCRegisterMatchers",
23192: "Could not find an augmented IDC item for an IDC "
23193: "definition");
23194: return (-1);
23195: }
23196: if ((aidc->keyrefDepth == -1) ||
23197: (vctxt->depth < aidc->keyrefDepth))
23198: aidc->keyrefDepth = vctxt->depth;
23199: }
23200: }
23201: /*
23202: * Lookup the augmented IDC item for the IDC definition.
23203: */
23204: aidc = vctxt->aidcs;
23205: while (aidc != NULL) {
23206: if (aidc->def == idc)
23207: break;
23208: aidc = aidc->next;
23209: }
23210: if (aidc == NULL) {
23211: VERROR_INT("xmlSchemaIDCRegisterMatchers",
23212: "Could not find an augmented IDC item for an IDC definition");
23213: return (-1);
23214: }
23215: /*
23216: * Create an IDC matcher for every IDC definition.
23217: */
23218: if (vctxt->idcMatcherCache != NULL) {
23219: /*
23220: * Reuse a cached matcher.
23221: */
23222: matcher = vctxt->idcMatcherCache;
23223: vctxt->idcMatcherCache = matcher->nextCached;
23224: matcher->nextCached = NULL;
23225: } else {
23226: matcher = (xmlSchemaIDCMatcherPtr)
23227: xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23228: if (matcher == NULL) {
23229: xmlSchemaVErrMemory(vctxt,
23230: "allocating an IDC matcher", NULL);
23231: return (-1);
23232: }
23233: memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23234: }
23235: if (last == NULL)
23236: vctxt->inode->idcMatchers = matcher;
23237: else
23238: last->next = matcher;
23239: last = matcher;
23240:
23241: matcher->type = IDC_MATCHER;
23242: matcher->depth = vctxt->depth;
23243: matcher->aidc = aidc;
23244: matcher->idcType = aidc->def->type;
23245: #ifdef DEBUG_IDC
23246: xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
23247: #endif
23248: /*
23249: * Init the automaton state object.
23250: */
23251: if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23252: idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23253: return (-1);
23254:
23255: idc = idc->next;
23256: } while (idc != NULL);
23257: return (0);
23258: }
23259:
23260: static int
23261: xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23262: xmlSchemaNodeInfoPtr ielem)
23263: {
23264: xmlSchemaPSVIIDCBindingPtr bind;
23265: int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23266: xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23267: xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23268:
23269: xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23270: /* vctxt->createIDCNodeTables */
23271: while (matcher != NULL) {
23272: /*
23273: * Skip keyref IDCs and empty IDC target-lists.
23274: */
23275: if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23276: WXS_ILIST_IS_EMPTY(matcher->targets))
23277: {
23278: matcher = matcher->next;
23279: continue;
23280: }
23281: /*
23282: * If we _want_ the IDC node-table to be created in any case
23283: * then do so. Otherwise create them only if keyrefs need them.
23284: */
23285: if ((! vctxt->createIDCNodeTables) &&
23286: ((matcher->aidc->keyrefDepth == -1) ||
23287: (matcher->aidc->keyrefDepth > vctxt->depth)))
23288: {
23289: matcher = matcher->next;
23290: continue;
23291: }
23292: /*
23293: * Get/create the IDC binding on this element for the IDC definition.
23294: */
23295: bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23296:
23297: if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23298: dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23299: nbDupls = bind->dupls->nbItems;
23300: } else {
23301: dupls = NULL;
23302: nbDupls = 0;
23303: }
23304: if (bind->nodeTable != NULL) {
23305: nbNodeTable = bind->nbNodes;
23306: } else {
23307: nbNodeTable = 0;
23308: }
23309:
23310: if ((nbNodeTable == 0) && (nbDupls == 0)) {
23311: /*
23312: * Transfer all IDC target-nodes to the IDC node-table.
23313: */
23314: bind->nodeTable =
23315: (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23316: bind->sizeNodes = matcher->targets->sizeItems;
23317: bind->nbNodes = matcher->targets->nbItems;
23318:
23319: matcher->targets->items = NULL;
23320: matcher->targets->sizeItems = 0;
23321: matcher->targets->nbItems = 0;
23322: } else {
23323: /*
23324: * Compare the key-sequences and add to the IDC node-table.
23325: */
23326: nbTargets = matcher->targets->nbItems;
23327: targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23328: nbFields = matcher->aidc->def->nbFields;
23329: i = 0;
23330: do {
23331: keys = targets[i]->keys;
23332: if (nbDupls) {
23333: /*
23334: * Search in already found duplicates first.
23335: */
23336: j = 0;
23337: do {
23338: if (nbFields == 1) {
23339: res = xmlSchemaAreValuesEqual(keys[0]->val,
23340: dupls[j]->keys[0]->val);
23341: if (res == -1)
23342: goto internal_error;
23343: if (res == 1) {
23344: /*
23345: * Equal key-sequence.
23346: */
23347: goto next_target;
23348: }
23349: } else {
23350: res = 0;
23351: ntkeys = dupls[j]->keys;
23352: for (k = 0; k < nbFields; k++) {
23353: res = xmlSchemaAreValuesEqual(keys[k]->val,
23354: ntkeys[k]->val);
23355: if (res == -1)
23356: goto internal_error;
23357: if (res == 0) {
23358: /*
23359: * One of the keys differs.
23360: */
23361: break;
23362: }
23363: }
23364: if (res == 1) {
23365: /*
23366: * Equal key-sequence found.
23367: */
23368: goto next_target;
23369: }
23370: }
23371: j++;
23372: } while (j < nbDupls);
23373: }
23374: if (nbNodeTable) {
23375: j = 0;
23376: do {
23377: if (nbFields == 1) {
23378: res = xmlSchemaAreValuesEqual(keys[0]->val,
23379: bind->nodeTable[j]->keys[0]->val);
23380: if (res == -1)
23381: goto internal_error;
23382: if (res == 0) {
23383: /*
23384: * The key-sequence differs.
23385: */
23386: goto next_node_table_entry;
23387: }
23388: } else {
23389: res = 0;
23390: ntkeys = bind->nodeTable[j]->keys;
23391: for (k = 0; k < nbFields; k++) {
23392: res = xmlSchemaAreValuesEqual(keys[k]->val,
23393: ntkeys[k]->val);
23394: if (res == -1)
23395: goto internal_error;
23396: if (res == 0) {
23397: /*
23398: * One of the keys differs.
23399: */
23400: goto next_node_table_entry;
23401: }
23402: }
23403: }
23404: /*
23405: * Add the duplicate to the list of duplicates.
23406: */
23407: if (bind->dupls == NULL) {
23408: bind->dupls = xmlSchemaItemListCreate();
23409: if (bind->dupls == NULL)
23410: goto internal_error;
23411: }
23412: if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23413: goto internal_error;
23414: /*
23415: * Remove the duplicate entry from the IDC node-table.
23416: */
23417: bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23418: bind->nbNodes--;
23419:
23420: goto next_target;
23421:
23422: next_node_table_entry:
23423: j++;
23424: } while (j < nbNodeTable);
23425: }
23426: /*
23427: * If everything is fine, then add the IDC target-node to
23428: * the IDC node-table.
23429: */
23430: if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23431: goto internal_error;
23432:
23433: next_target:
23434: i++;
23435: } while (i < nbTargets);
23436: }
23437: matcher = matcher->next;
23438: }
23439: return(0);
23440:
23441: internal_error:
23442: return(-1);
23443: }
23444:
23445: /**
23446: * xmlSchemaBubbleIDCNodeTables:
23447: * @depth: the current tree depth
23448: *
23449: * Merges IDC bindings of an element at @depth into the corresponding IDC
23450: * bindings of its parent element. If a duplicate note-table entry is found,
23451: * both, the parent node-table entry and child entry are discarded from the
23452: * node-table of the parent.
23453: *
23454: * Returns 0 if OK and -1 on internal errors.
23455: */
23456: static int
23457: xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23458: {
23459: xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23460: xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23461: xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23462: xmlSchemaIDCAugPtr aidc;
23463: int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23464:
23465: bind = vctxt->inode->idcTable;
23466: if (bind == NULL) {
23467: /* Fine, no table, no bubbles. */
23468: return (0);
23469: }
23470:
23471: parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23472: /*
23473: * Walk all bindings; create new or add to existing bindings.
23474: * Remove duplicate key-sequences.
23475: */
23476: while (bind != NULL) {
23477:
23478: if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23479: goto next_binding;
23480: /*
23481: * Check if the key/unique IDC table needs to be bubbled.
23482: */
23483: if (! vctxt->createIDCNodeTables) {
23484: aidc = vctxt->aidcs;
23485: do {
23486: if (aidc->def == bind->definition) {
23487: if ((aidc->keyrefDepth == -1) ||
23488: (aidc->keyrefDepth >= vctxt->depth)) {
23489: goto next_binding;
23490: }
23491: break;
23492: }
23493: aidc = aidc->next;
23494: } while (aidc != NULL);
23495: }
23496:
23497: if (parTable != NULL)
23498: parBind = *parTable;
23499: /*
23500: * Search a matching parent binding for the
23501: * IDC definition.
23502: */
23503: while (parBind != NULL) {
23504: if (parBind->definition == bind->definition)
23505: break;
23506: parBind = parBind->next;
23507: }
23508:
23509: if (parBind != NULL) {
23510: /*
23511: * Compare every node-table entry of the child node,
23512: * i.e. the key-sequence within, ...
23513: */
23514: oldNum = parBind->nbNodes; /* Skip newly added items. */
23515:
23516: if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23517: oldDupls = parBind->dupls->nbItems;
23518: dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23519: } else {
23520: dupls = NULL;
23521: oldDupls = 0;
23522: }
23523:
23524: parNodes = parBind->nodeTable;
23525: nbFields = bind->definition->nbFields;
23526:
23527: for (i = 0; i < bind->nbNodes; i++) {
23528: node = bind->nodeTable[i];
23529: if (node == NULL)
23530: continue;
23531: /*
23532: * ...with every key-sequence of the parent node, already
23533: * evaluated to be a duplicate key-sequence.
23534: */
23535: if (oldDupls) {
23536: j = 0;
23537: while (j < oldDupls) {
23538: if (nbFields == 1) {
23539: ret = xmlSchemaAreValuesEqual(
23540: node->keys[0]->val,
23541: dupls[j]->keys[0]->val);
23542: if (ret == -1)
23543: goto internal_error;
23544: if (ret == 0) {
23545: j++;
23546: continue;
23547: }
23548: } else {
23549: parNode = dupls[j];
23550: for (k = 0; k < nbFields; k++) {
23551: ret = xmlSchemaAreValuesEqual(
23552: node->keys[k]->val,
23553: parNode->keys[k]->val);
23554: if (ret == -1)
23555: goto internal_error;
23556: if (ret == 0)
23557: break;
23558: }
23559: }
23560: if (ret == 1)
23561: /* Duplicate found. */
23562: break;
23563: j++;
23564: }
23565: if (j != oldDupls) {
23566: /* Duplicate found. Skip this entry. */
23567: continue;
23568: }
23569: }
23570: /*
23571: * ... and with every key-sequence of the parent node.
23572: */
23573: if (oldNum) {
23574: j = 0;
23575: while (j < oldNum) {
23576: parNode = parNodes[j];
23577: if (nbFields == 1) {
23578: ret = xmlSchemaAreValuesEqual(
23579: node->keys[0]->val,
23580: parNode->keys[0]->val);
23581: if (ret == -1)
23582: goto internal_error;
23583: if (ret == 0) {
23584: j++;
23585: continue;
23586: }
23587: } else {
23588: for (k = 0; k < nbFields; k++) {
23589: ret = xmlSchemaAreValuesEqual(
23590: node->keys[k]->val,
23591: parNode->keys[k]->val);
23592: if (ret == -1)
23593: goto internal_error;
23594: if (ret == 0)
23595: break;
23596: }
23597: }
23598: if (ret == 1)
23599: /* Duplicate found. */
23600: break;
23601: j++;
23602: }
23603: if (j != oldNum) {
23604: /*
23605: * Handle duplicates. Move the duplicate in
23606: * the parent's node-table to the list of
23607: * duplicates.
23608: */
23609: oldNum--;
23610: parBind->nbNodes--;
23611: /*
23612: * Move last old item to pos of duplicate.
23613: */
23614: parNodes[j] = parNodes[oldNum];
23615:
23616: if (parBind->nbNodes != oldNum) {
23617: /*
23618: * If new items exist, move last new item to
23619: * last of old items.
23620: */
23621: parNodes[oldNum] =
23622: parNodes[parBind->nbNodes];
23623: }
23624: if (parBind->dupls == NULL) {
23625: parBind->dupls = xmlSchemaItemListCreate();
23626: if (parBind->dupls == NULL)
23627: goto internal_error;
23628: }
23629: xmlSchemaItemListAdd(parBind->dupls, parNode);
23630: } else {
23631: /*
23632: * Add the node-table entry (node and key-sequence) of
23633: * the child node to the node table of the parent node.
23634: */
23635: if (parBind->nodeTable == NULL) {
23636: parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23637: xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23638: if (parBind->nodeTable == NULL) {
23639: xmlSchemaVErrMemory(NULL,
23640: "allocating IDC list of node-table items", NULL);
23641: goto internal_error;
23642: }
23643: parBind->sizeNodes = 1;
23644: } else if (parBind->nbNodes >= parBind->sizeNodes) {
23645: parBind->sizeNodes *= 2;
23646: parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23647: xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23648: sizeof(xmlSchemaPSVIIDCNodePtr));
23649: if (parBind->nodeTable == NULL) {
23650: xmlSchemaVErrMemory(NULL,
23651: "re-allocating IDC list of node-table items", NULL);
23652: goto internal_error;
23653: }
23654: }
23655: parNodes = parBind->nodeTable;
23656: /*
23657: * Append the new node-table entry to the 'new node-table
23658: * entries' section.
23659: */
23660: parNodes[parBind->nbNodes++] = node;
23661: }
23662:
23663: }
23664:
23665: }
23666: } else {
23667: /*
23668: * No binding for the IDC was found: create a new one and
23669: * copy all node-tables.
23670: */
23671: parBind = xmlSchemaIDCNewBinding(bind->definition);
23672: if (parBind == NULL)
23673: goto internal_error;
23674:
23675: /*
23676: * TODO: Hmm, how to optimize the initial number of
23677: * allocated entries?
23678: */
23679: if (bind->nbNodes != 0) {
23680: /*
23681: * Add all IDC node-table entries.
23682: */
23683: if (! vctxt->psviExposeIDCNodeTables) {
23684: /*
23685: * Just move the entries.
23686: * NOTE: this is quite save here, since
23687: * all the keyref lookups have already been
23688: * performed.
23689: */
23690: parBind->nodeTable = bind->nodeTable;
23691: bind->nodeTable = NULL;
23692: parBind->sizeNodes = bind->sizeNodes;
23693: bind->sizeNodes = 0;
23694: parBind->nbNodes = bind->nbNodes;
23695: bind->nbNodes = 0;
23696: } else {
23697: /*
23698: * Copy the entries.
23699: */
23700: parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23701: xmlMalloc(bind->nbNodes *
23702: sizeof(xmlSchemaPSVIIDCNodePtr));
23703: if (parBind->nodeTable == NULL) {
23704: xmlSchemaVErrMemory(NULL,
23705: "allocating an array of IDC node-table "
23706: "items", NULL);
23707: xmlSchemaIDCFreeBinding(parBind);
23708: goto internal_error;
23709: }
23710: parBind->sizeNodes = bind->nbNodes;
23711: parBind->nbNodes = bind->nbNodes;
23712: memcpy(parBind->nodeTable, bind->nodeTable,
23713: bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23714: }
23715: }
23716: if (bind->dupls) {
23717: /*
23718: * Move the duplicates.
23719: */
23720: if (parBind->dupls != NULL)
23721: xmlSchemaItemListFree(parBind->dupls);
23722: parBind->dupls = bind->dupls;
23723: bind->dupls = NULL;
23724: }
23725: if (parTable != NULL) {
23726: if (*parTable == NULL)
23727: *parTable = parBind;
23728: else {
23729: parBind->next = *parTable;
23730: *parTable = parBind;
23731: }
23732: }
23733: }
23734:
23735: next_binding:
23736: bind = bind->next;
23737: }
23738: return (0);
23739:
23740: internal_error:
23741: return(-1);
23742: }
23743:
23744: /**
23745: * xmlSchemaCheckCVCIDCKeyRef:
23746: * @vctxt: the WXS validation context
23747: * @elemDecl: the element declaration
23748: *
23749: * Check the cvc-idc-keyref constraints.
23750: */
23751: static int
23752: xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23753: {
23754: xmlSchemaIDCMatcherPtr matcher;
23755: xmlSchemaPSVIIDCBindingPtr bind;
23756:
23757: matcher = vctxt->inode->idcMatchers;
23758: /*
23759: * Find a keyref.
23760: */
23761: while (matcher != NULL) {
23762: if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23763: matcher->targets &&
23764: matcher->targets->nbItems)
23765: {
23766: int i, j, k, res, nbFields, hasDupls;
23767: xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23768: xmlSchemaPSVIIDCNodePtr refNode = NULL;
23769:
23770: nbFields = matcher->aidc->def->nbFields;
23771:
23772: /*
23773: * Find the IDC node-table for the referenced IDC key/unique.
23774: */
23775: bind = vctxt->inode->idcTable;
23776: while (bind != NULL) {
23777: if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23778: bind->definition)
23779: break;
23780: bind = bind->next;
23781: }
23782: hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23783: /*
23784: * Search for a matching key-sequences.
23785: */
23786: for (i = 0; i < matcher->targets->nbItems; i++) {
23787: res = 0;
23788: refNode = matcher->targets->items[i];
23789: if (bind != NULL) {
23790: refKeys = refNode->keys;
23791: for (j = 0; j < bind->nbNodes; j++) {
23792: keys = bind->nodeTable[j]->keys;
23793: for (k = 0; k < nbFields; k++) {
23794: res = xmlSchemaAreValuesEqual(keys[k]->val,
23795: refKeys[k]->val);
23796: if (res == 0)
23797: break;
23798: else if (res == -1) {
23799: return (-1);
23800: }
23801: }
23802: if (res == 1) {
23803: /*
23804: * Match found.
23805: */
23806: break;
23807: }
23808: }
23809: if ((res == 0) && hasDupls) {
23810: /*
23811: * Search in duplicates
23812: */
23813: for (j = 0; j < bind->dupls->nbItems; j++) {
23814: keys = ((xmlSchemaPSVIIDCNodePtr)
23815: bind->dupls->items[j])->keys;
23816: for (k = 0; k < nbFields; k++) {
23817: res = xmlSchemaAreValuesEqual(keys[k]->val,
23818: refKeys[k]->val);
23819: if (res == 0)
23820: break;
23821: else if (res == -1) {
23822: return (-1);
23823: }
23824: }
23825: if (res == 1) {
23826: /*
23827: * Match in duplicates found.
23828: */
23829: xmlChar *str = NULL, *strB = NULL;
23830: xmlSchemaKeyrefErr(vctxt,
23831: XML_SCHEMAV_CVC_IDC, refNode,
23832: (xmlSchemaTypePtr) matcher->aidc->def,
23833: "More than one match found for "
23834: "key-sequence %s of keyref '%s'",
23835: xmlSchemaFormatIDCKeySequence(vctxt, &str,
23836: refNode->keys, nbFields),
23837: xmlSchemaGetComponentQName(&strB,
23838: matcher->aidc->def));
23839: FREE_AND_NULL(str);
23840: FREE_AND_NULL(strB);
23841: break;
23842: }
23843: }
23844: }
23845: }
23846:
23847: if (res == 0) {
23848: xmlChar *str = NULL, *strB = NULL;
23849: xmlSchemaKeyrefErr(vctxt,
23850: XML_SCHEMAV_CVC_IDC, refNode,
23851: (xmlSchemaTypePtr) matcher->aidc->def,
23852: "No match found for key-sequence %s of keyref '%s'",
23853: xmlSchemaFormatIDCKeySequence(vctxt, &str,
23854: refNode->keys, nbFields),
23855: xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23856: FREE_AND_NULL(str);
23857: FREE_AND_NULL(strB);
23858: }
23859: }
23860: }
23861: matcher = matcher->next;
23862: }
23863: /* TODO: Return an error if any error encountered. */
23864: return (0);
23865: }
23866:
23867: /************************************************************************
23868: * *
23869: * XML Reader validation code *
23870: * *
23871: ************************************************************************/
23872:
23873: static xmlSchemaAttrInfoPtr
23874: xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23875: {
23876: xmlSchemaAttrInfoPtr iattr;
23877: /*
23878: * Grow/create list of attribute infos.
23879: */
23880: if (vctxt->attrInfos == NULL) {
23881: vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23882: xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23883: vctxt->sizeAttrInfos = 1;
23884: if (vctxt->attrInfos == NULL) {
23885: xmlSchemaVErrMemory(vctxt,
23886: "allocating attribute info list", NULL);
23887: return (NULL);
23888: }
23889: } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23890: vctxt->sizeAttrInfos++;
23891: vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23892: xmlRealloc(vctxt->attrInfos,
23893: vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23894: if (vctxt->attrInfos == NULL) {
23895: xmlSchemaVErrMemory(vctxt,
23896: "re-allocating attribute info list", NULL);
23897: return (NULL);
23898: }
23899: } else {
23900: iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23901: if (iattr->localName != NULL) {
23902: VERROR_INT("xmlSchemaGetFreshAttrInfo",
23903: "attr info not cleared");
23904: return (NULL);
23905: }
23906: iattr->nodeType = XML_ATTRIBUTE_NODE;
23907: return (iattr);
23908: }
23909: /*
23910: * Create an attribute info.
23911: */
23912: iattr = (xmlSchemaAttrInfoPtr)
23913: xmlMalloc(sizeof(xmlSchemaAttrInfo));
23914: if (iattr == NULL) {
23915: xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23916: return (NULL);
23917: }
23918: memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23919: iattr->nodeType = XML_ATTRIBUTE_NODE;
23920: vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23921:
23922: return (iattr);
23923: }
23924:
23925: static int
23926: xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23927: xmlNodePtr attrNode,
23928: int nodeLine,
23929: const xmlChar *localName,
23930: const xmlChar *nsName,
23931: int ownedNames,
23932: xmlChar *value,
23933: int ownedValue)
23934: {
23935: xmlSchemaAttrInfoPtr attr;
23936:
23937: attr = xmlSchemaGetFreshAttrInfo(vctxt);
23938: if (attr == NULL) {
23939: VERROR_INT("xmlSchemaPushAttribute",
23940: "calling xmlSchemaGetFreshAttrInfo()");
23941: return (-1);
23942: }
23943: attr->node = attrNode;
23944: attr->nodeLine = nodeLine;
23945: attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23946: attr->localName = localName;
23947: attr->nsName = nsName;
23948: if (ownedNames)
23949: attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23950: /*
23951: * Evaluate if it's an XSI attribute.
23952: */
23953: if (nsName != NULL) {
23954: if (xmlStrEqual(localName, BAD_CAST "nil")) {
23955: if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23956: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23957: }
23958: } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23959: if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23960: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23961: }
23962: } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23963: if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23964: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23965: }
23966: } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23967: if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23968: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23969: }
23970: } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23971: attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23972: }
23973: }
23974: attr->value = value;
23975: if (ownedValue)
23976: attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23977: if (attr->metaType != 0)
23978: attr->state = XML_SCHEMAS_ATTR_META;
23979: return (0);
23980: }
23981:
23982: /**
23983: * xmlSchemaClearElemInfo:
23984: * @vctxt: the WXS validation context
23985: * @ielem: the element information item
23986: */
23987: static void
23988: xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23989: xmlSchemaNodeInfoPtr ielem)
23990: {
23991: ielem->hasKeyrefs = 0;
23992: ielem->appliedXPath = 0;
23993: if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23994: FREE_AND_NULL(ielem->localName);
23995: FREE_AND_NULL(ielem->nsName);
23996: } else {
23997: ielem->localName = NULL;
23998: ielem->nsName = NULL;
23999: }
24000: if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24001: FREE_AND_NULL(ielem->value);
24002: } else {
24003: ielem->value = NULL;
24004: }
24005: if (ielem->val != NULL) {
24006: /*
24007: * PSVI TODO: Be careful not to free it when the value is
24008: * exposed via PSVI.
24009: */
24010: xmlSchemaFreeValue(ielem->val);
24011: ielem->val = NULL;
24012: }
24013: if (ielem->idcMatchers != NULL) {
24014: /*
24015: * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24016: * Does it work?
24017: */
24018: xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24019: #if 0
24020: xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24021: #endif
24022: ielem->idcMatchers = NULL;
24023: }
24024: if (ielem->idcTable != NULL) {
24025: /*
24026: * OPTIMIZE TODO: Use a pool of IDC tables??.
24027: */
24028: xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24029: ielem->idcTable = NULL;
24030: }
24031: if (ielem->regexCtxt != NULL) {
24032: xmlRegFreeExecCtxt(ielem->regexCtxt);
24033: ielem->regexCtxt = NULL;
24034: }
24035: if (ielem->nsBindings != NULL) {
24036: xmlFree((xmlChar **)ielem->nsBindings);
24037: ielem->nsBindings = NULL;
24038: ielem->nbNsBindings = 0;
24039: ielem->sizeNsBindings = 0;
24040: }
24041: }
24042:
24043: /**
24044: * xmlSchemaGetFreshElemInfo:
24045: * @vctxt: the schema validation context
24046: *
24047: * Creates/reuses and initializes the element info item for
24048: * the currect tree depth.
24049: *
24050: * Returns the element info item or NULL on API or internal errors.
24051: */
24052: static xmlSchemaNodeInfoPtr
24053: xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24054: {
24055: xmlSchemaNodeInfoPtr info = NULL;
24056:
24057: if (vctxt->depth > vctxt->sizeElemInfos) {
24058: VERROR_INT("xmlSchemaGetFreshElemInfo",
24059: "inconsistent depth encountered");
24060: return (NULL);
24061: }
24062: if (vctxt->elemInfos == NULL) {
24063: vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24064: xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24065: if (vctxt->elemInfos == NULL) {
24066: xmlSchemaVErrMemory(vctxt,
24067: "allocating the element info array", NULL);
24068: return (NULL);
24069: }
24070: memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24071: vctxt->sizeElemInfos = 10;
24072: } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24073: int i = vctxt->sizeElemInfos;
24074:
24075: vctxt->sizeElemInfos *= 2;
24076: vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24077: xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24078: sizeof(xmlSchemaNodeInfoPtr));
24079: if (vctxt->elemInfos == NULL) {
24080: xmlSchemaVErrMemory(vctxt,
24081: "re-allocating the element info array", NULL);
24082: return (NULL);
24083: }
24084: /*
24085: * We need the new memory to be NULLed.
24086: * TODO: Use memset instead?
24087: */
24088: for (; i < vctxt->sizeElemInfos; i++)
24089: vctxt->elemInfos[i] = NULL;
24090: } else
24091: info = vctxt->elemInfos[vctxt->depth];
24092:
24093: if (info == NULL) {
24094: info = (xmlSchemaNodeInfoPtr)
24095: xmlMalloc(sizeof(xmlSchemaNodeInfo));
24096: if (info == NULL) {
24097: xmlSchemaVErrMemory(vctxt,
24098: "allocating an element info", NULL);
24099: return (NULL);
24100: }
24101: vctxt->elemInfos[vctxt->depth] = info;
24102: } else {
24103: if (info->localName != NULL) {
24104: VERROR_INT("xmlSchemaGetFreshElemInfo",
24105: "elem info has not been cleared");
24106: return (NULL);
24107: }
24108: }
24109: memset(info, 0, sizeof(xmlSchemaNodeInfo));
24110: info->nodeType = XML_ELEMENT_NODE;
24111: info->depth = vctxt->depth;
24112:
24113: return (info);
24114: }
24115:
24116: #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24117: #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24118: #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24119:
24120: static int
24121: xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24122: xmlNodePtr node,
24123: xmlSchemaTypePtr type,
24124: xmlSchemaValType valType,
24125: const xmlChar * value,
24126: xmlSchemaValPtr val,
24127: unsigned long length,
24128: int fireErrors)
24129: {
24130: int ret, error = 0;
24131:
24132: xmlSchemaTypePtr tmpType;
24133: xmlSchemaFacetLinkPtr facetLink;
24134: xmlSchemaFacetPtr facet;
24135: unsigned long len = 0;
24136: xmlSchemaWhitespaceValueType ws;
24137:
24138: /*
24139: * In Libxml2, derived built-in types have currently no explicit facets.
24140: */
24141: if (type->type == XML_SCHEMA_TYPE_BASIC)
24142: return (0);
24143:
24144: /*
24145: * NOTE: Do not jump away, if the facetSet of the given type is
24146: * empty: until now, "pattern" and "enumeration" facets of the
24147: * *base types* need to be checked as well.
24148: */
24149: if (type->facetSet == NULL)
24150: goto pattern_and_enum;
24151:
24152: if (! WXS_IS_ATOMIC(type)) {
24153: if (WXS_IS_LIST(type))
24154: goto WXS_IS_LIST;
24155: else
24156: goto pattern_and_enum;
24157: }
24158: /*
24159: * Whitespace handling is only of importance for string-based
24160: * types.
24161: */
24162: tmpType = xmlSchemaGetPrimitiveType(type);
24163: if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24164: WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24165: ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24166: } else
24167: ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24168: /*
24169: * If the value was not computed (for string or
24170: * anySimpleType based types), then use the provided
24171: * type.
24172: */
24173: if (val == NULL)
24174: valType = valType;
24175: else
24176: valType = xmlSchemaGetValType(val);
24177:
24178: ret = 0;
24179: for (facetLink = type->facetSet; facetLink != NULL;
24180: facetLink = facetLink->next) {
24181: /*
24182: * Skip the pattern "whiteSpace": it is used to
24183: * format the character content beforehand.
24184: */
24185: switch (facetLink->facet->type) {
24186: case XML_SCHEMA_FACET_WHITESPACE:
24187: case XML_SCHEMA_FACET_PATTERN:
24188: case XML_SCHEMA_FACET_ENUMERATION:
24189: continue;
24190: case XML_SCHEMA_FACET_LENGTH:
24191: case XML_SCHEMA_FACET_MINLENGTH:
24192: case XML_SCHEMA_FACET_MAXLENGTH:
24193: ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24194: valType, value, val, &len, ws);
24195: break;
24196: default:
24197: ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24198: valType, value, val, ws);
24199: break;
24200: }
24201: if (ret < 0) {
24202: AERROR_INT("xmlSchemaValidateFacets",
24203: "validating against a atomic type facet");
24204: return (-1);
24205: } else if (ret > 0) {
24206: if (fireErrors)
24207: xmlSchemaFacetErr(actxt, ret, node,
24208: value, len, type, facetLink->facet, NULL, NULL, NULL);
24209: else
24210: return (ret);
24211: if (error == 0)
24212: error = ret;
24213: }
24214: ret = 0;
24215: }
24216:
24217: WXS_IS_LIST:
24218: if (! WXS_IS_LIST(type))
24219: goto pattern_and_enum;
24220: /*
24221: * "length", "minLength" and "maxLength" of list types.
24222: */
24223: ret = 0;
24224: for (facetLink = type->facetSet; facetLink != NULL;
24225: facetLink = facetLink->next) {
24226:
24227: switch (facetLink->facet->type) {
24228: case XML_SCHEMA_FACET_LENGTH:
24229: case XML_SCHEMA_FACET_MINLENGTH:
24230: case XML_SCHEMA_FACET_MAXLENGTH:
24231: ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24232: value, length, NULL);
24233: break;
24234: default:
24235: continue;
24236: }
24237: if (ret < 0) {
24238: AERROR_INT("xmlSchemaValidateFacets",
24239: "validating against a list type facet");
24240: return (-1);
24241: } else if (ret > 0) {
24242: if (fireErrors)
24243: xmlSchemaFacetErr(actxt, ret, node,
24244: value, length, type, facetLink->facet, NULL, NULL, NULL);
24245: else
24246: return (ret);
24247: if (error == 0)
24248: error = ret;
24249: }
24250: ret = 0;
24251: }
24252:
24253: pattern_and_enum:
24254: if (error >= 0) {
24255: int found = 0;
24256: /*
24257: * Process enumerations. Facet values are in the value space
24258: * of the defining type's base type. This seems to be a bug in the
24259: * XML Schema 1.0 spec. Use the whitespace type of the base type.
24260: * Only the first set of enumerations in the ancestor-or-self axis
24261: * is used for validation.
24262: */
24263: ret = 0;
24264: tmpType = type;
24265: do {
24266: for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24267: if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24268: continue;
24269: found = 1;
24270: ret = xmlSchemaAreValuesEqual(facet->val, val);
24271: if (ret == 1)
24272: break;
24273: else if (ret < 0) {
24274: AERROR_INT("xmlSchemaValidateFacets",
24275: "validating against an enumeration facet");
24276: return (-1);
24277: }
24278: }
24279: if (ret != 0)
24280: break;
24281: /*
24282: * Break on the first set of enumerations. Any additional
24283: * enumerations which might be existent on the ancestors
24284: * of the current type are restricted by this set; thus
24285: * *must* *not* be taken into account.
24286: */
24287: if (found)
24288: break;
24289: tmpType = tmpType->baseType;
24290: } while ((tmpType != NULL) &&
24291: (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24292: if (found && (ret == 0)) {
24293: ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24294: if (fireErrors) {
24295: xmlSchemaFacetErr(actxt, ret, node,
24296: value, 0, type, NULL, NULL, NULL, NULL);
24297: } else
24298: return (ret);
24299: if (error == 0)
24300: error = ret;
24301: }
24302: }
24303:
24304: if (error >= 0) {
24305: int found;
24306: /*
24307: * Process patters. Pattern facets are ORed at type level
24308: * and ANDed if derived. Walk the base type axis.
24309: */
24310: tmpType = type;
24311: facet = NULL;
24312: do {
24313: found = 0;
24314: for (facetLink = tmpType->facetSet; facetLink != NULL;
24315: facetLink = facetLink->next) {
24316: if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24317: continue;
24318: found = 1;
24319: /*
24320: * NOTE that for patterns, @value needs to be the
24321: * normalized vaule.
24322: */
24323: ret = xmlRegexpExec(facetLink->facet->regexp, value);
24324: if (ret == 1)
24325: break;
24326: else if (ret < 0) {
24327: AERROR_INT("xmlSchemaValidateFacets",
24328: "validating against a pattern facet");
24329: return (-1);
24330: } else {
24331: /*
24332: * Save the last non-validating facet.
24333: */
24334: facet = facetLink->facet;
24335: }
24336: }
24337: if (found && (ret != 1)) {
24338: ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24339: if (fireErrors) {
24340: xmlSchemaFacetErr(actxt, ret, node,
24341: value, 0, type, facet, NULL, NULL, NULL);
24342: } else
24343: return (ret);
24344: if (error == 0)
24345: error = ret;
24346: break;
24347: }
24348: tmpType = tmpType->baseType;
24349: } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24350: }
24351:
24352: return (error);
24353: }
24354:
24355: static xmlChar *
24356: xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24357: const xmlChar *value)
24358: {
24359: switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24360: case XML_SCHEMA_WHITESPACE_COLLAPSE:
24361: return (xmlSchemaCollapseString(value));
24362: case XML_SCHEMA_WHITESPACE_REPLACE:
24363: return (xmlSchemaWhiteSpaceReplace(value));
24364: default:
24365: return (NULL);
24366: }
24367: }
24368:
24369: static int
24370: xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24371: const xmlChar *value,
24372: xmlSchemaValPtr *val,
24373: int valNeeded)
24374: {
24375: int ret;
24376: const xmlChar *nsName;
24377: xmlChar *local, *prefix = NULL;
24378:
24379: ret = xmlValidateQName(value, 1);
24380: if (ret != 0) {
24381: if (ret == -1) {
24382: VERROR_INT("xmlSchemaValidateQName",
24383: "calling xmlValidateQName()");
24384: return (-1);
24385: }
24386: return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24387: }
24388: /*
24389: * NOTE: xmlSplitQName2 will always return a duplicated
24390: * strings.
24391: */
24392: local = xmlSplitQName2(value, &prefix);
24393: if (local == NULL)
24394: local = xmlStrdup(value);
24395: /*
24396: * OPTIMIZE TODO: Use flags for:
24397: * - is there any namespace binding?
24398: * - is there a default namespace?
24399: */
24400: nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24401:
24402: if (prefix != NULL) {
24403: xmlFree(prefix);
24404: /*
24405: * A namespace must be found if the prefix is
24406: * NOT NULL.
24407: */
24408: if (nsName == NULL) {
24409: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24410: xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24411: WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24412: "The QName value '%s' has no "
24413: "corresponding namespace declaration in "
24414: "scope", value, NULL);
24415: if (local != NULL)
24416: xmlFree(local);
24417: return (ret);
24418: }
24419: }
24420: if (valNeeded && val) {
24421: if (nsName != NULL)
24422: *val = xmlSchemaNewQNameValue(
24423: BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24424: else
24425: *val = xmlSchemaNewQNameValue(NULL,
24426: BAD_CAST local);
24427: } else
24428: xmlFree(local);
24429: return (0);
24430: }
24431:
24432: /*
24433: * cvc-simple-type
24434: */
24435: static int
24436: xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24437: xmlNodePtr node,
24438: xmlSchemaTypePtr type,
24439: const xmlChar *value,
24440: xmlSchemaValPtr *retVal,
24441: int fireErrors,
24442: int normalize,
24443: int isNormalized)
24444: {
24445: int ret = 0, valNeeded = (retVal) ? 1 : 0;
24446: xmlSchemaValPtr val = NULL;
24447: /* xmlSchemaWhitespaceValueType ws; */
24448: xmlChar *normValue = NULL;
24449:
24450: #define NORMALIZE(atype) \
24451: if ((! isNormalized) && \
24452: (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24453: normValue = xmlSchemaNormalizeValue(atype, value); \
24454: if (normValue != NULL) \
24455: value = normValue; \
24456: isNormalized = 1; \
24457: }
24458:
24459: if ((retVal != NULL) && (*retVal != NULL)) {
24460: xmlSchemaFreeValue(*retVal);
24461: *retVal = NULL;
24462: }
24463: /*
24464: * 3.14.4 Simple Type Definition Validation Rules
24465: * Validation Rule: String Valid
24466: */
24467: /*
24468: * 1 It is schema-valid with respect to that definition as defined
24469: * by Datatype Valid in [XML Schemas: Datatypes].
24470: */
24471: /*
24472: * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24473: * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24474: * the string must be a �declared entity name�.
24475: */
24476: /*
24477: * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24478: * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24479: * then every whitespace-delimited substring of the string must be a �declared
24480: * entity name�.
24481: */
24482: /*
24483: * 2.3 otherwise no further condition applies.
24484: */
24485: if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24486: valNeeded = 1;
24487: if (value == NULL)
24488: value = BAD_CAST "";
24489: if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24490: xmlSchemaTypePtr biType; /* The built-in type. */
24491: /*
24492: * SPEC (1.2.1) "if {variety} is �atomic� then the string must �match�
24493: * a literal in the �lexical space� of {base type definition}"
24494: */
24495: /*
24496: * Whitespace-normalize.
24497: */
24498: NORMALIZE(type);
24499: if (type->type != XML_SCHEMA_TYPE_BASIC) {
24500: /*
24501: * Get the built-in type.
24502: */
24503: biType = type->baseType;
24504: while ((biType != NULL) &&
24505: (biType->type != XML_SCHEMA_TYPE_BASIC))
24506: biType = biType->baseType;
24507:
24508: if (biType == NULL) {
24509: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24510: "could not get the built-in type");
24511: goto internal_error;
24512: }
24513: } else
24514: biType = type;
24515: /*
24516: * NOTATIONs need to be processed here, since they need
24517: * to lookup in the hashtable of NOTATION declarations of the schema.
24518: */
24519: if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24520: switch (biType->builtInType) {
24521: case XML_SCHEMAS_NOTATION:
24522: ret = xmlSchemaValidateNotation(
24523: (xmlSchemaValidCtxtPtr) actxt,
24524: ((xmlSchemaValidCtxtPtr) actxt)->schema,
24525: NULL, value, &val, valNeeded);
24526: break;
24527: case XML_SCHEMAS_QNAME:
24528: ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24529: value, &val, valNeeded);
24530: break;
24531: default:
24532: /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24533: if (valNeeded)
24534: ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24535: value, &val, node);
24536: else
24537: ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24538: value, NULL, node);
24539: break;
24540: }
24541: } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24542: switch (biType->builtInType) {
24543: case XML_SCHEMAS_NOTATION:
24544: ret = xmlSchemaValidateNotation(NULL,
24545: ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24546: value, &val, valNeeded);
24547: break;
24548: default:
24549: /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24550: if (valNeeded)
24551: ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24552: value, &val, node);
24553: else
24554: ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24555: value, NULL, node);
24556: break;
24557: }
24558: } else {
24559: /*
24560: * Validation via a public API is not implemented yet.
24561: */
24562: TODO
24563: goto internal_error;
24564: }
24565: if (ret != 0) {
24566: if (ret < 0) {
24567: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24568: "validating against a built-in type");
24569: goto internal_error;
24570: }
24571: if (WXS_IS_LIST(type))
24572: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24573: else
24574: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24575: }
24576: if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24577: /*
24578: * Check facets.
24579: */
24580: ret = xmlSchemaValidateFacets(actxt, node, type,
24581: (xmlSchemaValType) biType->builtInType, value, val,
24582: 0, fireErrors);
24583: if (ret != 0) {
24584: if (ret < 0) {
24585: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24586: "validating facets of atomic simple type");
24587: goto internal_error;
24588: }
24589: if (WXS_IS_LIST(type))
24590: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24591: else
24592: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24593: }
24594: }
24595: if (fireErrors && (ret > 0))
24596: xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24597: } else if (WXS_IS_LIST(type)) {
24598:
24599: xmlSchemaTypePtr itemType;
24600: const xmlChar *cur, *end;
24601: xmlChar *tmpValue = NULL;
24602: unsigned long len = 0;
24603: xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24604: /* 1.2.2 if {variety} is �list� then the string must be a sequence
24605: * of white space separated tokens, each of which �match�es a literal
24606: * in the �lexical space� of {item type definition}
24607: */
24608: /*
24609: * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24610: * the list type has an enum or pattern facet.
24611: */
24612: NORMALIZE(type);
24613: /*
24614: * VAL TODO: Optimize validation of empty values.
24615: * VAL TODO: We do not have computed values for lists.
24616: */
24617: itemType = WXS_LIST_ITEMTYPE(type);
24618: cur = value;
24619: do {
24620: while (IS_BLANK_CH(*cur))
24621: cur++;
24622: end = cur;
24623: while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24624: end++;
24625: if (end == cur)
24626: break;
24627: tmpValue = xmlStrndup(cur, end - cur);
24628: len++;
24629:
24630: if (valNeeded)
24631: ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24632: tmpValue, &curVal, fireErrors, 0, 1);
24633: else
24634: ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24635: tmpValue, NULL, fireErrors, 0, 1);
24636: FREE_AND_NULL(tmpValue);
24637: if (curVal != NULL) {
24638: /*
24639: * Add to list of computed values.
24640: */
24641: if (val == NULL)
24642: val = curVal;
24643: else
24644: xmlSchemaValueAppend(prevVal, curVal);
24645: prevVal = curVal;
24646: curVal = NULL;
24647: }
24648: if (ret != 0) {
24649: if (ret < 0) {
24650: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24651: "validating an item of list simple type");
24652: goto internal_error;
24653: }
24654: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24655: break;
24656: }
24657: cur = end;
24658: } while (*cur != 0);
24659: FREE_AND_NULL(tmpValue);
24660: if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24661: /*
24662: * Apply facets (pattern, enumeration).
24663: */
24664: ret = xmlSchemaValidateFacets(actxt, node, type,
24665: XML_SCHEMAS_UNKNOWN, value, val,
24666: len, fireErrors);
24667: if (ret != 0) {
24668: if (ret < 0) {
24669: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24670: "validating facets of list simple type");
24671: goto internal_error;
24672: }
24673: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24674: }
24675: }
24676: if (fireErrors && (ret > 0)) {
24677: /*
24678: * Report the normalized value.
24679: */
24680: normalize = 1;
24681: NORMALIZE(type);
24682: xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24683: }
24684: } else if (WXS_IS_UNION(type)) {
24685: xmlSchemaTypeLinkPtr memberLink;
24686: /*
24687: * TODO: For all datatypes �derived� by �union� whiteSpace does
24688: * not apply directly; however, the normalization behavior of �union�
24689: * types is controlled by the value of whiteSpace on that one of the
24690: * �memberTypes� against which the �union� is successfully validated.
24691: *
24692: * This means that the value is normalized by the first validating
24693: * member type, then the facets of the union type are applied. This
24694: * needs changing of the value!
24695: */
24696:
24697: /*
24698: * 1.2.3 if {variety} is �union� then the string must �match� a
24699: * literal in the �lexical space� of at least one member of
24700: * {member type definitions}
24701: */
24702: memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24703: if (memberLink == NULL) {
24704: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24705: "union simple type has no member types");
24706: goto internal_error;
24707: }
24708: /*
24709: * Always normalize union type values, since we currently
24710: * cannot store the whitespace information with the value
24711: * itself; otherwise a later value-comparison would be
24712: * not possible.
24713: */
24714: while (memberLink != NULL) {
24715: if (valNeeded)
24716: ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24717: memberLink->type, value, &val, 0, 1, 0);
24718: else
24719: ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24720: memberLink->type, value, NULL, 0, 1, 0);
24721: if (ret <= 0)
24722: break;
24723: memberLink = memberLink->next;
24724: }
24725: if (ret != 0) {
24726: if (ret < 0) {
24727: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24728: "validating members of union simple type");
24729: goto internal_error;
24730: }
24731: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24732: }
24733: /*
24734: * Apply facets (pattern, enumeration).
24735: */
24736: if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24737: /*
24738: * The normalization behavior of �union� types is controlled by
24739: * the value of whiteSpace on that one of the �memberTypes�
24740: * against which the �union� is successfully validated.
24741: */
24742: NORMALIZE(memberLink->type);
24743: ret = xmlSchemaValidateFacets(actxt, node, type,
24744: XML_SCHEMAS_UNKNOWN, value, val,
24745: 0, fireErrors);
24746: if (ret != 0) {
24747: if (ret < 0) {
24748: AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24749: "validating facets of union simple type");
24750: goto internal_error;
24751: }
24752: ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24753: }
24754: }
24755: if (fireErrors && (ret > 0))
24756: xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24757: }
24758:
24759: if (normValue != NULL)
24760: xmlFree(normValue);
24761: if (ret == 0) {
24762: if (retVal != NULL)
24763: *retVal = val;
24764: else if (val != NULL)
24765: xmlSchemaFreeValue(val);
24766: } else if (val != NULL)
24767: xmlSchemaFreeValue(val);
24768: return (ret);
24769: internal_error:
24770: if (normValue != NULL)
24771: xmlFree(normValue);
24772: if (val != NULL)
24773: xmlSchemaFreeValue(val);
24774: return (-1);
24775: }
24776:
24777: static int
24778: xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24779: const xmlChar *value,
24780: const xmlChar **nsName,
24781: const xmlChar **localName)
24782: {
24783: int ret = 0;
24784:
24785: if ((nsName == NULL) || (localName == NULL))
24786: return (-1);
24787: *nsName = NULL;
24788: *localName = NULL;
24789:
24790: ret = xmlValidateQName(value, 1);
24791: if (ret == -1)
24792: return (-1);
24793: if (ret > 0) {
24794: xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24795: XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24796: value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24797: return (1);
24798: }
24799: {
24800: xmlChar *local = NULL;
24801: xmlChar *prefix;
24802:
24803: /*
24804: * NOTE: xmlSplitQName2 will return a duplicated
24805: * string.
24806: */
24807: local = xmlSplitQName2(value, &prefix);
24808: if (local == NULL)
24809: *localName = xmlDictLookup(vctxt->dict, value, -1);
24810: else {
24811: *localName = xmlDictLookup(vctxt->dict, local, -1);
24812: xmlFree(local);
24813: }
24814:
24815: *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24816:
24817: if (prefix != NULL) {
24818: xmlFree(prefix);
24819: /*
24820: * A namespace must be found if the prefix is NOT NULL.
24821: */
24822: if (*nsName == NULL) {
24823: xmlSchemaCustomErr(ACTXT_CAST vctxt,
24824: XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24825: WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24826: "The QName value '%s' has no "
24827: "corresponding namespace declaration in scope",
24828: value, NULL);
24829: return (2);
24830: }
24831: }
24832: }
24833: return (0);
24834: }
24835:
24836: static int
24837: xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24838: xmlSchemaAttrInfoPtr iattr,
24839: xmlSchemaTypePtr *localType,
24840: xmlSchemaElementPtr elemDecl)
24841: {
24842: int ret = 0;
24843: /*
24844: * cvc-elt (3.3.4) : (4)
24845: * AND
24846: * Schema-Validity Assessment (Element) (cvc-assess-elt)
24847: * (1.2.1.2.1) - (1.2.1.2.4)
24848: * Handle 'xsi:type'.
24849: */
24850: if (localType == NULL)
24851: return (-1);
24852: *localType = NULL;
24853: if (iattr == NULL)
24854: return (0);
24855: else {
24856: const xmlChar *nsName = NULL, *local = NULL;
24857: /*
24858: * TODO: We should report a *warning* that the type was overriden
24859: * by the instance.
24860: */
24861: ACTIVATE_ATTRIBUTE(iattr);
24862: /*
24863: * (cvc-elt) (3.3.4) : (4.1)
24864: * (cvc-assess-elt) (1.2.1.2.2)
24865: */
24866: ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24867: &nsName, &local);
24868: if (ret != 0) {
24869: if (ret < 0) {
24870: VERROR_INT("xmlSchemaValidateElementByDeclaration",
24871: "calling xmlSchemaQNameExpand() to validate the "
24872: "attribute 'xsi:type'");
24873: goto internal_error;
24874: }
24875: goto exit;
24876: }
24877: /*
24878: * (cvc-elt) (3.3.4) : (4.2)
24879: * (cvc-assess-elt) (1.2.1.2.3)
24880: */
24881: *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24882: if (*localType == NULL) {
24883: xmlChar *str = NULL;
24884:
24885: xmlSchemaCustomErr(ACTXT_CAST vctxt,
24886: XML_SCHEMAV_CVC_ELT_4_2, NULL,
24887: WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24888: "The QName value '%s' of the xsi:type attribute does not "
24889: "resolve to a type definition",
24890: xmlSchemaFormatQName(&str, nsName, local), NULL);
24891: FREE_AND_NULL(str);
24892: ret = vctxt->err;
24893: goto exit;
24894: }
24895: if (elemDecl != NULL) {
24896: int set = 0;
24897:
24898: /*
24899: * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24900: * "The �local type definition� must be validly
24901: * derived from the {type definition} given the union of
24902: * the {disallowed substitutions} and the {type definition}'s
24903: * {prohibited substitutions}, as defined in
24904: * Type Derivation OK (Complex) (�3.4.6)
24905: * (if it is a complex type definition),
24906: * or given {disallowed substitutions} as defined in Type
24907: * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24908: * definition)."
24909: *
24910: * {disallowed substitutions}: the "block" on the element decl.
24911: * {prohibited substitutions}: the "block" on the type def.
24912: */
24913: /*
24914: * OPTIMIZE TODO: We could map types already evaluated
24915: * to be validly derived from other types to avoid checking
24916: * this over and over for the same types.
24917: */
24918: if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24919: (elemDecl->subtypes->flags &
24920: XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24921: set |= SUBSET_EXTENSION;
24922:
24923: if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24924: (elemDecl->subtypes->flags &
24925: XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24926: set |= SUBSET_RESTRICTION;
24927:
24928: /*
24929: * REMOVED and CHANGED since this produced a parser context
24930: * which adds to the string dict of the schema. So this would
24931: * change the schema and we don't want this. We don't need
24932: * the parser context anymore.
24933: *
24934: * if ((vctxt->pctxt == NULL) &&
24935: * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24936: * return (-1);
24937: */
24938:
24939: if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24940: elemDecl->subtypes, set) != 0) {
24941: xmlChar *str = NULL;
24942:
24943: xmlSchemaCustomErr(ACTXT_CAST vctxt,
24944: XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24945: "The type definition '%s', specified by xsi:type, is "
24946: "blocked or not validly derived from the type definition "
24947: "of the element declaration",
24948: xmlSchemaFormatQName(&str,
24949: (*localType)->targetNamespace,
24950: (*localType)->name),
24951: NULL);
24952: FREE_AND_NULL(str);
24953: ret = vctxt->err;
24954: *localType = NULL;
24955: }
24956: }
24957: }
24958: exit:
24959: ACTIVATE_ELEM;
24960: return (ret);
24961: internal_error:
24962: ACTIVATE_ELEM;
24963: return (-1);
24964: }
24965:
24966: static int
24967: xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24968: {
24969: xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24970: xmlSchemaTypePtr actualType;
24971:
24972: /*
24973: * cvc-elt (3.3.4) : 1
24974: */
24975: if (elemDecl == NULL) {
24976: VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24977: "No matching declaration available");
24978: return (vctxt->err);
24979: }
24980: actualType = WXS_ELEM_TYPEDEF(elemDecl);
24981: /*
24982: * cvc-elt (3.3.4) : 2
24983: */
24984: if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24985: VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24986: "The element declaration is abstract");
24987: return (vctxt->err);
24988: }
24989: if (actualType == NULL) {
24990: VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24991: "The type definition is absent");
24992: return (XML_SCHEMAV_CVC_TYPE_1);
24993: }
24994: if (vctxt->nbAttrInfos != 0) {
24995: int ret;
24996: xmlSchemaAttrInfoPtr iattr;
24997: /*
24998: * cvc-elt (3.3.4) : 3
24999: * Handle 'xsi:nil'.
25000: */
25001: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25002: XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25003: if (iattr) {
25004: ACTIVATE_ATTRIBUTE(iattr);
25005: /*
25006: * Validate the value.
25007: */
25008: ret = xmlSchemaVCheckCVCSimpleType(
25009: ACTXT_CAST vctxt, NULL,
25010: xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25011: iattr->value, &(iattr->val), 1, 0, 0);
25012: ACTIVATE_ELEM;
25013: if (ret < 0) {
25014: VERROR_INT("xmlSchemaValidateElemDecl",
25015: "calling xmlSchemaVCheckCVCSimpleType() to "
25016: "validate the attribute 'xsi:nil'");
25017: return (-1);
25018: }
25019: if (ret == 0) {
25020: if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25021: /*
25022: * cvc-elt (3.3.4) : 3.1
25023: */
25024: VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25025: "The element is not 'nillable'");
25026: /* Does not return an error on purpose. */
25027: } else {
25028: if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25029: /*
25030: * cvc-elt (3.3.4) : 3.2.2
25031: */
25032: if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25033: (elemDecl->value != NULL)) {
25034: VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25035: "The element cannot be 'nilled' because "
25036: "there is a fixed value constraint defined "
25037: "for it");
25038: /* Does not return an error on purpose. */
25039: } else
25040: vctxt->inode->flags |=
25041: XML_SCHEMA_ELEM_INFO_NILLED;
25042: }
25043: }
25044: }
25045: }
25046: /*
25047: * cvc-elt (3.3.4) : 4
25048: * Handle 'xsi:type'.
25049: */
25050: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25051: XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25052: if (iattr) {
25053: xmlSchemaTypePtr localType = NULL;
25054:
25055: ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25056: elemDecl);
25057: if (ret != 0) {
25058: if (ret == -1) {
25059: VERROR_INT("xmlSchemaValidateElemDecl",
25060: "calling xmlSchemaProcessXSIType() to "
25061: "process the attribute 'xsi:type'");
25062: return (-1);
25063: }
25064: /* Does not return an error on purpose. */
25065: }
25066: if (localType != NULL) {
25067: vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25068: actualType = localType;
25069: }
25070: }
25071: }
25072: /*
25073: * IDC: Register identity-constraint XPath matchers.
25074: */
25075: if ((elemDecl->idcs != NULL) &&
25076: (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25077: return (-1);
25078: /*
25079: * No actual type definition.
25080: */
25081: if (actualType == NULL) {
25082: VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25083: "The type definition is absent");
25084: return (XML_SCHEMAV_CVC_TYPE_1);
25085: }
25086: /*
25087: * Remember the actual type definition.
25088: */
25089: vctxt->inode->typeDef = actualType;
25090:
25091: return (0);
25092: }
25093:
25094: static int
25095: xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25096: {
25097: xmlSchemaAttrInfoPtr iattr;
25098: int ret = 0, i;
25099:
25100: /*
25101: * SPEC cvc-type (3.1.1)
25102: * "The attributes of must be empty, excepting those whose namespace
25103: * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25104: * whose local name is one of type, nil, schemaLocation or
25105: * noNamespaceSchemaLocation."
25106: */
25107: if (vctxt->nbAttrInfos == 0)
25108: return (0);
25109: for (i = 0; i < vctxt->nbAttrInfos; i++) {
25110: iattr = vctxt->attrInfos[i];
25111: if (! iattr->metaType) {
25112: ACTIVATE_ATTRIBUTE(iattr)
25113: xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25114: XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25115: ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25116: }
25117: }
25118: ACTIVATE_ELEM
25119: return (ret);
25120: }
25121:
25122: /*
25123: * Cleanup currently used attribute infos.
25124: */
25125: static void
25126: xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25127: {
25128: int i;
25129: xmlSchemaAttrInfoPtr attr;
25130:
25131: if (vctxt->nbAttrInfos == 0)
25132: return;
25133: for (i = 0; i < vctxt->nbAttrInfos; i++) {
25134: attr = vctxt->attrInfos[i];
25135: if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25136: if (attr->localName != NULL)
25137: xmlFree((xmlChar *) attr->localName);
25138: if (attr->nsName != NULL)
25139: xmlFree((xmlChar *) attr->nsName);
25140: }
25141: if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25142: if (attr->value != NULL)
25143: xmlFree((xmlChar *) attr->value);
25144: }
25145: if (attr->val != NULL) {
25146: xmlSchemaFreeValue(attr->val);
25147: attr->val = NULL;
25148: }
25149: memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25150: }
25151: vctxt->nbAttrInfos = 0;
25152: }
25153:
25154: /*
25155: * 3.4.4 Complex Type Definition Validation Rules
25156: * Element Locally Valid (Complex Type) (cvc-complex-type)
25157: * 3.2.4 Attribute Declaration Validation Rules
25158: * Validation Rule: Attribute Locally Valid (cvc-attribute)
25159: * Attribute Locally Valid (Use) (cvc-au)
25160: *
25161: * Only "assessed" attribute information items will be visible to
25162: * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25163: */
25164: static int
25165: xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25166: {
25167: xmlSchemaTypePtr type = vctxt->inode->typeDef;
25168: xmlSchemaItemListPtr attrUseList;
25169: xmlSchemaAttributeUsePtr attrUse = NULL;
25170: xmlSchemaAttributePtr attrDecl = NULL;
25171: xmlSchemaAttrInfoPtr iattr, tmpiattr;
25172: int i, j, found, nbAttrs, nbUses;
25173: int xpathRes = 0, res, wildIDs = 0, fixed;
25174: xmlNodePtr defAttrOwnerElem = NULL;
25175:
25176: /*
25177: * SPEC (cvc-attribute)
25178: * (1) "The declaration must not be �absent� (see Missing
25179: * Sub-components (�5.3) for how this can fail to be
25180: * the case)."
25181: * (2) "Its {type definition} must not be absent."
25182: *
25183: * NOTE (1) + (2): This is not handled here, since we currently do not
25184: * allow validation against schemas which have missing sub-components.
25185: *
25186: * SPEC (cvc-complex-type)
25187: * (3) "For each attribute information item in the element information
25188: * item's [attributes] excepting those whose [namespace name] is
25189: * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25190: * [local name] is one of type, nil, schemaLocation or
25191: * noNamespaceSchemaLocation, the appropriate case among the following
25192: * must be true:
25193: *
25194: */
25195: attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25196: /*
25197: * @nbAttrs is the number of attributes present in the instance.
25198: */
25199: nbAttrs = vctxt->nbAttrInfos;
25200: if (attrUseList != NULL)
25201: nbUses = attrUseList->nbItems;
25202: else
25203: nbUses = 0;
25204: for (i = 0; i < nbUses; i++) {
25205: found = 0;
25206: attrUse = attrUseList->items[i];
25207: attrDecl = WXS_ATTRUSE_DECL(attrUse);
25208: for (j = 0; j < nbAttrs; j++) {
25209: iattr = vctxt->attrInfos[j];
25210: /*
25211: * SPEC (cvc-complex-type) (3)
25212: * Skip meta attributes.
25213: */
25214: if (iattr->metaType)
25215: continue;
25216: if (iattr->localName[0] != attrDecl->name[0])
25217: continue;
25218: if (!xmlStrEqual(iattr->localName, attrDecl->name))
25219: continue;
25220: if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25221: continue;
25222: found = 1;
25223: /*
25224: * SPEC (cvc-complex-type)
25225: * (3.1) "If there is among the {attribute uses} an attribute
25226: * use with an {attribute declaration} whose {name} matches
25227: * the attribute information item's [local name] and whose
25228: * {target namespace} is identical to the attribute information
25229: * item's [namespace name] (where an �absent� {target namespace}
25230: * is taken to be identical to a [namespace name] with no value),
25231: * then the attribute information must be �valid� with respect
25232: * to that attribute use as per Attribute Locally Valid (Use)
25233: * (�3.5.4). In this case the {attribute declaration} of that
25234: * attribute use is the �context-determined declaration� for the
25235: * attribute information item with respect to Schema-Validity
25236: * Assessment (Attribute) (�3.2.4) and
25237: * Assessment Outcome (Attribute) (�3.2.5).
25238: */
25239: iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25240: iattr->use = attrUse;
25241: /*
25242: * Context-determined declaration.
25243: */
25244: iattr->decl = attrDecl;
25245: iattr->typeDef = attrDecl->subtypes;
25246: break;
25247: }
25248:
25249: if (found)
25250: continue;
25251:
25252: if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25253: /*
25254: * Handle non-existent, required attributes.
25255: *
25256: * SPEC (cvc-complex-type)
25257: * (4) "The {attribute declaration} of each attribute use in
25258: * the {attribute uses} whose {required} is true matches one
25259: * of the attribute information items in the element information
25260: * item's [attributes] as per clause 3.1 above."
25261: */
25262: tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25263: if (tmpiattr == NULL) {
25264: VERROR_INT(
25265: "xmlSchemaVAttributesComplex",
25266: "calling xmlSchemaGetFreshAttrInfo()");
25267: return (-1);
25268: }
25269: tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25270: tmpiattr->use = attrUse;
25271: tmpiattr->decl = attrDecl;
25272: } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25273: ((attrUse->defValue != NULL) ||
25274: (attrDecl->defValue != NULL))) {
25275: /*
25276: * Handle non-existent, optional, default/fixed attributes.
25277: */
25278: tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25279: if (tmpiattr == NULL) {
25280: VERROR_INT(
25281: "xmlSchemaVAttributesComplex",
25282: "calling xmlSchemaGetFreshAttrInfo()");
25283: return (-1);
25284: }
25285: tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25286: tmpiattr->use = attrUse;
25287: tmpiattr->decl = attrDecl;
25288: tmpiattr->typeDef = attrDecl->subtypes;
25289: tmpiattr->localName = attrDecl->name;
25290: tmpiattr->nsName = attrDecl->targetNamespace;
25291: }
25292: }
25293:
25294: if (vctxt->nbAttrInfos == 0)
25295: return (0);
25296: /*
25297: * Validate against the wildcard.
25298: */
25299: if (type->attributeWildcard != NULL) {
25300: /*
25301: * SPEC (cvc-complex-type)
25302: * (3.2.1) "There must be an {attribute wildcard}."
25303: */
25304: for (i = 0; i < nbAttrs; i++) {
25305: iattr = vctxt->attrInfos[i];
25306: /*
25307: * SPEC (cvc-complex-type) (3)
25308: * Skip meta attributes.
25309: */
25310: if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25311: continue;
25312: /*
25313: * SPEC (cvc-complex-type)
25314: * (3.2.2) "The attribute information item must be �valid� with
25315: * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25316: *
25317: * SPEC Item Valid (Wildcard) (cvc-wildcard)
25318: * "... its [namespace name] must be �valid� with respect to
25319: * the wildcard constraint, as defined in Wildcard allows
25320: * Namespace Name (�3.10.4)."
25321: */
25322: if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25323: iattr->nsName) == 0) {
25324: /*
25325: * Handle processContents.
25326: *
25327: * SPEC (cvc-wildcard):
25328: * processContents | context-determined declaration:
25329: * "strict" "mustFind"
25330: * "lax" "none"
25331: * "skip" "skip"
25332: */
25333: if (type->attributeWildcard->processContents ==
25334: XML_SCHEMAS_ANY_SKIP) {
25335: /*
25336: * context-determined declaration = "skip"
25337: *
25338: * SPEC PSVI Assessment Outcome (Attribute)
25339: * [validity] = "notKnown"
25340: * [validation attempted] = "none"
25341: */
25342: iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25343: continue;
25344: }
25345: /*
25346: * Find an attribute declaration.
25347: */
25348: iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25349: iattr->localName, iattr->nsName);
25350: if (iattr->decl != NULL) {
25351: iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25352: /*
25353: * SPEC (cvc-complex-type)
25354: * (5) "Let [Definition:] the wild IDs be the set of
25355: * all attribute information item to which clause 3.2
25356: * applied and whose �validation� resulted in a
25357: * �context-determined declaration� of mustFind or no
25358: * �context-determined declaration� at all, and whose
25359: * [local name] and [namespace name] resolve (as
25360: * defined by QName resolution (Instance) (�3.15.4)) to
25361: * an attribute declaration whose {type definition} is
25362: * or is derived from ID. Then all of the following
25363: * must be true:"
25364: */
25365: iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25366: if (xmlSchemaIsDerivedFromBuiltInType(
25367: iattr->typeDef, XML_SCHEMAS_ID)) {
25368: /*
25369: * SPEC (5.1) "There must be no more than one
25370: * item in �wild IDs�."
25371: */
25372: if (wildIDs != 0) {
25373: /* VAL TODO */
25374: iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25375: TODO
25376: continue;
25377: }
25378: wildIDs++;
25379: /*
25380: * SPEC (cvc-complex-type)
25381: * (5.2) "If �wild IDs� is non-empty, there must not
25382: * be any attribute uses among the {attribute uses}
25383: * whose {attribute declaration}'s {type definition}
25384: * is or is derived from ID."
25385: */
25386: if (attrUseList != NULL) {
25387: for (j = 0; j < attrUseList->nbItems; j++) {
25388: if (xmlSchemaIsDerivedFromBuiltInType(
25389: WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25390: XML_SCHEMAS_ID)) {
25391: /* URGENT VAL TODO: implement */
25392: iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25393: TODO
25394: break;
25395: }
25396: }
25397: }
25398: }
25399: } else if (type->attributeWildcard->processContents ==
25400: XML_SCHEMAS_ANY_LAX) {
25401: iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25402: /*
25403: * SPEC PSVI Assessment Outcome (Attribute)
25404: * [validity] = "notKnown"
25405: * [validation attempted] = "none"
25406: */
25407: } else {
25408: iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25409: }
25410: }
25411: }
25412: }
25413:
25414: if (vctxt->nbAttrInfos == 0)
25415: return (0);
25416:
25417: /*
25418: * Get the owner element; needed for creation of default attributes.
25419: * This fixes bug #341337, reported by David Grohmann.
25420: */
25421: if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25422: xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25423: if (ielem && ielem->node && ielem->node->doc)
25424: defAttrOwnerElem = ielem->node;
25425: }
25426: /*
25427: * Validate values, create default attributes, evaluate IDCs.
25428: */
25429: for (i = 0; i < vctxt->nbAttrInfos; i++) {
25430: iattr = vctxt->attrInfos[i];
25431: /*
25432: * VAL TODO: Note that we won't try to resolve IDCs to
25433: * "lax" and "skip" validated attributes. Check what to
25434: * do in this case.
25435: */
25436: if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25437: (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25438: continue;
25439: /*
25440: * VAL TODO: What to do if the type definition is missing?
25441: */
25442: if (iattr->typeDef == NULL) {
25443: iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25444: continue;
25445: }
25446:
25447: ACTIVATE_ATTRIBUTE(iattr);
25448: fixed = 0;
25449: xpathRes = 0;
25450:
25451: if (vctxt->xpathStates != NULL) {
25452: /*
25453: * Evaluate IDCs.
25454: */
25455: xpathRes = xmlSchemaXPathEvaluate(vctxt,
25456: XML_ATTRIBUTE_NODE);
25457: if (xpathRes == -1) {
25458: VERROR_INT("xmlSchemaVAttributesComplex",
25459: "calling xmlSchemaXPathEvaluate()");
25460: goto internal_error;
25461: }
25462: }
25463:
25464: if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25465: /*
25466: * Default/fixed attributes.
25467: * We need the value only if we need to resolve IDCs or
25468: * will create default attributes.
25469: */
25470: if ((xpathRes) || (defAttrOwnerElem)) {
25471: if (iattr->use->defValue != NULL) {
25472: iattr->value = (xmlChar *) iattr->use->defValue;
25473: iattr->val = iattr->use->defVal;
25474: } else {
25475: iattr->value = (xmlChar *) iattr->decl->defValue;
25476: iattr->val = iattr->decl->defVal;
25477: }
25478: /*
25479: * IDCs will consume the precomputed default value,
25480: * so we need to clone it.
25481: */
25482: if (iattr->val == NULL) {
25483: VERROR_INT("xmlSchemaVAttributesComplex",
25484: "default/fixed value on an attribute use was "
25485: "not precomputed");
25486: goto internal_error;
25487: }
25488: iattr->val = xmlSchemaCopyValue(iattr->val);
25489: if (iattr->val == NULL) {
25490: VERROR_INT("xmlSchemaVAttributesComplex",
25491: "calling xmlSchemaCopyValue()");
25492: goto internal_error;
25493: }
25494: }
25495: /*
25496: * PSVI: Add the default attribute to the current element.
25497: * VAL TODO: Should we use the *normalized* value? This currently
25498: * uses the *initial* value.
25499: */
25500:
25501: if (defAttrOwnerElem) {
25502: xmlChar *normValue;
25503: const xmlChar *value;
25504:
25505: value = iattr->value;
25506: /*
25507: * Normalize the value.
25508: */
25509: normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25510: iattr->value);
25511: if (normValue != NULL)
25512: value = BAD_CAST normValue;
25513:
25514: if (iattr->nsName == NULL) {
25515: if (xmlNewProp(defAttrOwnerElem,
25516: iattr->localName, value) == NULL) {
25517: VERROR_INT("xmlSchemaVAttributesComplex",
25518: "callling xmlNewProp()");
25519: if (normValue != NULL)
25520: xmlFree(normValue);
25521: goto internal_error;
25522: }
25523: } else {
25524: xmlNsPtr ns;
25525:
25526: ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25527: defAttrOwnerElem, iattr->nsName);
25528: if (ns == NULL) {
25529: xmlChar prefix[12];
25530: int counter = 0;
25531:
25532: /*
25533: * Create a namespace declaration on the validation
25534: * root node if no namespace declaration is in scope.
25535: */
25536: do {
25537: snprintf((char *) prefix, 12, "p%d", counter++);
25538: ns = xmlSearchNs(defAttrOwnerElem->doc,
25539: defAttrOwnerElem, BAD_CAST prefix);
25540: if (counter > 1000) {
25541: VERROR_INT(
25542: "xmlSchemaVAttributesComplex",
25543: "could not compute a ns prefix for a "
25544: "default/fixed attribute");
25545: if (normValue != NULL)
25546: xmlFree(normValue);
25547: goto internal_error;
25548: }
25549: } while (ns != NULL);
25550: ns = xmlNewNs(vctxt->validationRoot,
25551: iattr->nsName, BAD_CAST prefix);
25552: }
25553: /*
25554: * TODO:
25555: * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25556: * If we have QNames: do we need to ensure there's a
25557: * prefix defined for the QName?
25558: */
25559: xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25560: }
25561: if (normValue != NULL)
25562: xmlFree(normValue);
25563: }
25564: /*
25565: * Go directly to IDC evaluation.
25566: */
25567: goto eval_idcs;
25568: }
25569: /*
25570: * Validate the value.
25571: */
25572: if (vctxt->value != NULL) {
25573: /*
25574: * Free last computed value; just for safety reasons.
25575: */
25576: xmlSchemaFreeValue(vctxt->value);
25577: vctxt->value = NULL;
25578: }
25579: /*
25580: * Note that the attribute *use* can be unavailable, if
25581: * the attribute was a wild attribute.
25582: */
25583: if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25584: ((iattr->use != NULL) &&
25585: (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25586: fixed = 1;
25587: else
25588: fixed = 0;
25589: /*
25590: * SPEC (cvc-attribute)
25591: * (3) "The item's �normalized value� must be locally �valid�
25592: * with respect to that {type definition} as per
25593: * String Valid (�3.14.4)."
25594: *
25595: * VAL TODO: Do we already have the
25596: * "normalized attribute value" here?
25597: */
25598: if (xpathRes || fixed) {
25599: iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25600: /*
25601: * Request a computed value.
25602: */
25603: res = xmlSchemaVCheckCVCSimpleType(
25604: ACTXT_CAST vctxt,
25605: iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25606: 1, 1, 0);
25607: } else {
25608: res = xmlSchemaVCheckCVCSimpleType(
25609: ACTXT_CAST vctxt,
25610: iattr->node, iattr->typeDef, iattr->value, NULL,
25611: 1, 0, 0);
25612: }
25613:
25614: if (res != 0) {
25615: if (res == -1) {
25616: VERROR_INT("xmlSchemaVAttributesComplex",
25617: "calling xmlSchemaStreamValidateSimpleTypeValue()");
25618: goto internal_error;
25619: }
25620: iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25621: /*
25622: * SPEC PSVI Assessment Outcome (Attribute)
25623: * [validity] = "invalid"
25624: */
25625: goto eval_idcs;
25626: }
25627:
25628: if (fixed) {
25629: /*
25630: * SPEC Attribute Locally Valid (Use) (cvc-au)
25631: * "For an attribute information item to be�valid�
25632: * with respect to an attribute use its *normalized*
25633: * value� must match the *canonical* lexical
25634: * representation of the attribute use's {value
25635: * constraint}value, if it is present and fixed."
25636: *
25637: * VAL TODO: The requirement for the *canonical* value
25638: * will be removed in XML Schema 1.1.
25639: */
25640: /*
25641: * SPEC Attribute Locally Valid (cvc-attribute)
25642: * (4) "The item's *actual* value� must match the *value* of
25643: * the {value constraint}, if it is present and fixed."
25644: */
25645: if (iattr->val == NULL) {
25646: /* VAL TODO: A value was not precomputed. */
25647: TODO
25648: goto eval_idcs;
25649: }
25650: if ((iattr->use != NULL) &&
25651: (iattr->use->defValue != NULL)) {
25652: if (iattr->use->defVal == NULL) {
25653: /* VAL TODO: A default value was not precomputed. */
25654: TODO
25655: goto eval_idcs;
25656: }
25657: iattr->vcValue = iattr->use->defValue;
25658: /*
25659: if (xmlSchemaCompareValuesWhtsp(attr->val,
25660: (xmlSchemaWhitespaceValueType) ws,
25661: attr->use->defVal,
25662: (xmlSchemaWhitespaceValueType) ws) != 0) {
25663: */
25664: if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25665: iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25666: } else {
25667: if (iattr->decl->defVal == NULL) {
25668: /* VAL TODO: A default value was not precomputed. */
25669: TODO
25670: goto eval_idcs;
25671: }
25672: iattr->vcValue = iattr->decl->defValue;
25673: /*
25674: if (xmlSchemaCompareValuesWhtsp(attr->val,
25675: (xmlSchemaWhitespaceValueType) ws,
25676: attrDecl->defVal,
25677: (xmlSchemaWhitespaceValueType) ws) != 0) {
25678: */
25679: if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25680: iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25681: }
25682: /*
25683: * [validity] = "valid"
25684: */
25685: }
25686: eval_idcs:
25687: /*
25688: * Evaluate IDCs.
25689: */
25690: if (xpathRes) {
25691: if (xmlSchemaXPathProcessHistory(vctxt,
25692: vctxt->depth +1) == -1) {
25693: VERROR_INT("xmlSchemaVAttributesComplex",
25694: "calling xmlSchemaXPathEvaluate()");
25695: goto internal_error;
25696: }
25697: } else if (vctxt->xpathStates != NULL)
25698: xmlSchemaXPathPop(vctxt);
25699: }
25700:
25701: /*
25702: * Report errors.
25703: */
25704: for (i = 0; i < vctxt->nbAttrInfos; i++) {
25705: iattr = vctxt->attrInfos[i];
25706: if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25707: (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25708: (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25709: (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25710: continue;
25711: ACTIVATE_ATTRIBUTE(iattr);
25712: switch (iattr->state) {
25713: case XML_SCHEMAS_ATTR_ERR_MISSING: {
25714: xmlChar *str = NULL;
25715: ACTIVATE_ELEM;
25716: xmlSchemaCustomErr(ACTXT_CAST vctxt,
25717: XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25718: "The attribute '%s' is required but missing",
25719: xmlSchemaFormatQName(&str,
25720: iattr->decl->targetNamespace,
25721: iattr->decl->name),
25722: NULL);
25723: FREE_AND_NULL(str)
25724: break;
25725: }
25726: case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25727: VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25728: "The type definition is absent");
25729: break;
25730: case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25731: xmlSchemaCustomErr(ACTXT_CAST vctxt,
25732: XML_SCHEMAV_CVC_AU, NULL, NULL,
25733: "The value '%s' does not match the fixed "
25734: "value constraint '%s'",
25735: iattr->value, iattr->vcValue);
25736: break;
25737: case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25738: VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25739: "No matching global attribute declaration available, but "
25740: "demanded by the strict wildcard");
25741: break;
25742: case XML_SCHEMAS_ATTR_UNKNOWN:
25743: if (iattr->metaType)
25744: break;
25745: /*
25746: * MAYBE VAL TODO: One might report different error messages
25747: * for the following errors.
25748: */
25749: if (type->attributeWildcard == NULL) {
25750: xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25751: XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25752: } else {
25753: xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25754: XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25755: }
25756: break;
25757: default:
25758: break;
25759: }
25760: }
25761:
25762: ACTIVATE_ELEM;
25763: return (0);
25764: internal_error:
25765: ACTIVATE_ELEM;
25766: return (-1);
25767: }
25768:
25769: static int
25770: xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25771: int *skip)
25772: {
25773: xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25774: /*
25775: * The namespace of the element was already identified to be
25776: * matching the wildcard.
25777: */
25778: if ((skip == NULL) || (wild == NULL) ||
25779: (wild->type != XML_SCHEMA_TYPE_ANY)) {
25780: VERROR_INT("xmlSchemaValidateElemWildcard",
25781: "bad arguments");
25782: return (-1);
25783: }
25784: *skip = 0;
25785: if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25786: /*
25787: * URGENT VAL TODO: Either we need to position the stream to the
25788: * next sibling, or walk the whole subtree.
25789: */
25790: *skip = 1;
25791: return (0);
25792: }
25793: {
25794: xmlSchemaElementPtr decl = NULL;
25795:
25796: decl = xmlSchemaGetElem(vctxt->schema,
25797: vctxt->inode->localName, vctxt->inode->nsName);
25798: if (decl != NULL) {
25799: vctxt->inode->decl = decl;
25800: return (0);
25801: }
25802: }
25803: if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25804: /* VAL TODO: Change to proper error code. */
25805: VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25806: "No matching global element declaration available, but "
25807: "demanded by the strict wildcard");
25808: return (vctxt->err);
25809: }
25810: if (vctxt->nbAttrInfos != 0) {
25811: xmlSchemaAttrInfoPtr iattr;
25812: /*
25813: * SPEC Validation Rule: Schema-Validity Assessment (Element)
25814: * (1.2.1.2.1) - (1.2.1.2.3 )
25815: *
25816: * Use the xsi:type attribute for the type definition.
25817: */
25818: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25819: XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25820: if (iattr != NULL) {
25821: if (xmlSchemaProcessXSIType(vctxt, iattr,
25822: &(vctxt->inode->typeDef), NULL) == -1) {
25823: VERROR_INT("xmlSchemaValidateElemWildcard",
25824: "calling xmlSchemaProcessXSIType() to "
25825: "process the attribute 'xsi:nil'");
25826: return (-1);
25827: }
25828: /*
25829: * Don't return an error on purpose.
25830: */
25831: return (0);
25832: }
25833: }
25834: /*
25835: * SPEC Validation Rule: Schema-Validity Assessment (Element)
25836: *
25837: * Fallback to "anyType".
25838: */
25839: vctxt->inode->typeDef =
25840: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25841: return (0);
25842: }
25843:
25844: /*
25845: * xmlSchemaCheckCOSValidDefault:
25846: *
25847: * This will be called if: not nilled, no content and a default/fixed
25848: * value is provided.
25849: */
25850:
25851: static int
25852: xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25853: const xmlChar *value,
25854: xmlSchemaValPtr *val)
25855: {
25856: int ret = 0;
25857: xmlSchemaNodeInfoPtr inode = vctxt->inode;
25858:
25859: /*
25860: * cos-valid-default:
25861: * Schema Component Constraint: Element Default Valid (Immediate)
25862: * For a string to be a valid default with respect to a type
25863: * definition the appropriate case among the following must be true:
25864: */
25865: if WXS_IS_COMPLEX(inode->typeDef) {
25866: /*
25867: * Complex type.
25868: *
25869: * SPEC (2.1) "its {content type} must be a simple type definition
25870: * or mixed."
25871: * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25872: * type}'s particle must be �emptiable� as defined by
25873: * Particle Emptiable (�3.9.6)."
25874: */
25875: if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25876: ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25877: (! WXS_EMPTIABLE(inode->typeDef)))) {
25878: ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25879: /* NOTE that this covers (2.2.2) as well. */
25880: VERROR(ret, NULL,
25881: "For a string to be a valid default, the type definition "
25882: "must be a simple type or a complex type with simple content "
25883: "or mixed content and a particle emptiable");
25884: return(ret);
25885: }
25886: }
25887: /*
25888: * 1 If the type definition is a simple type definition, then the string
25889: * must be �valid� with respect to that definition as defined by String
25890: * Valid (�3.14.4).
25891: *
25892: * AND
25893: *
25894: * 2.2.1 If the {content type} is a simple type definition, then the
25895: * string must be �valid� with respect to that simple type definition
25896: * as defined by String Valid (�3.14.4).
25897: */
25898: if (WXS_IS_SIMPLE(inode->typeDef)) {
25899:
25900: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25901: NULL, inode->typeDef, value, val, 1, 1, 0);
25902:
25903: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25904:
25905: ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25906: NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25907: }
25908: if (ret < 0) {
25909: VERROR_INT("xmlSchemaCheckCOSValidDefault",
25910: "calling xmlSchemaVCheckCVCSimpleType()");
25911: }
25912: return (ret);
25913: }
25914:
25915: static void
25916: xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25917: const xmlChar * name ATTRIBUTE_UNUSED,
25918: xmlSchemaElementPtr item,
25919: xmlSchemaNodeInfoPtr inode)
25920: {
25921: inode->decl = item;
25922: #ifdef DEBUG_CONTENT
25923: {
25924: xmlChar *str = NULL;
25925:
25926: if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25927: xmlGenericError(xmlGenericErrorContext,
25928: "AUTOMATON callback for '%s' [declaration]\n",
25929: xmlSchemaFormatQName(&str,
25930: inode->localName, inode->nsName));
25931: } else {
25932: xmlGenericError(xmlGenericErrorContext,
25933: "AUTOMATON callback for '%s' [wildcard]\n",
25934: xmlSchemaFormatQName(&str,
25935: inode->localName, inode->nsName));
25936:
25937: }
25938: FREE_AND_NULL(str)
25939: }
25940: #endif
25941: }
25942:
25943: static int
25944: xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25945: {
25946: vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25947: if (vctxt->inode == NULL) {
25948: VERROR_INT("xmlSchemaValidatorPushElem",
25949: "calling xmlSchemaGetFreshElemInfo()");
25950: return (-1);
25951: }
25952: vctxt->nbAttrInfos = 0;
25953: return (0);
25954: }
25955:
25956: static int
25957: xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25958: xmlSchemaNodeInfoPtr inode,
25959: xmlSchemaTypePtr type,
25960: const xmlChar *value)
25961: {
25962: if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25963: return (xmlSchemaVCheckCVCSimpleType(
25964: ACTXT_CAST vctxt, NULL,
25965: type, value, &(inode->val), 1, 1, 0));
25966: else
25967: return (xmlSchemaVCheckCVCSimpleType(
25968: ACTXT_CAST vctxt, NULL,
25969: type, value, NULL, 1, 0, 0));
25970: }
25971:
25972:
25973:
25974: /*
25975: * Process END of element.
25976: */
25977: static int
25978: xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25979: {
25980: int ret = 0;
25981: xmlSchemaNodeInfoPtr inode = vctxt->inode;
25982:
25983: if (vctxt->nbAttrInfos != 0)
25984: xmlSchemaClearAttrInfos(vctxt);
25985: if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25986: /*
25987: * This element was not expected;
25988: * we will not validate child elements of broken parents.
25989: * Skip validation of all content of the parent.
25990: */
25991: vctxt->skipDepth = vctxt->depth -1;
25992: goto end_elem;
25993: }
25994: if ((inode->typeDef == NULL) ||
25995: (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25996: /*
25997: * 1. the type definition might be missing if the element was
25998: * error prone
25999: * 2. it might be abstract.
26000: */
26001: goto end_elem;
26002: }
26003: /*
26004: * Check the content model.
26005: */
26006: if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26007: (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26008:
26009: /*
26010: * Workaround for "anyType".
26011: */
26012: if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26013: goto character_content;
26014:
26015: if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26016: xmlChar *values[10];
26017: int terminal, nbval = 10, nbneg;
26018:
26019: if (inode->regexCtxt == NULL) {
26020: /*
26021: * Create the regex context.
26022: */
26023: inode->regexCtxt =
26024: xmlRegNewExecCtxt(inode->typeDef->contModel,
26025: (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26026: vctxt);
26027: if (inode->regexCtxt == NULL) {
26028: VERROR_INT("xmlSchemaValidatorPopElem",
26029: "failed to create a regex context");
26030: goto internal_error;
26031: }
26032: #ifdef DEBUG_AUTOMATA
26033: xmlGenericError(xmlGenericErrorContext,
26034: "AUTOMATON create on '%s'\n", inode->localName);
26035: #endif
26036: }
26037: /*
26038: * Get hold of the still expected content, since a further
26039: * call to xmlRegExecPushString() will loose this information.
26040: */
26041: xmlRegExecNextValues(inode->regexCtxt,
26042: &nbval, &nbneg, &values[0], &terminal);
26043: ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26044: if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26045: /*
26046: * Still missing something.
26047: */
26048: ret = 1;
26049: inode->flags |=
26050: XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26051: xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26052: XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26053: "Missing child element(s)",
26054: nbval, nbneg, values);
26055: #ifdef DEBUG_AUTOMATA
26056: xmlGenericError(xmlGenericErrorContext,
26057: "AUTOMATON missing ERROR on '%s'\n",
26058: inode->localName);
26059: #endif
26060: } else {
26061: /*
26062: * Content model is satisfied.
26063: */
26064: ret = 0;
26065: #ifdef DEBUG_AUTOMATA
26066: xmlGenericError(xmlGenericErrorContext,
26067: "AUTOMATON succeeded on '%s'\n",
26068: inode->localName);
26069: #endif
26070: }
26071:
26072: }
26073: }
26074: if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26075: goto end_elem;
26076:
26077: character_content:
26078:
26079: if (vctxt->value != NULL) {
26080: xmlSchemaFreeValue(vctxt->value);
26081: vctxt->value = NULL;
26082: }
26083: /*
26084: * Check character content.
26085: */
26086: if (inode->decl == NULL) {
26087: /*
26088: * Speedup if no declaration exists.
26089: */
26090: if (WXS_IS_SIMPLE(inode->typeDef)) {
26091: ret = xmlSchemaVCheckINodeDataType(vctxt,
26092: inode, inode->typeDef, inode->value);
26093: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26094: ret = xmlSchemaVCheckINodeDataType(vctxt,
26095: inode, inode->typeDef->contentTypeDef,
26096: inode->value);
26097: }
26098: if (ret < 0) {
26099: VERROR_INT("xmlSchemaValidatorPopElem",
26100: "calling xmlSchemaVCheckCVCSimpleType()");
26101: goto internal_error;
26102: }
26103: goto end_elem;
26104: }
26105: /*
26106: * cvc-elt (3.3.4) : 5
26107: * The appropriate case among the following must be true:
26108: */
26109: /*
26110: * cvc-elt (3.3.4) : 5.1
26111: * If the declaration has a {value constraint},
26112: * the item has neither element nor character [children] and
26113: * clause 3.2 has not applied, then all of the following must be true:
26114: */
26115: if ((inode->decl->value != NULL) &&
26116: (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26117: (! INODE_NILLED(inode))) {
26118: /*
26119: * cvc-elt (3.3.4) : 5.1.1
26120: * If the �actual type definition� is a �local type definition�
26121: * then the canonical lexical representation of the {value constraint}
26122: * value must be a valid default for the �actual type definition� as
26123: * defined in Element Default Valid (Immediate) (�3.3.6).
26124: */
26125: /*
26126: * NOTE: 'local' above means types acquired by xsi:type.
26127: * NOTE: Although the *canonical* value is stated, it is not
26128: * relevant if canonical or not. Additionally XML Schema 1.1
26129: * will removed this requirement as well.
26130: */
26131: if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26132:
26133: ret = xmlSchemaCheckCOSValidDefault(vctxt,
26134: inode->decl->value, &(inode->val));
26135: if (ret != 0) {
26136: if (ret < 0) {
26137: VERROR_INT("xmlSchemaValidatorPopElem",
26138: "calling xmlSchemaCheckCOSValidDefault()");
26139: goto internal_error;
26140: }
26141: goto end_elem;
26142: }
26143: /*
26144: * Stop here, to avoid redundant validation of the value
26145: * (see following).
26146: */
26147: goto default_psvi;
26148: }
26149: /*
26150: * cvc-elt (3.3.4) : 5.1.2
26151: * The element information item with the canonical lexical
26152: * representation of the {value constraint} value used as its
26153: * �normalized value� must be �valid� with respect to the
26154: * �actual type definition� as defined by Element Locally Valid (Type)
26155: * (�3.3.4).
26156: */
26157: if (WXS_IS_SIMPLE(inode->typeDef)) {
26158: ret = xmlSchemaVCheckINodeDataType(vctxt,
26159: inode, inode->typeDef, inode->decl->value);
26160: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26161: ret = xmlSchemaVCheckINodeDataType(vctxt,
26162: inode, inode->typeDef->contentTypeDef,
26163: inode->decl->value);
26164: }
26165: if (ret != 0) {
26166: if (ret < 0) {
26167: VERROR_INT("xmlSchemaValidatorPopElem",
26168: "calling xmlSchemaVCheckCVCSimpleType()");
26169: goto internal_error;
26170: }
26171: goto end_elem;
26172: }
26173:
26174: default_psvi:
26175: /*
26176: * PSVI: Create a text node on the instance element.
26177: */
26178: if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26179: (inode->node != NULL)) {
26180: xmlNodePtr textChild;
26181: xmlChar *normValue;
26182: /*
26183: * VAL TODO: Normalize the value.
26184: */
26185: normValue = xmlSchemaNormalizeValue(inode->typeDef,
26186: inode->decl->value);
26187: if (normValue != NULL) {
26188: textChild = xmlNewText(BAD_CAST normValue);
26189: xmlFree(normValue);
26190: } else
26191: textChild = xmlNewText(inode->decl->value);
26192: if (textChild == NULL) {
26193: VERROR_INT("xmlSchemaValidatorPopElem",
26194: "calling xmlNewText()");
26195: goto internal_error;
26196: } else
26197: xmlAddChild(inode->node, textChild);
26198: }
26199:
26200: } else if (! INODE_NILLED(inode)) {
26201: /*
26202: * 5.2.1 The element information item must be �valid� with respect
26203: * to the �actual type definition� as defined by Element Locally
26204: * Valid (Type) (�3.3.4).
26205: */
26206: if (WXS_IS_SIMPLE(inode->typeDef)) {
26207: /*
26208: * SPEC (cvc-type) (3.1)
26209: * "If the type definition is a simple type definition, ..."
26210: * (3.1.3) "If clause 3.2 of Element Locally Valid
26211: * (Element) (�3.3.4) did not apply, then the �normalized value�
26212: * must be �valid� with respect to the type definition as defined
26213: * by String Valid (�3.14.4).
26214: */
26215: ret = xmlSchemaVCheckINodeDataType(vctxt,
26216: inode, inode->typeDef, inode->value);
26217: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26218: /*
26219: * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26220: * definition, then the element information item must be
26221: * �valid� with respect to the type definition as per
26222: * Element Locally Valid (Complex Type) (�3.4.4);"
26223: *
26224: * SPEC (cvc-complex-type) (2.2)
26225: * "If the {content type} is a simple type definition, ...
26226: * the �normalized value� of the element information item is
26227: * �valid� with respect to that simple type definition as
26228: * defined by String Valid (�3.14.4)."
26229: */
26230: ret = xmlSchemaVCheckINodeDataType(vctxt,
26231: inode, inode->typeDef->contentTypeDef, inode->value);
26232: }
26233: if (ret != 0) {
26234: if (ret < 0) {
26235: VERROR_INT("xmlSchemaValidatorPopElem",
26236: "calling xmlSchemaVCheckCVCSimpleType()");
26237: goto internal_error;
26238: }
26239: goto end_elem;
26240: }
26241: /*
26242: * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26243: * not applied, all of the following must be true:
26244: */
26245: if ((inode->decl->value != NULL) &&
26246: (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26247:
26248: /*
26249: * TODO: We will need a computed value, when comparison is
26250: * done on computed values.
26251: */
26252: /*
26253: * 5.2.2.1 The element information item must have no element
26254: * information item [children].
26255: */
26256: if (inode->flags &
26257: XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26258: ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26259: VERROR(ret, NULL,
26260: "The content must not containt element nodes since "
26261: "there is a fixed value constraint");
26262: goto end_elem;
26263: } else {
26264: /*
26265: * 5.2.2.2 The appropriate case among the following must
26266: * be true:
26267: */
26268: if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26269: /*
26270: * 5.2.2.2.1 If the {content type} of the �actual type
26271: * definition� is mixed, then the *initial value* of the
26272: * item must match the canonical lexical representation
26273: * of the {value constraint} value.
26274: *
26275: * ... the *initial value* of an element information
26276: * item is the string composed of, in order, the
26277: * [character code] of each character information item in
26278: * the [children] of that element information item.
26279: */
26280: if (! xmlStrEqual(inode->value, inode->decl->value)){
26281: /*
26282: * VAL TODO: Report invalid & expected values as well.
26283: * VAL TODO: Implement the canonical stuff.
26284: */
26285: ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26286: xmlSchemaCustomErr(ACTXT_CAST vctxt,
26287: ret, NULL, NULL,
26288: "The initial value '%s' does not match the fixed "
26289: "value constraint '%s'",
26290: inode->value, inode->decl->value);
26291: goto end_elem;
26292: }
26293: } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26294: /*
26295: * 5.2.2.2.2 If the {content type} of the �actual type
26296: * definition� is a simple type definition, then the
26297: * *actual value* of the item must match the canonical
26298: * lexical representation of the {value constraint} value.
26299: */
26300: /*
26301: * VAL TODO: *actual value* is the normalized value, impl.
26302: * this.
26303: * VAL TODO: Report invalid & expected values as well.
26304: * VAL TODO: Implement a comparison with the computed values.
26305: */
26306: if (! xmlStrEqual(inode->value,
26307: inode->decl->value)) {
26308: ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26309: xmlSchemaCustomErr(ACTXT_CAST vctxt,
26310: ret, NULL, NULL,
26311: "The actual value '%s' does not match the fixed "
26312: "value constraint '%s'",
26313: inode->value,
26314: inode->decl->value);
26315: goto end_elem;
26316: }
26317: }
26318: }
26319: }
26320: }
26321:
26322: end_elem:
26323: if (vctxt->depth < 0) {
26324: /* TODO: raise error? */
26325: return (0);
26326: }
26327: if (vctxt->depth == vctxt->skipDepth)
26328: vctxt->skipDepth = -1;
26329: /*
26330: * Evaluate the history of XPath state objects.
26331: */
26332: if (inode->appliedXPath &&
26333: (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26334: goto internal_error;
26335: /*
26336: * MAYBE TODO:
26337: * SPEC (6) "The element information item must be �valid� with
26338: * respect to each of the {identity-constraint definitions} as per
26339: * Identity-constraint Satisfied (�3.11.4)."
26340: */
26341: /*
26342: * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26343: * need to be built in any case.
26344: * We will currently build IDC node-tables and bubble them only if
26345: * keyrefs do exist.
26346: */
26347:
26348: /*
26349: * Add the current IDC target-nodes to the IDC node-tables.
26350: */
26351: if ((inode->idcMatchers != NULL) &&
26352: (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26353: {
26354: if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26355: goto internal_error;
26356: }
26357: /*
26358: * Validate IDC keyrefs.
26359: */
26360: if (vctxt->inode->hasKeyrefs)
26361: if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26362: goto internal_error;
26363: /*
26364: * Merge/free the IDC table.
26365: */
26366: if (inode->idcTable != NULL) {
26367: #ifdef DEBUG_IDC_NODE_TABLE
26368: xmlSchemaDebugDumpIDCTable(stdout,
26369: inode->nsName,
26370: inode->localName,
26371: inode->idcTable);
26372: #endif
26373: if ((vctxt->depth > 0) &&
26374: (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26375: {
26376: /*
26377: * Merge the IDC node table with the table of the parent node.
26378: */
26379: if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26380: goto internal_error;
26381: }
26382: }
26383: /*
26384: * Clear the current ielem.
26385: * VAL TODO: Don't free the PSVI IDC tables if they are
26386: * requested for the PSVI.
26387: */
26388: xmlSchemaClearElemInfo(vctxt, inode);
26389: /*
26390: * Skip further processing if we are on the validation root.
26391: */
26392: if (vctxt->depth == 0) {
26393: vctxt->depth--;
26394: vctxt->inode = NULL;
26395: return (0);
26396: }
26397: /*
26398: * Reset the keyrefDepth if needed.
26399: */
26400: if (vctxt->aidcs != NULL) {
26401: xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26402: do {
26403: if (aidc->keyrefDepth == vctxt->depth) {
26404: /*
26405: * A 'keyrefDepth' of a key/unique IDC matches the current
26406: * depth, this means that we are leaving the scope of the
26407: * top-most keyref IDC which refers to this IDC.
26408: */
26409: aidc->keyrefDepth = -1;
26410: }
26411: aidc = aidc->next;
26412: } while (aidc != NULL);
26413: }
26414: vctxt->depth--;
26415: vctxt->inode = vctxt->elemInfos[vctxt->depth];
26416: /*
26417: * VAL TODO: 7 If the element information item is the �validation root�, it must be
26418: * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26419: */
26420: return (ret);
26421:
26422: internal_error:
26423: vctxt->err = -1;
26424: return (-1);
26425: }
26426:
26427: /*
26428: * 3.4.4 Complex Type Definition Validation Rules
26429: * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26430: */
26431: static int
26432: xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26433: {
26434: xmlSchemaNodeInfoPtr pielem;
26435: xmlSchemaTypePtr ptype;
26436: int ret = 0;
26437:
26438: if (vctxt->depth <= 0) {
26439: VERROR_INT("xmlSchemaValidateChildElem",
26440: "not intended for the validation root");
26441: return (-1);
26442: }
26443: pielem = vctxt->elemInfos[vctxt->depth -1];
26444: if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26445: pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26446: /*
26447: * Handle 'nilled' elements.
26448: */
26449: if (INODE_NILLED(pielem)) {
26450: /*
26451: * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26452: */
26453: ACTIVATE_PARENT_ELEM;
26454: ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26455: VERROR(ret, NULL,
26456: "Neither character nor element content is allowed, "
26457: "because the element was 'nilled'");
26458: ACTIVATE_ELEM;
26459: goto unexpected_elem;
26460: }
26461:
26462: ptype = pielem->typeDef;
26463:
26464: if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26465: /*
26466: * Workaround for "anyType": we have currently no content model
26467: * assigned for "anyType", so handle it explicitely.
26468: * "anyType" has an unbounded, lax "any" wildcard.
26469: */
26470: vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26471: vctxt->inode->localName,
26472: vctxt->inode->nsName);
26473:
26474: if (vctxt->inode->decl == NULL) {
26475: xmlSchemaAttrInfoPtr iattr;
26476: /*
26477: * Process "xsi:type".
26478: * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26479: */
26480: iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26481: XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26482: if (iattr != NULL) {
26483: ret = xmlSchemaProcessXSIType(vctxt, iattr,
26484: &(vctxt->inode->typeDef), NULL);
26485: if (ret != 0) {
26486: if (ret == -1) {
26487: VERROR_INT("xmlSchemaValidateChildElem",
26488: "calling xmlSchemaProcessXSIType() to "
26489: "process the attribute 'xsi:nil'");
26490: return (-1);
26491: }
26492: return (ret);
26493: }
26494: } else {
26495: /*
26496: * Fallback to "anyType".
26497: *
26498: * SPEC (cvc-assess-elt)
26499: * "If the item cannot be �strictly assessed�, [...]
26500: * an element information item's schema validity may be laxly
26501: * assessed if its �context-determined declaration� is not
26502: * skip by �validating� with respect to the �ur-type
26503: * definition� as per Element Locally Valid (Type) (�3.3.4)."
26504: */
26505: vctxt->inode->typeDef =
26506: xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26507: }
26508: }
26509: return (0);
26510: }
26511:
26512: switch (ptype->contentType) {
26513: case XML_SCHEMA_CONTENT_EMPTY:
26514: /*
26515: * SPEC (2.1) "If the {content type} is empty, then the
26516: * element information item has no character or element
26517: * information item [children]."
26518: */
26519: ACTIVATE_PARENT_ELEM
26520: ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26521: VERROR(ret, NULL,
26522: "Element content is not allowed, "
26523: "because the content type is empty");
26524: ACTIVATE_ELEM
26525: goto unexpected_elem;
26526: break;
26527:
26528: case XML_SCHEMA_CONTENT_MIXED:
26529: case XML_SCHEMA_CONTENT_ELEMENTS: {
26530: xmlRegExecCtxtPtr regexCtxt;
26531: xmlChar *values[10];
26532: int terminal, nbval = 10, nbneg;
26533:
26534: /* VAL TODO: Optimized "anyType" validation.*/
26535:
26536: if (ptype->contModel == NULL) {
26537: VERROR_INT("xmlSchemaValidateChildElem",
26538: "type has elem content but no content model");
26539: return (-1);
26540: }
26541: /*
26542: * Safety belf for evaluation if the cont. model was already
26543: * examined to be invalid.
26544: */
26545: if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26546: VERROR_INT("xmlSchemaValidateChildElem",
26547: "validating elem, but elem content is already invalid");
26548: return (-1);
26549: }
26550:
26551: regexCtxt = pielem->regexCtxt;
26552: if (regexCtxt == NULL) {
26553: /*
26554: * Create the regex context.
26555: */
26556: regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26557: (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26558: vctxt);
26559: if (regexCtxt == NULL) {
26560: VERROR_INT("xmlSchemaValidateChildElem",
26561: "failed to create a regex context");
26562: return (-1);
26563: }
26564: pielem->regexCtxt = regexCtxt;
26565: #ifdef DEBUG_AUTOMATA
26566: xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26567: pielem->localName);
26568: #endif
26569: }
26570:
26571: /*
26572: * SPEC (2.4) "If the {content type} is element-only or mixed,
26573: * then the sequence of the element information item's
26574: * element information item [children], if any, taken in
26575: * order, is �valid� with respect to the {content type}'s
26576: * particle, as defined in Element Sequence Locally Valid
26577: * (Particle) (�3.9.4)."
26578: */
26579: ret = xmlRegExecPushString2(regexCtxt,
26580: vctxt->inode->localName,
26581: vctxt->inode->nsName,
26582: vctxt->inode);
26583: #ifdef DEBUG_AUTOMATA
26584: if (ret < 0)
26585: xmlGenericError(xmlGenericErrorContext,
26586: "AUTOMATON push ERROR for '%s' on '%s'\n",
26587: vctxt->inode->localName, pielem->localName);
26588: else
26589: xmlGenericError(xmlGenericErrorContext,
26590: "AUTOMATON push OK for '%s' on '%s'\n",
26591: vctxt->inode->localName, pielem->localName);
26592: #endif
26593: if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26594: VERROR_INT("xmlSchemaValidateChildElem",
26595: "calling xmlRegExecPushString2()");
26596: return (-1);
26597: }
26598: if (ret < 0) {
26599: xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26600: &values[0], &terminal);
26601: xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26602: XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26603: "This element is not expected",
26604: nbval, nbneg, values);
26605: ret = vctxt->err;
26606: goto unexpected_elem;
26607: } else
26608: ret = 0;
26609: }
26610: break;
26611: case XML_SCHEMA_CONTENT_SIMPLE:
26612: case XML_SCHEMA_CONTENT_BASIC:
26613: ACTIVATE_PARENT_ELEM
26614: if (WXS_IS_COMPLEX(ptype)) {
26615: /*
26616: * SPEC (cvc-complex-type) (2.2)
26617: * "If the {content type} is a simple type definition, then
26618: * the element information item has no element information
26619: * item [children], ..."
26620: */
26621: ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26622: VERROR(ret, NULL, "Element content is not allowed, "
26623: "because the content type is a simple type definition");
26624: } else {
26625: /*
26626: * SPEC (cvc-type) (3.1.2) "The element information item must
26627: * have no element information item [children]."
26628: */
26629: ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26630: VERROR(ret, NULL, "Element content is not allowed, "
26631: "because the type definition is simple");
26632: }
26633: ACTIVATE_ELEM
26634: ret = vctxt->err;
26635: goto unexpected_elem;
26636: break;
26637:
26638: default:
26639: break;
26640: }
26641: return (ret);
26642: unexpected_elem:
26643: /*
26644: * Pop this element and set the skipDepth to skip
26645: * all further content of the parent element.
26646: */
26647: vctxt->skipDepth = vctxt->depth;
26648: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26649: pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26650: return (ret);
26651: }
26652:
26653: #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26654: #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26655: #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26656:
26657: static int
26658: xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26659: int nodeType, const xmlChar *value, int len,
26660: int mode, int *consumed)
26661: {
26662: /*
26663: * Unfortunately we have to duplicate the text sometimes.
26664: * OPTIMIZE: Maybe we could skip it, if:
26665: * 1. content type is simple
26666: * 2. whitespace is "collapse"
26667: * 3. it consists of whitespace only
26668: *
26669: * Process character content.
26670: */
26671: if (consumed != NULL)
26672: *consumed = 0;
26673: if (INODE_NILLED(vctxt->inode)) {
26674: /*
26675: * SPEC cvc-elt (3.3.4 - 3.2.1)
26676: * "The element information item must have no character or
26677: * element information item [children]."
26678: */
26679: VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26680: "Neither character nor element content is allowed "
26681: "because the element is 'nilled'");
26682: return (vctxt->err);
26683: }
26684: /*
26685: * SPEC (2.1) "If the {content type} is empty, then the
26686: * element information item has no character or element
26687: * information item [children]."
26688: */
26689: if (vctxt->inode->typeDef->contentType ==
26690: XML_SCHEMA_CONTENT_EMPTY) {
26691: VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26692: "Character content is not allowed, "
26693: "because the content type is empty");
26694: return (vctxt->err);
26695: }
26696:
26697: if (vctxt->inode->typeDef->contentType ==
26698: XML_SCHEMA_CONTENT_ELEMENTS) {
26699: if ((nodeType != XML_TEXT_NODE) ||
26700: (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26701: /*
26702: * SPEC cvc-complex-type (2.3)
26703: * "If the {content type} is element-only, then the
26704: * element information item has no character information
26705: * item [children] other than those whose [character
26706: * code] is defined as a white space in [XML 1.0 (Second
26707: * Edition)]."
26708: */
26709: VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26710: "Character content other than whitespace is not allowed "
26711: "because the content type is 'element-only'");
26712: return (vctxt->err);
26713: }
26714: return (0);
26715: }
26716:
26717: if ((value == NULL) || (value[0] == 0))
26718: return (0);
26719: /*
26720: * Save the value.
26721: * NOTE that even if the content type is *mixed*, we need the
26722: * *initial value* for default/fixed value constraints.
26723: */
26724: if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26725: ((vctxt->inode->decl == NULL) ||
26726: (vctxt->inode->decl->value == NULL)))
26727: return (0);
26728:
26729: if (vctxt->inode->value == NULL) {
26730: /*
26731: * Set the value.
26732: */
26733: switch (mode) {
26734: case XML_SCHEMA_PUSH_TEXT_PERSIST:
26735: /*
26736: * When working on a tree.
26737: */
26738: vctxt->inode->value = value;
26739: break;
26740: case XML_SCHEMA_PUSH_TEXT_CREATED:
26741: /*
26742: * When working with the reader.
26743: * The value will be freed by the element info.
26744: */
26745: vctxt->inode->value = value;
26746: if (consumed != NULL)
26747: *consumed = 1;
26748: vctxt->inode->flags |=
26749: XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26750: break;
26751: case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26752: /*
26753: * When working with SAX.
26754: * The value will be freed by the element info.
26755: */
26756: if (len != -1)
26757: vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26758: else
26759: vctxt->inode->value = BAD_CAST xmlStrdup(value);
26760: vctxt->inode->flags |=
26761: XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26762: break;
26763: default:
26764: break;
26765: }
26766: } else {
26767: if (len < 0)
26768: len = xmlStrlen(value);
26769: /*
26770: * Concat the value.
26771: */
26772: if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26773: vctxt->inode->value = BAD_CAST xmlStrncat(
26774: (xmlChar *) vctxt->inode->value, value, len);
26775: } else {
26776: vctxt->inode->value =
26777: BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26778: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26779: }
26780: }
26781:
26782: return (0);
26783: }
26784:
26785: static int
26786: xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26787: {
26788: int ret = 0;
26789:
26790: if ((vctxt->skipDepth != -1) &&
26791: (vctxt->depth >= vctxt->skipDepth)) {
26792: VERROR_INT("xmlSchemaValidateElem",
26793: "in skip-state");
26794: goto internal_error;
26795: }
26796: if (vctxt->xsiAssemble) {
26797: /*
26798: * We will stop validation if there was an error during
26799: * dynamic schema construction.
26800: * Note that we simply set @skipDepth to 0, this could
26801: * mean that a streaming document via SAX would be
26802: * still read to the end but it won't be validated any more.
26803: * TODO: If we are sure how to stop the validation at once
26804: * for all input scenarios, then this should be changed to
26805: * instantly stop the validation.
26806: */
26807: ret = xmlSchemaAssembleByXSI(vctxt);
26808: if (ret != 0) {
26809: if (ret == -1)
26810: goto internal_error;
26811: vctxt->skipDepth = 0;
26812: return(ret);
26813: }
26814: /*
26815: * Augment the IDC definitions for the main schema and all imported ones
26816: * NOTE: main schema is the first in the imported list
26817: */
26818: xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
26819: }
26820: if (vctxt->depth > 0) {
26821: /*
26822: * Validate this element against the content model
26823: * of the parent.
26824: */
26825: ret = xmlSchemaValidateChildElem(vctxt);
26826: if (ret != 0) {
26827: if (ret < 0) {
26828: VERROR_INT("xmlSchemaValidateElem",
26829: "calling xmlSchemaStreamValidateChildElement()");
26830: goto internal_error;
26831: }
26832: goto exit;
26833: }
26834: if (vctxt->depth == vctxt->skipDepth)
26835: goto exit;
26836: if ((vctxt->inode->decl == NULL) &&
26837: (vctxt->inode->typeDef == NULL)) {
26838: VERROR_INT("xmlSchemaValidateElem",
26839: "the child element was valid but neither the "
26840: "declaration nor the type was set");
26841: goto internal_error;
26842: }
26843: } else {
26844: /*
26845: * Get the declaration of the validation root.
26846: */
26847: vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26848: vctxt->inode->localName,
26849: vctxt->inode->nsName);
26850: if (vctxt->inode->decl == NULL) {
26851: ret = XML_SCHEMAV_CVC_ELT_1;
26852: VERROR(ret, NULL,
26853: "No matching global declaration available "
26854: "for the validation root");
26855: goto exit;
26856: }
26857: }
26858:
26859: if (vctxt->inode->decl == NULL)
26860: goto type_validation;
26861:
26862: if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26863: int skip;
26864: /*
26865: * Wildcards.
26866: */
26867: ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26868: if (ret != 0) {
26869: if (ret < 0) {
26870: VERROR_INT("xmlSchemaValidateElem",
26871: "calling xmlSchemaValidateElemWildcard()");
26872: goto internal_error;
26873: }
26874: goto exit;
26875: }
26876: if (skip) {
26877: vctxt->skipDepth = vctxt->depth;
26878: goto exit;
26879: }
26880: /*
26881: * The declaration might be set by the wildcard validation,
26882: * when the processContents is "lax" or "strict".
26883: */
26884: if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26885: /*
26886: * Clear the "decl" field to not confuse further processing.
26887: */
26888: vctxt->inode->decl = NULL;
26889: goto type_validation;
26890: }
26891: }
26892: /*
26893: * Validate against the declaration.
26894: */
26895: ret = xmlSchemaValidateElemDecl(vctxt);
26896: if (ret != 0) {
26897: if (ret < 0) {
26898: VERROR_INT("xmlSchemaValidateElem",
26899: "calling xmlSchemaValidateElemDecl()");
26900: goto internal_error;
26901: }
26902: goto exit;
26903: }
26904: /*
26905: * Validate against the type definition.
26906: */
26907: type_validation:
26908:
26909: if (vctxt->inode->typeDef == NULL) {
26910: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26911: ret = XML_SCHEMAV_CVC_TYPE_1;
26912: VERROR(ret, NULL,
26913: "The type definition is absent");
26914: goto exit;
26915: }
26916: if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26917: vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26918: ret = XML_SCHEMAV_CVC_TYPE_2;
26919: VERROR(ret, NULL,
26920: "The type definition is abstract");
26921: goto exit;
26922: }
26923: /*
26924: * Evaluate IDCs. Do it here, since new IDC matchers are registered
26925: * during validation against the declaration. This must be done
26926: * _before_ attribute validation.
26927: */
26928: if (vctxt->xpathStates != NULL) {
26929: ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26930: vctxt->inode->appliedXPath = 1;
26931: if (ret == -1) {
26932: VERROR_INT("xmlSchemaValidateElem",
26933: "calling xmlSchemaXPathEvaluate()");
26934: goto internal_error;
26935: }
26936: }
26937: /*
26938: * Validate attributes.
26939: */
26940: if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26941: if ((vctxt->nbAttrInfos != 0) ||
26942: (vctxt->inode->typeDef->attrUses != NULL)) {
26943:
26944: ret = xmlSchemaVAttributesComplex(vctxt);
26945: }
26946: } else if (vctxt->nbAttrInfos != 0) {
26947:
26948: ret = xmlSchemaVAttributesSimple(vctxt);
26949: }
26950: /*
26951: * Clear registered attributes.
26952: */
26953: if (vctxt->nbAttrInfos != 0)
26954: xmlSchemaClearAttrInfos(vctxt);
26955: if (ret == -1) {
26956: VERROR_INT("xmlSchemaValidateElem",
26957: "calling attributes validation");
26958: goto internal_error;
26959: }
26960: /*
26961: * Don't return an error if attributes are invalid on purpose.
26962: */
26963: ret = 0;
26964:
26965: exit:
26966: if (ret != 0)
26967: vctxt->skipDepth = vctxt->depth;
26968: return (ret);
26969: internal_error:
26970: return (-1);
26971: }
26972:
26973: #ifdef XML_SCHEMA_READER_ENABLED
26974: static int
26975: xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26976: {
26977: const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26978: int depth, nodeType, ret = 0, consumed;
26979: xmlSchemaNodeInfoPtr ielem;
26980:
26981: vctxt->depth = -1;
26982: ret = xmlTextReaderRead(vctxt->reader);
26983: /*
26984: * Move to the document element.
26985: */
26986: while (ret == 1) {
26987: nodeType = xmlTextReaderNodeType(vctxt->reader);
26988: if (nodeType == XML_ELEMENT_NODE)
26989: goto root_found;
26990: ret = xmlTextReaderRead(vctxt->reader);
26991: }
26992: goto exit;
26993:
26994: root_found:
26995:
26996: do {
26997: depth = xmlTextReaderDepth(vctxt->reader);
26998: nodeType = xmlTextReaderNodeType(vctxt->reader);
26999:
27000: if (nodeType == XML_ELEMENT_NODE) {
27001:
27002: vctxt->depth++;
27003: if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27004: VERROR_INT("xmlSchemaVReaderWalk",
27005: "calling xmlSchemaValidatorPushElem()");
27006: goto internal_error;
27007: }
27008: ielem = vctxt->inode;
27009: ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27010: ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27011: ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27012: /*
27013: * Is the element empty?
27014: */
27015: ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27016: if (ret == -1) {
27017: VERROR_INT("xmlSchemaVReaderWalk",
27018: "calling xmlTextReaderIsEmptyElement()");
27019: goto internal_error;
27020: }
27021: if (ret) {
27022: ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27023: }
27024: /*
27025: * Register attributes.
27026: */
27027: vctxt->nbAttrInfos = 0;
27028: ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27029: if (ret == -1) {
27030: VERROR_INT("xmlSchemaVReaderWalk",
27031: "calling xmlTextReaderMoveToFirstAttribute()");
27032: goto internal_error;
27033: }
27034: if (ret == 1) {
27035: do {
27036: /*
27037: * VAL TODO: How do we know that the reader works on a
27038: * node tree, to be able to pass a node here?
27039: */
27040: if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27041: (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27042: xmlTextReaderNamespaceUri(vctxt->reader), 1,
27043: xmlTextReaderValue(vctxt->reader), 1) == -1) {
27044:
27045: VERROR_INT("xmlSchemaVReaderWalk",
27046: "calling xmlSchemaValidatorPushAttribute()");
27047: goto internal_error;
27048: }
27049: ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27050: if (ret == -1) {
27051: VERROR_INT("xmlSchemaVReaderWalk",
27052: "calling xmlTextReaderMoveToFirstAttribute()");
27053: goto internal_error;
27054: }
27055: } while (ret == 1);
27056: /*
27057: * Back to element position.
27058: */
27059: ret = xmlTextReaderMoveToElement(vctxt->reader);
27060: if (ret == -1) {
27061: VERROR_INT("xmlSchemaVReaderWalk",
27062: "calling xmlTextReaderMoveToElement()");
27063: goto internal_error;
27064: }
27065: }
27066: /*
27067: * Validate the element.
27068: */
27069: ret= xmlSchemaValidateElem(vctxt);
27070: if (ret != 0) {
27071: if (ret == -1) {
27072: VERROR_INT("xmlSchemaVReaderWalk",
27073: "calling xmlSchemaValidateElem()");
27074: goto internal_error;
27075: }
27076: goto exit;
27077: }
27078: if (vctxt->depth == vctxt->skipDepth) {
27079: int curDepth;
27080: /*
27081: * Skip all content.
27082: */
27083: if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27084: ret = xmlTextReaderRead(vctxt->reader);
27085: curDepth = xmlTextReaderDepth(vctxt->reader);
27086: while ((ret == 1) && (curDepth != depth)) {
27087: ret = xmlTextReaderRead(vctxt->reader);
27088: curDepth = xmlTextReaderDepth(vctxt->reader);
27089: }
27090: if (ret < 0) {
27091: /*
27092: * VAL TODO: A reader error occured; what to do here?
27093: */
27094: ret = 1;
27095: goto exit;
27096: }
27097: }
27098: goto leave_elem;
27099: }
27100: /*
27101: * READER VAL TODO: Is an END_ELEM really never called
27102: * if the elem is empty?
27103: */
27104: if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27105: goto leave_elem;
27106: } else if (nodeType == END_ELEM) {
27107: /*
27108: * Process END of element.
27109: */
27110: leave_elem:
27111: ret = xmlSchemaValidatorPopElem(vctxt);
27112: if (ret != 0) {
27113: if (ret < 0) {
27114: VERROR_INT("xmlSchemaVReaderWalk",
27115: "calling xmlSchemaValidatorPopElem()");
27116: goto internal_error;
27117: }
27118: goto exit;
27119: }
27120: if (vctxt->depth >= 0)
27121: ielem = vctxt->inode;
27122: else
27123: ielem = NULL;
27124: } else if ((nodeType == XML_TEXT_NODE) ||
27125: (nodeType == XML_CDATA_SECTION_NODE) ||
27126: (nodeType == WHTSP) ||
27127: (nodeType == SIGN_WHTSP)) {
27128: /*
27129: * Process character content.
27130: */
27131: xmlChar *value;
27132:
27133: if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27134: nodeType = XML_TEXT_NODE;
27135:
27136: value = xmlTextReaderValue(vctxt->reader);
27137: ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27138: -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27139: if (! consumed)
27140: xmlFree(value);
27141: if (ret == -1) {
27142: VERROR_INT("xmlSchemaVReaderWalk",
27143: "calling xmlSchemaVPushText()");
27144: goto internal_error;
27145: }
27146: } else if ((nodeType == XML_ENTITY_NODE) ||
27147: (nodeType == XML_ENTITY_REF_NODE)) {
27148: /*
27149: * VAL TODO: What to do with entities?
27150: */
27151: TODO
27152: }
27153: /*
27154: * Read next node.
27155: */
27156: ret = xmlTextReaderRead(vctxt->reader);
27157: } while (ret == 1);
27158:
27159: exit:
27160: return (ret);
27161: internal_error:
27162: return (-1);
27163: }
27164: #endif
27165:
27166: /************************************************************************
27167: * *
27168: * SAX validation handlers *
27169: * *
27170: ************************************************************************/
27171:
27172: /*
27173: * Process text content.
27174: */
27175: static void
27176: xmlSchemaSAXHandleText(void *ctx,
27177: const xmlChar * ch,
27178: int len)
27179: {
27180: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27181:
27182: if (vctxt->depth < 0)
27183: return;
27184: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27185: return;
27186: if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27187: vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27188: if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27189: XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27190: VERROR_INT("xmlSchemaSAXHandleCDataSection",
27191: "calling xmlSchemaVPushText()");
27192: vctxt->err = -1;
27193: xmlStopParser(vctxt->parserCtxt);
27194: }
27195: }
27196:
27197: /*
27198: * Process CDATA content.
27199: */
27200: static void
27201: xmlSchemaSAXHandleCDataSection(void *ctx,
27202: const xmlChar * ch,
27203: int len)
27204: {
27205: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27206:
27207: if (vctxt->depth < 0)
27208: return;
27209: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27210: return;
27211: if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27212: vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27213: if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27214: XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27215: VERROR_INT("xmlSchemaSAXHandleCDataSection",
27216: "calling xmlSchemaVPushText()");
27217: vctxt->err = -1;
27218: xmlStopParser(vctxt->parserCtxt);
27219: }
27220: }
27221:
27222: static void
27223: xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27224: const xmlChar * name ATTRIBUTE_UNUSED)
27225: {
27226: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27227:
27228: if (vctxt->depth < 0)
27229: return;
27230: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27231: return;
27232: /* SAX VAL TODO: What to do here? */
27233: TODO
27234: }
27235:
27236: static void
27237: xmlSchemaSAXHandleStartElementNs(void *ctx,
27238: const xmlChar * localname,
27239: const xmlChar * prefix ATTRIBUTE_UNUSED,
27240: const xmlChar * URI,
27241: int nb_namespaces,
27242: const xmlChar ** namespaces,
27243: int nb_attributes,
27244: int nb_defaulted ATTRIBUTE_UNUSED,
27245: const xmlChar ** attributes)
27246: {
27247: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27248: int ret;
27249: xmlSchemaNodeInfoPtr ielem;
27250: int i, j;
27251:
27252: /*
27253: * SAX VAL TODO: What to do with nb_defaulted?
27254: */
27255: /*
27256: * Skip elements if inside a "skip" wildcard or invalid.
27257: */
27258: vctxt->depth++;
27259: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27260: return;
27261: /*
27262: * Push the element.
27263: */
27264: if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27265: VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27266: "calling xmlSchemaValidatorPushElem()");
27267: goto internal_error;
27268: }
27269: ielem = vctxt->inode;
27270: /*
27271: * TODO: Is this OK?
27272: */
27273: ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27274: ielem->localName = localname;
27275: ielem->nsName = URI;
27276: ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27277: /*
27278: * Register namespaces on the elem info.
27279: */
27280: if (nb_namespaces != 0) {
27281: /*
27282: * Although the parser builds its own namespace list,
27283: * we have no access to it, so we'll use an own one.
27284: */
27285: for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27286: /*
27287: * Store prefix and namespace name.
27288: */
27289: if (ielem->nsBindings == NULL) {
27290: ielem->nsBindings =
27291: (const xmlChar **) xmlMalloc(10 *
27292: sizeof(const xmlChar *));
27293: if (ielem->nsBindings == NULL) {
27294: xmlSchemaVErrMemory(vctxt,
27295: "allocating namespace bindings for SAX validation",
27296: NULL);
27297: goto internal_error;
27298: }
27299: ielem->nbNsBindings = 0;
27300: ielem->sizeNsBindings = 5;
27301: } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27302: ielem->sizeNsBindings *= 2;
27303: ielem->nsBindings =
27304: (const xmlChar **) xmlRealloc(
27305: (void *) ielem->nsBindings,
27306: ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27307: if (ielem->nsBindings == NULL) {
27308: xmlSchemaVErrMemory(vctxt,
27309: "re-allocating namespace bindings for SAX validation",
27310: NULL);
27311: goto internal_error;
27312: }
27313: }
27314:
27315: ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27316: if (namespaces[j+1][0] == 0) {
27317: /*
27318: * Handle xmlns="".
27319: */
27320: ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27321: } else
27322: ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27323: namespaces[j+1];
27324: ielem->nbNsBindings++;
27325: }
27326: }
27327: /*
27328: * Register attributes.
27329: * SAX VAL TODO: We are not adding namespace declaration
27330: * attributes yet.
27331: */
27332: if (nb_attributes != 0) {
27333: xmlChar *value;
27334:
27335: for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27336: /*
27337: * Duplicate the value.
27338: */
27339: value = xmlStrndup(attributes[j+3],
27340: attributes[j+4] - attributes[j+3]);
27341: /*
27342: * TODO: Set the node line.
27343: */
27344: ret = xmlSchemaValidatorPushAttribute(vctxt,
27345: NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27346: value, 1);
27347: if (ret == -1) {
27348: VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27349: "calling xmlSchemaValidatorPushAttribute()");
27350: goto internal_error;
27351: }
27352: }
27353: }
27354: /*
27355: * Validate the element.
27356: */
27357: ret = xmlSchemaValidateElem(vctxt);
27358: if (ret != 0) {
27359: if (ret == -1) {
27360: VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27361: "calling xmlSchemaValidateElem()");
27362: goto internal_error;
27363: }
27364: goto exit;
27365: }
27366:
27367: exit:
27368: return;
27369: internal_error:
27370: vctxt->err = -1;
27371: xmlStopParser(vctxt->parserCtxt);
27372: return;
27373: }
27374:
27375: static void
27376: xmlSchemaSAXHandleEndElementNs(void *ctx,
27377: const xmlChar * localname ATTRIBUTE_UNUSED,
27378: const xmlChar * prefix ATTRIBUTE_UNUSED,
27379: const xmlChar * URI ATTRIBUTE_UNUSED)
27380: {
27381: xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27382: int res;
27383:
27384: /*
27385: * Skip elements if inside a "skip" wildcard or if invalid.
27386: */
27387: if (vctxt->skipDepth != -1) {
27388: if (vctxt->depth > vctxt->skipDepth) {
27389: vctxt->depth--;
27390: return;
27391: } else
27392: vctxt->skipDepth = -1;
27393: }
27394: /*
27395: * SAX VAL TODO: Just a temporary check.
27396: */
27397: if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27398: (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27399: VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27400: "elem pop mismatch");
27401: }
27402: res = xmlSchemaValidatorPopElem(vctxt);
27403: if (res != 0) {
27404: if (res < 0) {
27405: VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27406: "calling xmlSchemaValidatorPopElem()");
27407: goto internal_error;
27408: }
27409: goto exit;
27410: }
27411: exit:
27412: return;
27413: internal_error:
27414: vctxt->err = -1;
27415: xmlStopParser(vctxt->parserCtxt);
27416: return;
27417: }
27418:
27419: /************************************************************************
27420: * *
27421: * Validation interfaces *
27422: * *
27423: ************************************************************************/
27424:
27425: /**
27426: * xmlSchemaNewValidCtxt:
27427: * @schema: a precompiled XML Schemas
27428: *
27429: * Create an XML Schemas validation context based on the given schema.
27430: *
27431: * Returns the validation context or NULL in case of error
27432: */
27433: xmlSchemaValidCtxtPtr
27434: xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27435: {
27436: xmlSchemaValidCtxtPtr ret;
27437:
27438: ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27439: if (ret == NULL) {
27440: xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27441: return (NULL);
27442: }
27443: memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27444: ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27445: ret->dict = xmlDictCreate();
27446: ret->nodeQNames = xmlSchemaItemListCreate();
27447: ret->schema = schema;
27448: return (ret);
27449: }
27450:
27451: /**
27452: * xmlSchemaClearValidCtxt:
27453: * @ctxt: the schema validation context
27454: *
27455: * Free the resources associated to the schema validation context;
27456: * leaves some fields alive intended for reuse of the context.
27457: */
27458: static void
27459: xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27460: {
27461: if (vctxt == NULL)
27462: return;
27463:
27464: /*
27465: * TODO: Should we clear the flags?
27466: * Might be problematic if one reuses the context
27467: * and assumes that the options remain the same.
27468: */
27469: vctxt->flags = 0;
27470: vctxt->validationRoot = NULL;
27471: vctxt->doc = NULL;
27472: #ifdef LIBXML_READER_ENABLED
27473: vctxt->reader = NULL;
27474: #endif
27475: vctxt->hasKeyrefs = 0;
27476:
27477: if (vctxt->value != NULL) {
27478: xmlSchemaFreeValue(vctxt->value);
27479: vctxt->value = NULL;
27480: }
27481: /*
27482: * Augmented IDC information.
27483: */
27484: if (vctxt->aidcs != NULL) {
27485: xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27486: do {
27487: next = cur->next;
27488: xmlFree(cur);
27489: cur = next;
27490: } while (cur != NULL);
27491: vctxt->aidcs = NULL;
27492: }
27493: if (vctxt->idcMatcherCache != NULL) {
27494: xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27495:
27496: while (matcher) {
27497: tmp = matcher;
27498: matcher = matcher->nextCached;
27499: xmlSchemaIDCFreeMatcherList(tmp);
27500: }
27501: vctxt->idcMatcherCache = NULL;
27502: }
27503:
27504:
27505: if (vctxt->idcNodes != NULL) {
27506: int i;
27507: xmlSchemaPSVIIDCNodePtr item;
27508:
27509: for (i = 0; i < vctxt->nbIdcNodes; i++) {
27510: item = vctxt->idcNodes[i];
27511: xmlFree(item->keys);
27512: xmlFree(item);
27513: }
27514: xmlFree(vctxt->idcNodes);
27515: vctxt->idcNodes = NULL;
27516: vctxt->nbIdcNodes = 0;
27517: vctxt->sizeIdcNodes = 0;
27518: }
27519: /*
27520: * Note that we won't delete the XPath state pool here.
27521: */
27522: if (vctxt->xpathStates != NULL) {
27523: xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27524: vctxt->xpathStates = NULL;
27525: }
27526: /*
27527: * Attribute info.
27528: */
27529: if (vctxt->nbAttrInfos != 0) {
27530: xmlSchemaClearAttrInfos(vctxt);
27531: }
27532: /*
27533: * Element info.
27534: */
27535: if (vctxt->elemInfos != NULL) {
27536: int i;
27537: xmlSchemaNodeInfoPtr ei;
27538:
27539: for (i = 0; i < vctxt->sizeElemInfos; i++) {
27540: ei = vctxt->elemInfos[i];
27541: if (ei == NULL)
27542: break;
27543: xmlSchemaClearElemInfo(vctxt, ei);
27544: }
27545: }
27546: xmlSchemaItemListClear(vctxt->nodeQNames);
27547: /* Recreate the dict. */
27548: xmlDictFree(vctxt->dict);
27549: /*
27550: * TODO: Is is save to recreate it? Do we have a scenario
27551: * where the user provides the dict?
27552: */
27553: vctxt->dict = xmlDictCreate();
27554: }
27555:
27556: /**
27557: * xmlSchemaFreeValidCtxt:
27558: * @ctxt: the schema validation context
27559: *
27560: * Free the resources associated to the schema validation context
27561: */
27562: void
27563: xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27564: {
27565: if (ctxt == NULL)
27566: return;
27567: if (ctxt->value != NULL)
27568: xmlSchemaFreeValue(ctxt->value);
27569: if (ctxt->pctxt != NULL)
27570: xmlSchemaFreeParserCtxt(ctxt->pctxt);
27571: if (ctxt->idcNodes != NULL) {
27572: int i;
27573: xmlSchemaPSVIIDCNodePtr item;
27574:
27575: for (i = 0; i < ctxt->nbIdcNodes; i++) {
27576: item = ctxt->idcNodes[i];
27577: xmlFree(item->keys);
27578: xmlFree(item);
27579: }
27580: xmlFree(ctxt->idcNodes);
27581: }
27582: if (ctxt->idcKeys != NULL) {
27583: int i;
27584: for (i = 0; i < ctxt->nbIdcKeys; i++)
27585: xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27586: xmlFree(ctxt->idcKeys);
27587: }
27588:
27589: if (ctxt->xpathStates != NULL) {
27590: xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27591: ctxt->xpathStates = NULL;
27592: }
27593: if (ctxt->xpathStatePool != NULL) {
27594: xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27595: ctxt->xpathStatePool = NULL;
27596: }
27597:
27598: /*
27599: * Augmented IDC information.
27600: */
27601: if (ctxt->aidcs != NULL) {
27602: xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27603: do {
27604: next = cur->next;
27605: xmlFree(cur);
27606: cur = next;
27607: } while (cur != NULL);
27608: }
27609: if (ctxt->attrInfos != NULL) {
27610: int i;
27611: xmlSchemaAttrInfoPtr attr;
27612:
27613: /* Just a paranoid call to the cleanup. */
27614: if (ctxt->nbAttrInfos != 0)
27615: xmlSchemaClearAttrInfos(ctxt);
27616: for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27617: attr = ctxt->attrInfos[i];
27618: xmlFree(attr);
27619: }
27620: xmlFree(ctxt->attrInfos);
27621: }
27622: if (ctxt->elemInfos != NULL) {
27623: int i;
27624: xmlSchemaNodeInfoPtr ei;
27625:
27626: for (i = 0; i < ctxt->sizeElemInfos; i++) {
27627: ei = ctxt->elemInfos[i];
27628: if (ei == NULL)
27629: break;
27630: xmlSchemaClearElemInfo(ctxt, ei);
27631: xmlFree(ei);
27632: }
27633: xmlFree(ctxt->elemInfos);
27634: }
27635: if (ctxt->nodeQNames != NULL)
27636: xmlSchemaItemListFree(ctxt->nodeQNames);
27637: if (ctxt->dict != NULL)
27638: xmlDictFree(ctxt->dict);
27639: xmlFree(ctxt);
27640: }
27641:
27642: /**
27643: * xmlSchemaIsValid:
27644: * @ctxt: the schema validation context
27645: *
27646: * Check if any error was detected during validation.
27647: *
27648: * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27649: * of internal error.
27650: */
27651: int
27652: xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27653: {
27654: if (ctxt == NULL)
27655: return(-1);
27656: return(ctxt->err == 0);
27657: }
27658:
27659: /**
27660: * xmlSchemaSetValidErrors:
27661: * @ctxt: a schema validation context
27662: * @err: the error function
27663: * @warn: the warning function
27664: * @ctx: the functions context
27665: *
27666: * Set the error and warning callback informations
27667: */
27668: void
27669: xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27670: xmlSchemaValidityErrorFunc err,
27671: xmlSchemaValidityWarningFunc warn, void *ctx)
27672: {
27673: if (ctxt == NULL)
27674: return;
27675: ctxt->error = err;
27676: ctxt->warning = warn;
27677: ctxt->errCtxt = ctx;
27678: if (ctxt->pctxt != NULL)
27679: xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27680: }
27681:
27682: /**
27683: * xmlSchemaSetValidStructuredErrors:
27684: * @ctxt: a schema validation context
27685: * @serror: the structured error function
27686: * @ctx: the functions context
27687: *
27688: * Set the structured error callback
27689: */
27690: void
27691: xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27692: xmlStructuredErrorFunc serror, void *ctx)
27693: {
27694: if (ctxt == NULL)
27695: return;
27696: ctxt->serror = serror;
27697: ctxt->error = NULL;
27698: ctxt->warning = NULL;
27699: ctxt->errCtxt = ctx;
27700: if (ctxt->pctxt != NULL)
27701: xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27702: }
27703:
27704: /**
27705: * xmlSchemaGetValidErrors:
27706: * @ctxt: a XML-Schema validation context
27707: * @err: the error function result
27708: * @warn: the warning function result
27709: * @ctx: the functions context result
27710: *
27711: * Get the error and warning callback informations
27712: *
27713: * Returns -1 in case of error and 0 otherwise
27714: */
27715: int
27716: xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27717: xmlSchemaValidityErrorFunc * err,
27718: xmlSchemaValidityWarningFunc * warn, void **ctx)
27719: {
27720: if (ctxt == NULL)
27721: return (-1);
27722: if (err != NULL)
27723: *err = ctxt->error;
27724: if (warn != NULL)
27725: *warn = ctxt->warning;
27726: if (ctx != NULL)
27727: *ctx = ctxt->errCtxt;
27728: return (0);
27729: }
27730:
27731:
27732: /**
27733: * xmlSchemaSetValidOptions:
27734: * @ctxt: a schema validation context
27735: * @options: a combination of xmlSchemaValidOption
27736: *
27737: * Sets the options to be used during the validation.
27738: *
27739: * Returns 0 in case of success, -1 in case of an
27740: * API error.
27741: */
27742: int
27743: xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27744: int options)
27745:
27746: {
27747: int i;
27748:
27749: if (ctxt == NULL)
27750: return (-1);
27751: /*
27752: * WARNING: Change the start value if adding to the
27753: * xmlSchemaValidOption.
27754: * TODO: Is there an other, more easy to maintain,
27755: * way?
27756: */
27757: for (i = 1; i < (int) sizeof(int) * 8; i++) {
27758: if (options & 1<<i)
27759: return (-1);
27760: }
27761: ctxt->options = options;
27762: return (0);
27763: }
27764:
27765: /**
27766: * xmlSchemaValidCtxtGetOptions:
27767: * @ctxt: a schema validation context
27768: *
27769: * Get the validation context options.
27770: *
27771: * Returns the option combination or -1 on error.
27772: */
27773: int
27774: xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27775:
27776: {
27777: if (ctxt == NULL)
27778: return (-1);
27779: else
27780: return (ctxt->options);
27781: }
27782:
27783: static int
27784: xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27785: {
27786: xmlAttrPtr attr;
27787: int ret = 0;
27788: xmlSchemaNodeInfoPtr ielem = NULL;
27789: xmlNodePtr node, valRoot;
27790: const xmlChar *nsName;
27791:
27792: /* DOC VAL TODO: Move this to the start function. */
27793: valRoot = xmlDocGetRootElement(vctxt->doc);
27794: if (valRoot == NULL) {
27795: /* VAL TODO: Error code? */
27796: VERROR(1, NULL, "The document has no document element");
27797: return (1);
27798: }
27799: vctxt->depth = -1;
27800: vctxt->validationRoot = valRoot;
27801: node = valRoot;
27802: while (node != NULL) {
27803: if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27804: goto next_sibling;
27805: if (node->type == XML_ELEMENT_NODE) {
27806:
27807: /*
27808: * Init the node-info.
27809: */
27810: vctxt->depth++;
27811: if (xmlSchemaValidatorPushElem(vctxt) == -1)
27812: goto internal_error;
27813: ielem = vctxt->inode;
27814: ielem->node = node;
27815: ielem->nodeLine = node->line;
27816: ielem->localName = node->name;
27817: if (node->ns != NULL)
27818: ielem->nsName = node->ns->href;
27819: ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27820: /*
27821: * Register attributes.
27822: * DOC VAL TODO: We do not register namespace declaration
27823: * attributes yet.
27824: */
27825: vctxt->nbAttrInfos = 0;
27826: if (node->properties != NULL) {
27827: attr = node->properties;
27828: do {
27829: if (attr->ns != NULL)
27830: nsName = attr->ns->href;
27831: else
27832: nsName = NULL;
27833: ret = xmlSchemaValidatorPushAttribute(vctxt,
27834: (xmlNodePtr) attr,
27835: /*
27836: * Note that we give it the line number of the
27837: * parent element.
27838: */
27839: ielem->nodeLine,
27840: attr->name, nsName, 0,
27841: xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27842: if (ret == -1) {
27843: VERROR_INT("xmlSchemaDocWalk",
27844: "calling xmlSchemaValidatorPushAttribute()");
27845: goto internal_error;
27846: }
27847: attr = attr->next;
27848: } while (attr);
27849: }
27850: /*
27851: * Validate the element.
27852: */
27853: ret = xmlSchemaValidateElem(vctxt);
27854: if (ret != 0) {
27855: if (ret == -1) {
27856: VERROR_INT("xmlSchemaDocWalk",
27857: "calling xmlSchemaValidateElem()");
27858: goto internal_error;
27859: }
27860: /*
27861: * Don't stop validation; just skip the content
27862: * of this element.
27863: */
27864: goto leave_node;
27865: }
27866: if ((vctxt->skipDepth != -1) &&
27867: (vctxt->depth >= vctxt->skipDepth))
27868: goto leave_node;
27869: } else if ((node->type == XML_TEXT_NODE) ||
27870: (node->type == XML_CDATA_SECTION_NODE)) {
27871: /*
27872: * Process character content.
27873: */
27874: if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27875: ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27876: ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27877: -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27878: if (ret < 0) {
27879: VERROR_INT("xmlSchemaVDocWalk",
27880: "calling xmlSchemaVPushText()");
27881: goto internal_error;
27882: }
27883: /*
27884: * DOC VAL TODO: Should we skip further validation of the
27885: * element content here?
27886: */
27887: } else if ((node->type == XML_ENTITY_NODE) ||
27888: (node->type == XML_ENTITY_REF_NODE)) {
27889: /*
27890: * DOC VAL TODO: What to do with entities?
27891: */
27892: VERROR_INT("xmlSchemaVDocWalk",
27893: "there is at least one entity reference in the node-tree "
27894: "currently being validated. Processing of entities with "
27895: "this XML Schema processor is not supported (yet). Please "
27896: "substitute entities before validation.");
27897: goto internal_error;
27898: } else {
27899: goto leave_node;
27900: /*
27901: * DOC VAL TODO: XInclude nodes, etc.
27902: */
27903: }
27904: /*
27905: * Walk the doc.
27906: */
27907: if (node->children != NULL) {
27908: node = node->children;
27909: continue;
27910: }
27911: leave_node:
27912: if (node->type == XML_ELEMENT_NODE) {
27913: /*
27914: * Leaving the scope of an element.
27915: */
27916: if (node != vctxt->inode->node) {
27917: VERROR_INT("xmlSchemaVDocWalk",
27918: "element position mismatch");
27919: goto internal_error;
27920: }
27921: ret = xmlSchemaValidatorPopElem(vctxt);
27922: if (ret != 0) {
27923: if (ret < 0) {
27924: VERROR_INT("xmlSchemaVDocWalk",
27925: "calling xmlSchemaValidatorPopElem()");
27926: goto internal_error;
27927: }
27928: }
27929: if (node == valRoot)
27930: goto exit;
27931: }
27932: next_sibling:
27933: if (node->next != NULL)
27934: node = node->next;
27935: else {
27936: node = node->parent;
27937: goto leave_node;
27938: }
27939: }
27940:
27941: exit:
27942: return (ret);
27943: internal_error:
27944: return (-1);
27945: }
27946:
27947: static int
27948: xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27949: /*
27950: * Some initialization.
27951: */
27952: vctxt->err = 0;
27953: vctxt->nberrors = 0;
27954: vctxt->depth = -1;
27955: vctxt->skipDepth = -1;
27956: vctxt->xsiAssemble = 0;
27957: vctxt->hasKeyrefs = 0;
27958: #ifdef ENABLE_IDC_NODE_TABLES_TEST
27959: vctxt->createIDCNodeTables = 1;
27960: #else
27961: vctxt->createIDCNodeTables = 0;
27962: #endif
27963: /*
27964: * Create a schema + parser if necessary.
27965: */
27966: if (vctxt->schema == NULL) {
27967: xmlSchemaParserCtxtPtr pctxt;
27968:
27969: vctxt->xsiAssemble = 1;
27970: /*
27971: * If not schema was given then we will create a schema
27972: * dynamically using XSI schema locations.
27973: *
27974: * Create the schema parser context.
27975: */
27976: if ((vctxt->pctxt == NULL) &&
27977: (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27978: return (-1);
27979: pctxt = vctxt->pctxt;
27980: pctxt->xsiAssemble = 1;
27981: /*
27982: * Create the schema.
27983: */
27984: vctxt->schema = xmlSchemaNewSchema(pctxt);
27985: if (vctxt->schema == NULL)
27986: return (-1);
27987: /*
27988: * Create the schema construction context.
27989: */
27990: pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27991: if (pctxt->constructor == NULL)
27992: return(-1);
27993: pctxt->constructor->mainSchema = vctxt->schema;
27994: /*
27995: * Take ownership of the constructor to be able to free it.
27996: */
27997: pctxt->ownsConstructor = 1;
27998: }
27999: /*
28000: * Augment the IDC definitions for the main schema and all imported ones
28001: * NOTE: main schema if the first in the imported list
28002: */
28003: xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
28004:
28005: return(0);
28006: }
28007:
28008: static void
28009: xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28010: if (vctxt->xsiAssemble) {
28011: if (vctxt->schema != NULL) {
28012: xmlSchemaFree(vctxt->schema);
28013: vctxt->schema = NULL;
28014: }
28015: }
28016: xmlSchemaClearValidCtxt(vctxt);
28017: }
28018:
28019: static int
28020: xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28021: {
28022: int ret = 0;
28023:
28024: if (xmlSchemaPreRun(vctxt) < 0)
28025: return(-1);
28026:
28027: if (vctxt->doc != NULL) {
28028: /*
28029: * Tree validation.
28030: */
28031: ret = xmlSchemaVDocWalk(vctxt);
28032: #ifdef LIBXML_READER_ENABLED
28033: } else if (vctxt->reader != NULL) {
28034: /*
28035: * XML Reader validation.
28036: */
28037: #ifdef XML_SCHEMA_READER_ENABLED
28038: ret = xmlSchemaVReaderWalk(vctxt);
28039: #endif
28040: #endif
28041: } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28042: /*
28043: * SAX validation.
28044: */
28045: ret = xmlParseDocument(vctxt->parserCtxt);
28046: } else {
28047: VERROR_INT("xmlSchemaVStart",
28048: "no instance to validate");
28049: ret = -1;
28050: }
28051:
28052: xmlSchemaPostRun(vctxt);
28053: if (ret == 0)
28054: ret = vctxt->err;
28055: return (ret);
28056: }
28057:
28058: /**
28059: * xmlSchemaValidateOneElement:
28060: * @ctxt: a schema validation context
28061: * @elem: an element node
28062: *
28063: * Validate a branch of a tree, starting with the given @elem.
28064: *
28065: * Returns 0 if the element and its subtree is valid, a positive error
28066: * code number otherwise and -1 in case of an internal or API error.
28067: */
28068: int
28069: xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28070: {
28071: if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28072: return (-1);
28073:
28074: if (ctxt->schema == NULL)
28075: return (-1);
28076:
28077: ctxt->doc = elem->doc;
28078: ctxt->node = elem;
28079: ctxt->validationRoot = elem;
28080: return(xmlSchemaVStart(ctxt));
28081: }
28082:
28083: /**
28084: * xmlSchemaValidateDoc:
28085: * @ctxt: a schema validation context
28086: * @doc: a parsed document tree
28087: *
28088: * Validate a document tree in memory.
28089: *
28090: * Returns 0 if the document is schemas valid, a positive error code
28091: * number otherwise and -1 in case of internal or API error.
28092: */
28093: int
28094: xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28095: {
28096: if ((ctxt == NULL) || (doc == NULL))
28097: return (-1);
28098:
28099: ctxt->doc = doc;
28100: ctxt->node = xmlDocGetRootElement(doc);
28101: if (ctxt->node == NULL) {
28102: xmlSchemaCustomErr(ACTXT_CAST ctxt,
28103: XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28104: (xmlNodePtr) doc, NULL,
28105: "The document has no document element", NULL, NULL);
28106: return (ctxt->err);
28107: }
28108: ctxt->validationRoot = ctxt->node;
28109: return (xmlSchemaVStart(ctxt));
28110: }
28111:
28112:
28113: /************************************************************************
28114: * *
28115: * Function and data for SAX streaming API *
28116: * *
28117: ************************************************************************/
28118: typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28119: typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28120:
28121: struct _xmlSchemaSplitSAXData {
28122: xmlSAXHandlerPtr user_sax;
28123: void *user_data;
28124: xmlSchemaValidCtxtPtr ctxt;
28125: xmlSAXHandlerPtr schemas_sax;
28126: };
28127:
28128: #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28129:
28130: struct _xmlSchemaSAXPlug {
28131: unsigned int magic;
28132:
28133: /* the original callbacks informations */
28134: xmlSAXHandlerPtr *user_sax_ptr;
28135: xmlSAXHandlerPtr user_sax;
28136: void **user_data_ptr;
28137: void *user_data;
28138:
28139: /* the block plugged back and validation informations */
28140: xmlSAXHandler schemas_sax;
28141: xmlSchemaValidCtxtPtr ctxt;
28142: };
28143:
28144: /* All those functions just bounces to the user provided SAX handlers */
28145: static void
28146: internalSubsetSplit(void *ctx, const xmlChar *name,
28147: const xmlChar *ExternalID, const xmlChar *SystemID)
28148: {
28149: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28150: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28151: (ctxt->user_sax->internalSubset != NULL))
28152: ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28153: SystemID);
28154: }
28155:
28156: static int
28157: isStandaloneSplit(void *ctx)
28158: {
28159: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28160: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28161: (ctxt->user_sax->isStandalone != NULL))
28162: return(ctxt->user_sax->isStandalone(ctxt->user_data));
28163: return(0);
28164: }
28165:
28166: static int
28167: hasInternalSubsetSplit(void *ctx)
28168: {
28169: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28170: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28171: (ctxt->user_sax->hasInternalSubset != NULL))
28172: return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28173: return(0);
28174: }
28175:
28176: static int
28177: hasExternalSubsetSplit(void *ctx)
28178: {
28179: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28180: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28181: (ctxt->user_sax->hasExternalSubset != NULL))
28182: return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28183: return(0);
28184: }
28185:
28186: static void
28187: externalSubsetSplit(void *ctx, const xmlChar *name,
28188: const xmlChar *ExternalID, const xmlChar *SystemID)
28189: {
28190: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28191: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28192: (ctxt->user_sax->externalSubset != NULL))
28193: ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28194: SystemID);
28195: }
28196:
28197: static xmlParserInputPtr
28198: resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28199: {
28200: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28201: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28202: (ctxt->user_sax->resolveEntity != NULL))
28203: return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28204: systemId));
28205: return(NULL);
28206: }
28207:
28208: static xmlEntityPtr
28209: getEntitySplit(void *ctx, const xmlChar *name)
28210: {
28211: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28212: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28213: (ctxt->user_sax->getEntity != NULL))
28214: return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28215: return(NULL);
28216: }
28217:
28218: static xmlEntityPtr
28219: getParameterEntitySplit(void *ctx, const xmlChar *name)
28220: {
28221: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28222: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28223: (ctxt->user_sax->getParameterEntity != NULL))
28224: return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28225: return(NULL);
28226: }
28227:
28228:
28229: static void
28230: entityDeclSplit(void *ctx, const xmlChar *name, int type,
28231: const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28232: {
28233: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28234: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28235: (ctxt->user_sax->entityDecl != NULL))
28236: ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28237: systemId, content);
28238: }
28239:
28240: static void
28241: attributeDeclSplit(void *ctx, const xmlChar * elem,
28242: const xmlChar * name, int type, int def,
28243: const xmlChar * defaultValue, xmlEnumerationPtr tree)
28244: {
28245: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28246: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28247: (ctxt->user_sax->attributeDecl != NULL)) {
28248: ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28249: def, defaultValue, tree);
28250: } else {
28251: xmlFreeEnumeration(tree);
28252: }
28253: }
28254:
28255: static void
28256: elementDeclSplit(void *ctx, const xmlChar *name, int type,
28257: xmlElementContentPtr content)
28258: {
28259: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28260: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28261: (ctxt->user_sax->elementDecl != NULL))
28262: ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28263: }
28264:
28265: static void
28266: notationDeclSplit(void *ctx, const xmlChar *name,
28267: const xmlChar *publicId, const xmlChar *systemId)
28268: {
28269: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28270: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28271: (ctxt->user_sax->notationDecl != NULL))
28272: ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28273: systemId);
28274: }
28275:
28276: static void
28277: unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28278: const xmlChar *publicId, const xmlChar *systemId,
28279: const xmlChar *notationName)
28280: {
28281: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28282: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28283: (ctxt->user_sax->unparsedEntityDecl != NULL))
28284: ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28285: systemId, notationName);
28286: }
28287:
28288: static void
28289: setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28290: {
28291: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28292: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28293: (ctxt->user_sax->setDocumentLocator != NULL))
28294: ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28295: }
28296:
28297: static void
28298: startDocumentSplit(void *ctx)
28299: {
28300: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28301: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28302: (ctxt->user_sax->startDocument != NULL))
28303: ctxt->user_sax->startDocument(ctxt->user_data);
28304: }
28305:
28306: static void
28307: endDocumentSplit(void *ctx)
28308: {
28309: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28310: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28311: (ctxt->user_sax->endDocument != NULL))
28312: ctxt->user_sax->endDocument(ctxt->user_data);
28313: }
28314:
28315: static void
28316: processingInstructionSplit(void *ctx, const xmlChar *target,
28317: const xmlChar *data)
28318: {
28319: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28320: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28321: (ctxt->user_sax->processingInstruction != NULL))
28322: ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28323: }
28324:
28325: static void
28326: commentSplit(void *ctx, const xmlChar *value)
28327: {
28328: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28329: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28330: (ctxt->user_sax->comment != NULL))
28331: ctxt->user_sax->comment(ctxt->user_data, value);
28332: }
28333:
28334: /*
28335: * Varargs error callbacks to the user application, harder ...
28336: */
28337:
28338: static void XMLCDECL
28339: warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28340: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28341: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28342: (ctxt->user_sax->warning != NULL)) {
28343: TODO
28344: }
28345: }
28346: static void XMLCDECL
28347: errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28348: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28349: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28350: (ctxt->user_sax->error != NULL)) {
28351: TODO
28352: }
28353: }
28354: static void XMLCDECL
28355: fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28356: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28357: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28358: (ctxt->user_sax->fatalError != NULL)) {
28359: TODO
28360: }
28361: }
28362:
28363: /*
28364: * Those are function where both the user handler and the schemas handler
28365: * need to be called.
28366: */
28367: static void
28368: charactersSplit(void *ctx, const xmlChar *ch, int len)
28369: {
28370: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28371: if (ctxt == NULL)
28372: return;
28373: if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28374: ctxt->user_sax->characters(ctxt->user_data, ch, len);
28375: if (ctxt->ctxt != NULL)
28376: xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28377: }
28378:
28379: static void
28380: ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28381: {
28382: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28383: if (ctxt == NULL)
28384: return;
28385: if ((ctxt->user_sax != NULL) &&
28386: (ctxt->user_sax->ignorableWhitespace != NULL))
28387: ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28388: if (ctxt->ctxt != NULL)
28389: xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28390: }
28391:
28392: static void
28393: cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28394: {
28395: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28396: if (ctxt == NULL)
28397: return;
28398: if ((ctxt->user_sax != NULL) &&
28399: (ctxt->user_sax->cdataBlock != NULL))
28400: ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28401: if (ctxt->ctxt != NULL)
28402: xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28403: }
28404:
28405: static void
28406: referenceSplit(void *ctx, const xmlChar *name)
28407: {
28408: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28409: if (ctxt == NULL)
28410: return;
28411: if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28412: (ctxt->user_sax->reference != NULL))
28413: ctxt->user_sax->reference(ctxt->user_data, name);
28414: if (ctxt->ctxt != NULL)
28415: xmlSchemaSAXHandleReference(ctxt->user_data, name);
28416: }
28417:
28418: static void
28419: startElementNsSplit(void *ctx, const xmlChar * localname,
28420: const xmlChar * prefix, const xmlChar * URI,
28421: int nb_namespaces, const xmlChar ** namespaces,
28422: int nb_attributes, int nb_defaulted,
28423: const xmlChar ** attributes) {
28424: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28425: if (ctxt == NULL)
28426: return;
28427: if ((ctxt->user_sax != NULL) &&
28428: (ctxt->user_sax->startElementNs != NULL))
28429: ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28430: URI, nb_namespaces, namespaces,
28431: nb_attributes, nb_defaulted,
28432: attributes);
28433: if (ctxt->ctxt != NULL)
28434: xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28435: URI, nb_namespaces, namespaces,
28436: nb_attributes, nb_defaulted,
28437: attributes);
28438: }
28439:
28440: static void
28441: endElementNsSplit(void *ctx, const xmlChar * localname,
28442: const xmlChar * prefix, const xmlChar * URI) {
28443: xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28444: if (ctxt == NULL)
28445: return;
28446: if ((ctxt->user_sax != NULL) &&
28447: (ctxt->user_sax->endElementNs != NULL))
28448: ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28449: if (ctxt->ctxt != NULL)
28450: xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28451: }
28452:
28453: /**
28454: * xmlSchemaSAXPlug:
28455: * @ctxt: a schema validation context
28456: * @sax: a pointer to the original xmlSAXHandlerPtr
28457: * @user_data: a pointer to the original SAX user data pointer
28458: *
28459: * Plug a SAX based validation layer in a SAX parsing event flow.
28460: * The original @saxptr and @dataptr data are replaced by new pointers
28461: * but the calls to the original will be maintained.
28462: *
28463: * Returns a pointer to a data structure needed to unplug the validation layer
28464: * or NULL in case of errors.
28465: */
28466: xmlSchemaSAXPlugPtr
28467: xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28468: xmlSAXHandlerPtr *sax, void **user_data)
28469: {
28470: xmlSchemaSAXPlugPtr ret;
28471: xmlSAXHandlerPtr old_sax;
28472:
28473: if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28474: return(NULL);
28475:
28476: /*
28477: * We only allow to plug into SAX2 event streams
28478: */
28479: old_sax = *sax;
28480: if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28481: return(NULL);
28482: if ((old_sax != NULL) &&
28483: (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28484: ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28485: return(NULL);
28486:
28487: /*
28488: * everything seems right allocate the local data needed for that layer
28489: */
28490: ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28491: if (ret == NULL) {
28492: return(NULL);
28493: }
28494: memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28495: ret->magic = XML_SAX_PLUG_MAGIC;
28496: ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28497: ret->ctxt = ctxt;
28498: ret->user_sax_ptr = sax;
28499: ret->user_sax = old_sax;
28500: if (old_sax == NULL) {
28501: /*
28502: * go direct, no need for the split block and functions.
28503: */
28504: ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28505: ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28506: /*
28507: * Note that we use the same text-function for both, to prevent
28508: * the parser from testing for ignorable whitespace.
28509: */
28510: ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28511: ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28512:
28513: ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28514: ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28515:
28516: ret->user_data = ctxt;
28517: *user_data = ctxt;
28518: } else {
28519: /*
28520: * for each callback unused by Schemas initialize it to the Split
28521: * routine only if non NULL in the user block, this can speed up
28522: * things at the SAX level.
28523: */
28524: if (old_sax->internalSubset != NULL)
28525: ret->schemas_sax.internalSubset = internalSubsetSplit;
28526: if (old_sax->isStandalone != NULL)
28527: ret->schemas_sax.isStandalone = isStandaloneSplit;
28528: if (old_sax->hasInternalSubset != NULL)
28529: ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28530: if (old_sax->hasExternalSubset != NULL)
28531: ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28532: if (old_sax->resolveEntity != NULL)
28533: ret->schemas_sax.resolveEntity = resolveEntitySplit;
28534: if (old_sax->getEntity != NULL)
28535: ret->schemas_sax.getEntity = getEntitySplit;
28536: if (old_sax->entityDecl != NULL)
28537: ret->schemas_sax.entityDecl = entityDeclSplit;
28538: if (old_sax->notationDecl != NULL)
28539: ret->schemas_sax.notationDecl = notationDeclSplit;
28540: if (old_sax->attributeDecl != NULL)
28541: ret->schemas_sax.attributeDecl = attributeDeclSplit;
28542: if (old_sax->elementDecl != NULL)
28543: ret->schemas_sax.elementDecl = elementDeclSplit;
28544: if (old_sax->unparsedEntityDecl != NULL)
28545: ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28546: if (old_sax->setDocumentLocator != NULL)
28547: ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28548: if (old_sax->startDocument != NULL)
28549: ret->schemas_sax.startDocument = startDocumentSplit;
28550: if (old_sax->endDocument != NULL)
28551: ret->schemas_sax.endDocument = endDocumentSplit;
28552: if (old_sax->processingInstruction != NULL)
28553: ret->schemas_sax.processingInstruction = processingInstructionSplit;
28554: if (old_sax->comment != NULL)
28555: ret->schemas_sax.comment = commentSplit;
28556: if (old_sax->warning != NULL)
28557: ret->schemas_sax.warning = warningSplit;
28558: if (old_sax->error != NULL)
28559: ret->schemas_sax.error = errorSplit;
28560: if (old_sax->fatalError != NULL)
28561: ret->schemas_sax.fatalError = fatalErrorSplit;
28562: if (old_sax->getParameterEntity != NULL)
28563: ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28564: if (old_sax->externalSubset != NULL)
28565: ret->schemas_sax.externalSubset = externalSubsetSplit;
28566:
28567: /*
28568: * the 6 schemas callback have to go to the splitter functions
28569: * Note that we use the same text-function for ignorableWhitespace
28570: * if possible, to prevent the parser from testing for ignorable
28571: * whitespace.
28572: */
28573: ret->schemas_sax.characters = charactersSplit;
28574: if ((old_sax->ignorableWhitespace != NULL) &&
28575: (old_sax->ignorableWhitespace != old_sax->characters))
28576: ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28577: else
28578: ret->schemas_sax.ignorableWhitespace = charactersSplit;
28579: ret->schemas_sax.cdataBlock = cdataBlockSplit;
28580: ret->schemas_sax.reference = referenceSplit;
28581: ret->schemas_sax.startElementNs = startElementNsSplit;
28582: ret->schemas_sax.endElementNs = endElementNsSplit;
28583:
28584: ret->user_data_ptr = user_data;
28585: ret->user_data = *user_data;
28586: *user_data = ret;
28587: }
28588:
28589: /*
28590: * plug the pointers back.
28591: */
28592: *sax = &(ret->schemas_sax);
28593: ctxt->sax = *sax;
28594: ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28595: xmlSchemaPreRun(ctxt);
28596: return(ret);
28597: }
28598:
28599: /**
28600: * xmlSchemaSAXUnplug:
28601: * @plug: a data structure returned by xmlSchemaSAXPlug
28602: *
28603: * Unplug a SAX based validation layer in a SAX parsing event flow.
28604: * The original pointers used in the call are restored.
28605: *
28606: * Returns 0 in case of success and -1 in case of failure.
28607: */
28608: int
28609: xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28610: {
28611: xmlSAXHandlerPtr *sax;
28612: void **user_data;
28613:
28614: if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28615: return(-1);
28616: plug->magic = 0;
28617:
28618: xmlSchemaPostRun(plug->ctxt);
28619: /* restore the data */
28620: sax = plug->user_sax_ptr;
28621: *sax = plug->user_sax;
28622: if (plug->user_sax != NULL) {
28623: user_data = plug->user_data_ptr;
28624: *user_data = plug->user_data;
28625: }
28626:
28627: /* free and return */
28628: xmlFree(plug);
28629: return(0);
28630: }
28631:
28632: /**
28633: * xmlSchemaValidateStream:
28634: * @ctxt: a schema validation context
28635: * @input: the input to use for reading the data
28636: * @enc: an optional encoding information
28637: * @sax: a SAX handler for the resulting events
28638: * @user_data: the context to provide to the SAX handler.
28639: *
28640: * Validate an input based on a flow of SAX event from the parser
28641: * and forward the events to the @sax handler with the provided @user_data
28642: * the user provided @sax handler must be a SAX2 one.
28643: *
28644: * Returns 0 if the document is schemas valid, a positive error code
28645: * number otherwise and -1 in case of internal or API error.
28646: */
28647: int
28648: xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28649: xmlParserInputBufferPtr input, xmlCharEncoding enc,
28650: xmlSAXHandlerPtr sax, void *user_data)
28651: {
28652: xmlSchemaSAXPlugPtr plug = NULL;
28653: xmlSAXHandlerPtr old_sax = NULL;
28654: xmlParserCtxtPtr pctxt = NULL;
28655: xmlParserInputPtr inputStream = NULL;
28656: int ret;
28657:
28658: if ((ctxt == NULL) || (input == NULL))
28659: return (-1);
28660:
28661: /*
28662: * prepare the parser
28663: */
28664: pctxt = xmlNewParserCtxt();
28665: if (pctxt == NULL)
28666: return (-1);
28667: old_sax = pctxt->sax;
28668: pctxt->sax = sax;
28669: pctxt->userData = user_data;
28670: #if 0
28671: if (options)
28672: xmlCtxtUseOptions(pctxt, options);
28673: #endif
28674: pctxt->linenumbers = 1;
28675:
28676: inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28677: if (inputStream == NULL) {
28678: ret = -1;
28679: goto done;
28680: }
28681: inputPush(pctxt, inputStream);
28682: ctxt->parserCtxt = pctxt;
28683: ctxt->input = input;
28684:
28685: /*
28686: * Plug the validation and launch the parsing
28687: */
28688: plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28689: if (plug == NULL) {
28690: ret = -1;
28691: goto done;
28692: }
28693: ctxt->input = input;
28694: ctxt->enc = enc;
28695: ctxt->sax = pctxt->sax;
28696: ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28697: ret = xmlSchemaVStart(ctxt);
28698:
28699: if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28700: ret = ctxt->parserCtxt->errNo;
28701: if (ret == 0)
28702: ret = 1;
28703: }
28704:
28705: done:
28706: ctxt->parserCtxt = NULL;
28707: ctxt->sax = NULL;
28708: ctxt->input = NULL;
28709: if (plug != NULL) {
28710: xmlSchemaSAXUnplug(plug);
28711: }
28712: /* cleanup */
28713: if (pctxt != NULL) {
28714: pctxt->sax = old_sax;
28715: xmlFreeParserCtxt(pctxt);
28716: }
28717: return (ret);
28718: }
28719:
28720: /**
28721: * xmlSchemaValidateFile:
28722: * @ctxt: a schema validation context
28723: * @filename: the URI of the instance
28724: * @options: a future set of options, currently unused
28725: *
28726: * Do a schemas validation of the given resource, it will use the
28727: * SAX streamable validation internally.
28728: *
28729: * Returns 0 if the document is valid, a positive error code
28730: * number otherwise and -1 in case of an internal or API error.
28731: */
28732: int
28733: xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28734: const char * filename,
28735: int options ATTRIBUTE_UNUSED)
28736: {
28737: int ret;
28738: xmlParserInputBufferPtr input;
28739:
28740: if ((ctxt == NULL) || (filename == NULL))
28741: return (-1);
28742:
28743: input = xmlParserInputBufferCreateFilename(filename,
28744: XML_CHAR_ENCODING_NONE);
28745: if (input == NULL)
28746: return (-1);
28747: ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28748: NULL, NULL);
28749: return (ret);
28750: }
28751:
28752: /**
28753: * xmlSchemaValidCtxtGetParserCtxt:
28754: * @ctxt: a schema validation context
28755: *
28756: * allow access to the parser context of the schema validation context
28757: *
28758: * Returns the parser context of the schema validation context or NULL
28759: * in case of error.
28760: */
28761: xmlParserCtxtPtr
28762: xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28763: {
28764: if (ctxt == NULL)
28765: return(NULL);
28766: return (ctxt->parserCtxt);
28767: }
28768:
28769: #define bottom_xmlschemas
28770: #include "elfgcchack.h"
28771: #endif /* LIBXML_SCHEMAS_ENABLED */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>